// ----------------------------------------------------------------------
// File: Schedule2Delete.cc
// Author: Andreas-Joachim Peters - CERN
// ----------------------------------------------------------------------
/************************************************************************
* EOS - the CERN Disk Storage System *
* Copyright (C) 2018 CERN/Switzerland *
* *
* This program is free software: you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation, either version 3 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program. If not, see .*
************************************************************************/
#include "common/Logging.hh"
#include "common/BufferManager.hh"
#include "namespace/Prefetcher.hh"
#include "namespace/interface/IView.hh"
#include "namespace/interface/IFileMD.hh"
#include "namespace/interface/IFsView.hh"
#include "mgm/Stat.hh"
#include "mgm/XrdMgmOfs.hh"
#include "mgm/Macros.hh"
#include "mgm/FsView.hh"
#include "mgm/Messaging.hh"
#include "proto/Delete.pb.h"
#include
#include
#include "XrdOuc/XrdOucEnv.hh"
//------------------------------------------------------------------------------
// Schedule deletion for FSTs
//------------------------------------------------------------------------------
int
XrdMgmOfs::Schedule2Delete(const char* path,
const char* ininfo,
XrdOucEnv& env,
XrdOucErrInfo& error,
eos::common::VirtualIdentity& vid,
const XrdSecEntity* client)
{
static const char* epname = "Schedule2Delete";
REQUIRE_SSS_OR_LOCAL_AUTH;
ACCESSMODE_W;
MAYSTALL;
MAYREDIRECT;
EXEC_TIMING_BEGIN("Scheduled2Delete");
gOFS->MgmStats.Add("Schedule2Delete", 0, 0, 1);
const std::string nodename = (env.Get("mgm.target.nodename") ?
env.Get("mgm.target.nodename") : "-none-");
eos_static_debug("msg=\"handle query\" nodename=%s", nodename.c_str());
// Retrieve filesystems from the given node and save the following info
// in the tuple below
std::list> fs_info;
{
eos::common::RWMutexReadLock lock(FsView::gFsView.ViewMutex);
if (!FsView::gFsView.mNodeView.count(nodename)) {
eos_static_warning("msg=\"node is not configured\" name=%s",
nodename.c_str());
return Emsg(epname, error, EINVAL, "schedule delete - unknown node "
"[EINVAL]", nodename.c_str());
}
for (auto set_it = FsView::gFsView.mNodeView[nodename]->begin();
set_it != FsView::gFsView.mNodeView[nodename]->end(); ++set_it) {
auto* fs = FsView::gFsView.mIdView.lookupByID(*set_it);
// Don't send messages if filesystem is down, booting or offline
if ((fs == nullptr) ||
(fs->GetActiveStatus() == eos::common::ActiveStatus::kOffline) ||
(fs->GetConfigStatus() <= eos::common::ConfigStatus::kOff) ||
(fs->GetStatus() != eos::common::BootStatus::kBooted)) {
continue;
}
fs_info.emplace_back(fs->GetId(), fs->GetPath(), fs->GetQueue());
}
}
size_t total_del = 0;
eos::fst::DeletionsProto del_fst;
// Go through each filesystem and collect unlinked files
for (const auto& info : fs_info) {
eos::fst::DeletionsFsProto* del = del_fst.mutable_fs()->Add();
unsigned long fsid = std::get<0>(info);
std::string fs_path = std::get<1>(info);
std::string fs_queue = std::get<2>(info);
std::unordered_set set_fids;
// Collect all the file ids to be deleted from the current filesystem
for (auto it_fid = gOFS->eosFsView->getUnlinkedFileList(fsid);
(it_fid && it_fid->valid()); it_fid->next()) {
set_fids.insert(it_fid->getElement());
}
del->set_fsid(fsid);
del->set_path(fs_path);
// Add file ids to the deletion message
for (auto fid : set_fids) {
del->mutable_fids()->Add(fid);
++total_del;
if (total_del > 1024) {
break;
}
}
if (total_del > 1024) {
break;
}
}
if (total_del) {
if (EOS_LOGS_DEBUG) {
std::string json;
(void) google::protobuf::util::MessageToJsonString(del_fst, &json);
eos_static_debug("msg=\"query2delete reponse\" data=\"%s\"", json.c_str());
}
#if GOOGLE_PROTOBUF_VERSION < 3004000
const auto sz = del_fst.ByteSize();
#else
const auto sz = del_fst.ByteSizeLong();
#endif
const uint32_t aligned_sz = eos::common::GetPowerCeil(sz, 2 * eos::common::KB);
XrdOucBuffer* buff = mXrdBuffPool.Alloc(aligned_sz);
if (buff == nullptr) {
eos_static_err("msg=\"requested buffer allocation size too big\" "
"req_sz=%llu max_sz=%i", sz, mXrdBuffPool.MaxSize());
error.setErrInfo(ENOMEM, "requested buffer too big");
EXEC_TIMING_END("Scheduled2Delete");
return SFS_ERROR;
}
google::protobuf::io::ArrayOutputStream aos((void*)buff->Buffer(), sz);
buff->SetLen(sz);
if (!del_fst.SerializeToZeroCopyStream(&aos)) {
eos_static_err("%s", "msg=\"failed protobuf serialization\"");
error.setErrInfo(EINVAL, "failed protobuf serialization\"");
EXEC_TIMING_END("Scheduled2Delete");
return SFS_ERROR;
}
error.setErrInfo(buff->DataLen(), buff);
gOFS->MgmStats.Add("Scheduled2Delete", 0, 0, total_del);
} else {
error.setErrInfo(0, "");
}
EXEC_TIMING_END("Scheduled2Delete");
return SFS_DATA;
}