// ---------------------------------------------------------------------- // File: com_file.cc // Author: Andreas-Joachim Peters - CERN // ---------------------------------------------------------------------- /************************************************************************ * EOS - the CERN Disk Storage System * * Copyright (C) 2011 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 .* ************************************************************************/ #define __STDC_FORMAT_MACROS #include #include "console/ConsoleMain.hh" #include "common/StringTokenizer.hh" #include "common/FileId.hh" #include "common/SymKeys.hh" #include "common/LayoutId.hh" #include "common/Fmd.hh" #include "XrdCl/XrdClFileSystem.hh" #ifdef __APPLE__ #define ECOMM 70 #endif void com_fileinfo_help(); //------------------------------------------------------------------------------ //! Return Fmd from a remote filesystem //! //! @param manager host:port of the server to contact //! @param shexfid hex string of the file id //! @param sfsid string of filesystem id //! @param fmd reference to the Fmd struct to store Fmd //------------------------------------------------------------------------------ int GetRemoteFmdFromLocalDb(const char* manager, const char* shexfid, const char* sfsid, eos::common::FmdHelper& fmd) { if ((!manager) || (!shexfid) || (!sfsid)) { return EINVAL; } int rc = 0; XrdCl::Buffer arg; XrdCl::Buffer* response = 0; XrdCl::XRootDStatus status; XrdOucString fmdquery = "/?fst.pcmd=getfmd&fst.getfmd.fid="; fmdquery += shexfid; fmdquery += "&fst.getfmd.fsid="; fmdquery += sfsid; XrdOucString address = "root://"; address += manager; address += "//dummy"; XrdCl::URL url(address.c_str()); if (!url.IsValid()) { eos_static_err("error=URL is not valid: %s", address.c_str()); return EINVAL; } std::unique_ptr fs(new XrdCl::FileSystem(url)); if (!fs) { eos_static_err("error=failed to get new FS object"); return EINVAL; } arg.FromString(fmdquery.c_str()); status = fs->Query(XrdCl::QueryCode::OpaqueFile, arg, response); if (status.IsOK()) { rc = 0; eos_static_debug("got replica file meta data from server %s for fxid=%s fsid=%s", manager, shexfid, sfsid); } else { rc = ECOMM; eos_static_err("Unable to retrieve meta data from server %s for fxid=%s fsid=%s", manager, shexfid, sfsid); } if (rc) { delete response; return EIO; } if (!strncmp(response->GetBuffer(), "ERROR", 5)) { // remote side couldn't get the record eos_static_info("Unable to retrieve meta data on remote server %s for fxid=%s fsid=%s", manager, shexfid, sfsid); delete response; return ENODATA; } // get the remote file meta data into an env hash XrdOucEnv fmdenv(response->GetBuffer()); if (!eos::common::EnvToFstFmd(fmdenv, fmd)) { int envlen; eos_static_err("Failed to unparse file meta data %s", fmdenv.Env(envlen)); delete response; return EIO; } // very simple check if (fmd.mProtoFmd.fid() != eos::common::FileId::Hex2Fid(shexfid)) { eos_static_err("Uups! Received wrong meta data from remote server - fid " "is %lu instead of %lu !", fmd.mProtoFmd.fid(), eos::common::FileId::Hex2Fid(shexfid)); delete response; return EIO; } delete response; return 0; } //------------------------------------------------------------------------------ // Fileinfo command entry point //------------------------------------------------------------------------------ int com_fileinfo(char* arg1) { XrdOucString savearg = arg1; // Split subcommands eos::common::StringTokenizer subtokenizer(arg1); subtokenizer.GetLine(); XrdOucString path = subtokenizer.GetToken(); XrdOucString option = ""; do { XrdOucString newoption = subtokenizer.GetToken(); if (!newoption.length()) { break; } else { if (newoption == "s") { option += "silent"; } else { option += newoption; } } } while (1); if (wants_help(savearg.c_str())) { com_fileinfo_help(); return 0; } if (!path.length() || path.beginswith("-")) { com_fileinfo_help(); global_retc = EINVAL; return EINVAL; } if ((!path.beginswith("fid:")) && (!path.beginswith("fxid:")) && (!path.beginswith("pid:")) && (!path.beginswith("pxid:")) && (!path.beginswith("inode:"))) { path = abspath(path.c_str()); } XrdOucString in = "mgm.cmd=fileinfo&"; in += "mgm.path="; in += path; if (option.length()) { in += "&mgm.file.info.option="; in += option; } if ((option.find("silent") == STR_NPOS)) { global_retc = output_result(client_command(in)); } return (0); } //------------------------------------------------------------------------------ // Fileinfo help message //------------------------------------------------------------------------------ void com_fileinfo_help() { std::ostringstream oss; oss << "Usage: fileinfo [--path] [--fid] [--fxid] [--size] " << "[--checksum] [--fullpath] [--proxy] [-m] [--env] [-s|--silent]\n" << " Prints information for specified \n" << " = |fid:|fxid:|" << "pid:|pxid:|inode:\n" << "\n" << " fid/fxid - refers to a file identifier\n" << " pid/pxid - refers to a container identifier\n" << " inode - refers to a fuse encoded inode value\n" << "\n" << "Options:\n" << " --path : filters output to show path field\n" << " --fid : filters output to show fid field\n" << " --fxid : filters output to show fxid field\n" << " --size : filters output to show size field\n" << " --checksum : filters output to show checksum field\n" << " --fullpath : adds physical path information to the output\n" << " --proxy : adds proxy information to the output\n" << " --env : prints information in OucEnv format\n" << " -m : prints single-line information in monitoring format\n" << " -s | --silent : silent - used to run as internal command\n" << "\n" << " Remarks:\n" << " Filters stack up and apply only to normal display mode.\n" << " Command also supports JSON output.\n"; std::cout << oss.str() << std::endl; } int com_file(char* arg1) { XrdOucString savearg = arg1; XrdOucString arg = arg1; eos::common::StringTokenizer subtokenizer(arg1); XrdOucString option = ""; XrdOucString path = ""; subtokenizer.GetLine(); XrdOucString cmd = subtokenizer.GetToken(); XrdOucString tmpArg; do { tmpArg = subtokenizer.GetToken(); if (tmpArg.beginswith("-")) { while (tmpArg.replace("-", "")) { } option += tmpArg; } else { path = tmpArg; break; } } while (1); XrdOucString fsid1 = subtokenizer.GetToken(); XrdOucString fsid2 = subtokenizer.GetToken(); XrdOucString fsid3 = subtokenizer.GetToken(); XrdOucString in = "mgm.cmd=file"; if (!path.length()) { goto com_file_usage; } if (wants_help(savearg.c_str())) { goto com_file_usage; } if ((cmd != "drop") && (cmd != "move") && (cmd != "touch") && (cmd != "replicate") && (cmd != "check") && (cmd != "adjustreplica") && (cmd != "info") && (cmd != "layout") && (cmd != "verify") && (cmd != "rename") && (cmd != "copy") && (cmd != "convert") && (cmd != "share") && (cmd != "purge") && (cmd != "version") && (cmd != "versions") && (cmd != "symlink") && (cmd != "tag") && (cmd != "workflow")) { goto com_file_usage; } if ((!path.beginswith("fid:")) && (!path.beginswith("fxid:"))) { path = abspath(path.c_str()); } // convenience function if (cmd == "info") { arg.erase(0, arg.find(" ") + 1); return com_fileinfo((char*) arg.c_str()); } if (cmd == "rename") { if (!path.length() || !fsid1.length()) { goto com_file_usage; } fsid1 = abspath(fsid1.c_str()); in += "&mgm.subcmd=rename"; in += Path2FileDenominator(path) ? "&mgm.file.id=" : "&mgm.path="; in += path; in += "&mgm.file.source="; in += path; in += "&mgm.file.target="; in += fsid1.c_str(); } if (cmd == "symlink") { if (!path.length() || !fsid1.length()) { goto com_file_usage; } in += "&mgm.path="; in += path; in += "&mgm.subcmd=symlink"; in += "&mgm.file.source="; in += path.c_str(); in += "&mgm.file.target="; in += fsid1.c_str(); } if (cmd == "share") { if (!path.length()) { goto com_file_usage; } path = abspath(path.c_str()); in += "&mgm.path="; in += path; in += "&mgm.subcmd=share"; in += "&mgm.file.expires="; unsigned long long expires = (time(NULL) + 28 * 86400); if (fsid1.length()) { expires = time(NULL) + eos::common::StringConversion::GetSizeFromString(fsid1); } char sexpires[1024]; snprintf(sexpires, sizeof(sexpires) - 1, "%llu", expires); in += sexpires; } if (cmd == "touch") { if (!path.length()) { goto com_file_usage; } in += Path2FileDenominator(path) ? "&mgm.file.id=" : "&mgm.path="; in += path; in += "&mgm.subcmd=touch"; if (option.find("n") != STR_NPOS) { in += "&mgm.file.touch.nolayout=true"; } if (option.find("0") != STR_NPOS) { in += "&mgm.file.touch.truncate=true"; } if (option.find("a") != STR_NPOS) { in += "&mgm.file.touch.absorb=true"; } if (option.find("l") != STR_NPOS) { in += "&mgm.file.touch.lockop=lock"; if (fsid1.length()) { in += "&mgm.file.touch.lockop.lifetime="; in += fsid1.c_str(); fsid1 = ""; } if (fsid2.length()) { if ((fsid2 != "app") && (fsid2 != "user")) { goto com_file_usage; } if (fsid2 == "app") { // this is inverted logic because we set the wildcard in += "&mgm.file.touch.wildcard=user"; } else { // this is inverted logic because we set the wildcard in += "&mgm.file.touch.wildcard=app"; } fsid2 = ""; } } if (option.find("u") != STR_NPOS) { in += "&mgm.file.touch.lockop=unlock"; fsid1 = ""; fsid2 = ""; } if (fsid1.length()) { if (fsid1.beginswith("/")) { in += "&mgm.file.touch.hardlinkpath="; in += fsid1.c_str(); } else { in += "&mgm.file.touch.size="; in += fsid1.c_str(); } } if (fsid2.length()) { in += "&mgm.file.touch.checksuminfo="; in += fsid2.c_str(); } } if (cmd == "drop") { if (!path.length() || !fsid1.length()) { goto com_file_usage; } in += "&mgm.subcmd=drop"; in += Path2FileDenominator(path) ? "&mgm.file.id=" : "&mgm.path="; in += path; in += "&mgm.file.fsid="; in += fsid1; if (fsid2 == "-f") { in += "&mgm.file.force=1"; } else { if (fsid2.length()) { goto com_file_usage; } } } if (cmd == "move") { if (!path.length() || !fsid1.length() || !fsid2.length()) { goto com_file_usage; } in += "&mgm.subcmd=move"; in += Path2FileDenominator(path) ? "&mgm.file.id=" : "&mgm.path="; in += path; in += "&mgm.file.sourcefsid="; in += fsid1; in += "&mgm.file.targetfsid="; in += fsid2; } if (cmd == "copy") { XrdOucString dest_path = fsid1; if (!path.length() || !dest_path.length()) { goto com_file_usage; } in += "&mgm.subcmd=copy"; in += Path2FileDenominator(path) ? "&mgm.file.id=" : "&mgm.path="; in += path; if (option.length()) { XrdOucString checkoption = option; checkoption.replace("f", ""); checkoption.replace("s", ""); checkoption.replace("c", ""); if (checkoption.length()) { goto com_file_usage; } in += "&mgm.file.option="; in += option; } dest_path = abspath(dest_path.c_str()); in += "&mgm.file.target="; in += dest_path; } if (cmd == "convert") { XrdOucString layout = fsid1; XrdOucString space = fsid2; XrdOucString plctplcty = fsid3; XrdOucString checksum = subtokenizer.GetToken(); if (!path.length()) { goto com_file_usage; } in += "&mgm.subcmd=convert"; in += Path2FileDenominator(path) ? "&mgm.file.id=" : "&mgm.path="; in += path; if (layout.length()) { in += "&mgm.convert.layout="; in += layout; } if (space.length()) { in += "&mgm.convert.space="; in += space; } if (plctplcty.length()) { in += "&mgm.convert.placementpolicy="; in += plctplcty; } if (checksum.length()) { in += "&mgm.convert.checksum="; in += checksum; } if (option == "sync") { fprintf(stderr, "error: --sync is currently not supported\n"); goto com_file_usage; } if (option == "rewrite") { in += "&mgm.option=rewrite"; } else { if (option.length()) { goto com_file_usage; } } } if (cmd == "replicate") { if (!path.length() || !fsid1.length() || !fsid2.length()) { goto com_file_usage; } in += "&mgm.subcmd=replicate"; in += Path2FileDenominator(path) ? "&mgm.file.id=" : "&mgm.path="; in += path; in += "&mgm.file.sourcefsid="; in += fsid1; in += "&mgm.file.targetfsid="; in += fsid2; } if ((cmd == "purge") || (cmd == "version")) { if (!path.length()) { goto com_file_usage; } in += "&mgm.subcmd="; in += cmd; in += "&mgm.path="; in += path; in += "&mgm.purge.version="; if (fsid1.length()) { in += fsid1; } else { in += "-1"; } } if (cmd == "versions") { if (!path.length()) { goto com_file_usage; } in += "&mgm.subcmd="; in += cmd; in += Path2FileDenominator(path) ? "&mgm.file.id=" : "&mgm.path="; in += path; in += "&mgm.grab.version="; if (fsid1.length()) { in += fsid1; } else { in += "-1"; } } if (cmd == "adjustreplica") { if (!path.length()) { goto com_file_usage; } in += "&mgm.subcmd=adjustreplica"; in += Path2FileDenominator(path) ? "&mgm.file.id=" : "&mgm.path="; in += path; if (fsid1.length()) { in += "&mgm.file.desiredspace="; in += fsid1; if (fsid2.length()) { in += "&mgm.file.desiredsubgroup="; in += fsid2; } } } if (cmd == "layout") { if (!path.length()) { goto com_file_usage; } in += "&mgm.subcmd=layout"; in += Path2FileDenominator(path) ? "&mgm.file.id=" : "&mgm.path="; in += path; if ((fsid1 != "-stripes") && (fsid1 != "-checksum") && (fsid1 != "-type")) { goto com_file_usage; } if (!fsid2.length()) { goto com_file_usage; } if (fsid1 == "-stripes") { in += "&mgm.file.layout.stripes="; in += fsid2; } if (fsid1 == "-checksum") { in += "&mgm.file.layout.checksum="; in += fsid2; } if (fsid1 == "-type") { in += "&mgm.file.layout.type="; in += fsid2; } } if (cmd == "workflow") { if (!path.length()) { goto com_file_usage; } if (!fsid1.length()) { goto com_file_usage; } if (!fsid2.length()) { goto com_file_usage; } in += "&mgm.subcmd=workflow"; in += "&mgm.path="; in += path; in += "&mgm.workflow="; in += fsid1; in += "&mgm.event="; in += fsid2; } if (cmd == "tag") { if (!path.length()) { goto com_file_usage; } in += "&mgm.subcmd=tag"; in += "&mgm.path="; in += path; if ((!fsid1.beginswith("+")) && (!fsid1.beginswith("-")) && (!fsid1.beginswith("~"))) { goto com_file_usage; } in += "&mgm.file.tag.fsid="; in += fsid1; } if (cmd == "verify") { if (!path.length()) { goto com_file_usage; } const char* opt; std::vector options; in += "&mgm.subcmd=verify"; in += "&mgm.path="; in += path; // TODO: all this is silly and should be properly re-written if (fsid1.length()) { if ((fsid1 != "-checksum") && (fsid1 != "-commitchecksum") && (fsid1 != "-commitsize") && (fsid1 != "-commitfmd") && (fsid1 != "-rate") && (fsid1 != "-resync")) { if (fsid1.beginswith("-")) { goto com_file_usage; } in += "&mgm.file.verify.filterid="; in += fsid1; if (fsid2.length()) { options.push_back(fsid2.c_str()); if (fsid3.length()) { options.push_back(fsid3.c_str()); } while ((opt = subtokenizer.GetToken())) { options.push_back(opt); opt = 0; } } } else { options.push_back(fsid1.c_str()); if (fsid2.length()) { options.push_back(fsid2.c_str()); } if (fsid3.length()) { options.push_back(fsid3.c_str()); } while ((opt = subtokenizer.GetToken())) { options.push_back(opt); opt = 0; } } } for (auto& elem : options) { if (elem.length()) { if (elem == "-checksum") { in += "&mgm.file.compute.checksum=1"; } else if (elem == "-commitchecksum") { in += "&mgm.file.commit.checksum=1"; } else if (elem == "-commitsize") { in += "&mgm.file.commit.size=1"; } else if (elem == "-commitfmd") { in += "&mgm.file.commit.fmd=1"; } else if (elem == "-rate") { in += "&mgm.file.verify.rate="; } else if (elem == "-resync") { in += "&mgm.file.resync=1"; } else { goto com_file_usage; } } } } if (cmd == "check") { if (!path.length()) { goto com_file_usage; } in += "&mgm.subcmd=getmdlocation"; in += "&mgm.format=fuse"; in += "&mgm.path="; in += path; XrdOucString option = fsid1; // Eventually disable json format to avoid parsin issues bool old_json = json; if (old_json) { json = false; } XrdOucEnv* result = client_command(in); if (old_json) { json = true; } if (!result) { fprintf(stderr, "error: getmdlocation query failed\n"); global_retc = EINVAL; return (0); } int envlen = 0; std::unique_ptr newresult(new XrdOucEnv(result->Env(envlen))); delete result; if (!envlen) { fprintf(stderr, "error: couldn't get meta data information\n"); global_retc = EIO; return (0); } char* ptr = newresult->Get("mgm.proc.retc"); if (ptr) { int retc_getmdloc = 0; try { retc_getmdloc = std::stoi(ptr); } catch (...) { retc_getmdloc = EINVAL; } if (retc_getmdloc) { fprintf(stderr, "error: failed getmdlocation command, errno=%i", retc_getmdloc); global_retc = retc_getmdloc; return (0); } } XrdOucString ns_path = newresult->Get("mgm.nspath"); XrdOucString checksumtype = newresult->Get("mgm.checksumtype"); XrdOucString checksum = newresult->Get("mgm.checksum"); uint64_t mgm_size = std::stoull(newresult->Get("mgm.size")); bool silent_cmd = ((option.find("%silent") != STR_NPOS) || silent); if (!silent_cmd) { fprintf(stdout, "path=\"%s\" fxid=\"%4s\" size=\"%llu\" nrep=\"%s\" " "checksumtype=\"%s\" checksum=\"%s\"\n", ns_path.c_str(), newresult->Get("mgm.fid0"), (unsigned long long)mgm_size, newresult->Get("mgm.nrep"), checksumtype.c_str(), newresult->Get("mgm.checksum")); } std::string err_label; std::set set_errors; int nrep_online = 0; int i = 0; for (i = 0; i < 255; ++i) { err_label = "none"; XrdOucString repurl = "mgm.replica.url"; repurl += i; XrdOucString repfid = "mgm.fid"; repfid += i; XrdOucString repfsid = "mgm.fsid"; repfsid += i; XrdOucString repbootstat = "mgm.fsbootstat"; repbootstat += i; XrdOucString repfstpath = "mgm.fstpath"; repfstpath += i; if (!newresult->Get(repurl.c_str())) { break; } // Query the FSTs for stripe info XrdCl::StatInfo* stat_info = 0; XrdCl::XRootDStatus status; std::ostringstream oss; oss << "root://" << newresult->Get(repurl.c_str()) << "//dummy"; XrdCl::URL url(oss.str()); if (!url.IsValid()) { fprintf(stderr, "error: URL is not valid: %s", oss.str().c_str()); global_retc = EINVAL; return (0); } // Get XrdCl::FileSystem object std::unique_ptr fs {new XrdCl::FileSystem(url)}; if (!fs) { fprintf(stderr, "error: failed to get new FS object"); global_retc = ECOMM; return (0); } XrdOucString bs = newresult->Get(repbootstat.c_str()); bool down = (bs != "booted"); if (down && ((option.find("%force")) == STR_NPOS)) { err_label = "DOWN"; set_errors.insert(err_label); if (!silent_cmd) { fprintf(stderr, "error: unable to retrieve file meta data from %s " "[ status=%s ]\n", newresult->Get(repurl.c_str()), bs.c_str()); } continue; } // Do a remote stat using XrdCl::FileSystem uint64_t stat_size = std::numeric_limits::max(); XrdOucString statpath = newresult->Get(repfstpath.c_str()); if (!statpath.beginswith("/")) { // base 64 encode this path XrdOucString statpath64; eos::common::SymKey::Base64(statpath, statpath64); statpath = "/#/"; statpath += statpath64; } status = fs->Stat(statpath.c_str(), stat_info); if (!status.IsOK()) { err_label = "STATFAILED"; set_errors.insert(err_label); } else { stat_size = stat_info->GetSize(); } // Free memory delete stat_info; int retc = 0; eos::common::FmdHelper fmd; if ((retc = GetRemoteFmdFromLocalDb(newresult->Get(repurl.c_str()), newresult->Get(repfid.c_str()), newresult->Get(repfsid.c_str()), fmd))) { if (!silent_cmd) { fprintf(stderr, "error: unable to retrieve file meta data from %s [%d]\n", newresult->Get(repurl.c_str()), retc); } err_label = "NOFMD"; set_errors.insert(err_label); } else { const auto& proto_fmd = fmd.mProtoFmd; XrdOucString cx = proto_fmd.checksum().c_str(); for (unsigned int k = (cx.length() / 2); k < SHA256_DIGEST_LENGTH; ++k) { cx += "00"; } std::string disk_cx = proto_fmd.diskchecksum().c_str(); for (unsigned int k = (disk_cx.length() / 2); k < SHA256_DIGEST_LENGTH; ++k) { disk_cx += "00"; } if (eos::common::LayoutId::IsRain(proto_fmd.lid()) == false) { // These checks make sense only for non-rain layouts if (proto_fmd.size() != mgm_size) { err_label = "SIZE"; set_errors.insert(err_label); } else { if (proto_fmd.size() != (unsigned long long) stat_size) { err_label = "FSTSIZE"; set_errors.insert(err_label); } } if (cx != checksum) { err_label = "CHECKSUM"; set_errors.insert(err_label); } uint64_t disk_cx_val = 0ull; try { disk_cx_val = std::stoull(disk_cx.substr(0, 8), nullptr, 16); } catch (...) { // error during conversion } if ((disk_cx.length() > 0) && disk_cx_val && ((disk_cx.length() < 8) || (!cx.beginswith(disk_cx.c_str())))) { err_label = "DISK_CHECKSUM"; set_errors.insert(err_label); } if (!silent_cmd) { fprintf(stdout, "nrep=\"%02d\" fsid=\"%s\" host=\"%s\" fstpath=\"%s\" " "size=\"%llu\" statsize=\"%llu\" checksum=\"%s\" diskchecksum=\"%s\" " "error_label=\"%s\"\n", i, newresult->Get(repfsid.c_str()), newresult->Get(repurl.c_str()), newresult->Get(repfstpath.c_str()), (unsigned long long)proto_fmd.size(), (unsigned long long)(stat_size), cx.c_str(), disk_cx.c_str(), err_label.c_str()); } } else { // For RAIN layouts we only check for block-checksum errors if (proto_fmd.blockcxerror()) { err_label = "BLOCK_XS"; set_errors.insert(err_label); } if (!silent_cmd) { fprintf(stdout, "nrep=\"%02d\" fsid=\"%s\" host=\"%s\" fstpath=\"%s\" " "size=\"%llu\" statsize=\"%llu\" error_label=\"%s\"\n", i, newresult->Get(repfsid.c_str()), newresult->Get(repurl.c_str()), newresult->Get(repfstpath.c_str()), (unsigned long long)proto_fmd.size(), (unsigned long long)(stat_size), err_label.c_str()); } } ++nrep_online; } } int nrep = 0; int stripes = 0; if (newresult->Get("mgm.stripes")) { stripes = atoi(newresult->Get("mgm.stripes")); } if (newresult->Get("mgm.nrep")) { nrep = atoi(newresult->Get("mgm.nrep")); } if (nrep != stripes) { if (set_errors.find("NOFMD") == set_errors.end()) { err_label = "NUM_REPLICAS"; set_errors.insert(err_label); } } if (set_errors.size()) { if ((option.find("%output")) != STR_NPOS) { fprintf(stdout, "INCONSISTENCY %s path=%-32s fxid=%s size=%llu " "stripes=%d nrep=%d nrepstored=%d nreponline=%d " "checksumtype=%s checksum=%s\n", set_errors.begin()->c_str(), path.c_str(), newresult->Get("mgm.fid0"), (unsigned long long) mgm_size, stripes, nrep, i, nrep_online, checksumtype.c_str(), newresult->Get("mgm.checksum")); } if (((option.find("%size") != STR_NPOS) && ((set_errors.find("SIZE") != set_errors.end() || set_errors.find("FSTSIZE") != set_errors.end()))) || ((option.find("%checksum") != STR_NPOS) && ((set_errors.find("CHECKSUM") != set_errors.end()) || (set_errors.find("BLOCK_XS") != set_errors.end()))) || ((option.find("%diskchecksum") != STR_NPOS) && (set_errors.find("DISK_CHECKSUM") != set_errors.end())) || ((option.find("%nrep") != STR_NPOS) && ((set_errors.find("NOFMD") != set_errors.end()) || (set_errors.find("NUM_REPLICAS") != set_errors.end())))) { global_retc = EFAULT; } } return (0); } if (option.length()) { in += "&mgm.file.option="; in += option; } global_retc = output_result(client_command(in)); return (0); com_file_usage: fprintf(stdout, "Usage: file adjustreplica|check|convert|copy|drop|info|layout|move|purge|rename|replicate|verify|version ...\n"); fprintf(stdout, "'[eos] file ..' provides the file management interface of EOS.\n"); fprintf(stdout, "Options:\n"); fprintf(stdout, "file adjustreplica [--nodrop] |fid:|fxid: [space [subgroup]] :\n"); fprintf(stdout, " tries to bring a files with replica layouts to the nominal replica level [ need to be root ]\n"); fprintf(stdout, "file check [|fid:|fxid:] [%%size%%checksum%%nrep%%diskchecksum%%force%%output%%silent] :\n"); fprintf(stdout, " retrieves stat information from the physical replicas and verifies the correctness\n"); fprintf(stdout, " - %%size : return EFAULT if mismatch between the size meta data information\n"); fprintf(stdout, " - %%checksum : return EFAULT if mismatch between the checksum meta data information\n"); fprintf(stdout, " - %%nrep : return EFAULT if mismatch between the layout number of replicas and the existing replicas\n"); fprintf(stdout, " - %%diskchecksum : return EFAULT if mismatch between the disk checksum on the FST and the reference checksum\n"); fprintf(stdout, " - %%silent : suppresses all information for each replica to be printed\n"); fprintf(stdout, " - %%force : forces to get the MD even if the node is down\n"); fprintf(stdout, " - %%output : prints lines with inconsistency information\n"); fprintf(stdout, "file convert [--sync|--rewrite] [|fid:|fxid:] [: | | ] [target-space] [placement-policy] [checksum]:\n"); fprintf(stdout, " convert the layout of a file\n"); fprintf(stdout, " : : specify the target layout and number of stripes\n"); fprintf(stdout, " : specify the hexadecimal layout id \n"); fprintf(stdout, " : specify the name of the attribute sys.conversion. in the parent directory of defining the target layout\n"); fprintf(stdout, " : optional name of the target space or group e.g. default or default.3\n"); fprintf(stdout, " : optional placement policy valid values are 'scattered','hybrid:' and 'gathered:'\n"); fprintf(stdout, " : optional target checksum name. E.g.: md5, adler, etc.\n"); fprintf(stdout, " --sync : run conversion in synchronous mode (by default conversions are asynchronous) - not supported yet\n"); fprintf(stdout, " --rewrite : run conversion rewriting the file as is creating new copies and dropping old\n"); fprintf(stdout, "file copy [-f] [-s] [-c] : synchronous third party copy from to \n"); fprintf(stdout, " : source can be a file or a directory (|fid:|fxid:) \n"); fprintf(stdout, " : destination can be a file (if source is a file) or a directory\n"); fprintf(stdout, " -f : force overwrite\n"); fprintf(stdout, " -s : don't print output\n"); fprintf(stdout, " -c : clone the file (keep ctime, mtime)\n"); fprintf(stdout, "file drop [|fid:|fxid:] [-f] :\n"); fprintf(stdout, " drop the file from - force removes replica without trigger/wait for deletion (used to retire a filesystem) \n"); fprintf(stdout, "file info [|fid:|fxid:] :\n"); fprintf(stdout, " convenience function aliasing to 'fileinfo' command\n"); fprintf(stdout, "file layout |fid:|fxid: -stripes :\n"); fprintf(stdout, " change the number of stripes of a file with replica layout to \n"); fprintf(stdout, "file layout |fid:|fxid: -checksum :\n"); fprintf(stdout, " change the checksum-type of a file to \n"); fprintf(stdout, "file layout |fid:|fxid: -type :\n"); fprintf(stdout, " change the layout-type of a file to (as shown by file info)\n"); fprintf(stdout, "file move [|fid:|fxid:] :\n"); fprintf(stdout, " move the file from to \n"); fprintf(stdout, "file purge [purge-version] :\n"); fprintf(stdout, " keep maximum versions of a file. If not specified apply the attribute definition from sys.versioning.\n"); fprintf(stdout, "file rename [|fid:|fxid:] :\n"); fprintf(stdout, " rename from to name (works for files and directories!).\n"); fprintf(stdout, "file replicate [|fid:|fxid:] :\n"); fprintf(stdout, " replicate file part on to \n"); fprintf(stdout, "file symlink :\n"); fprintf(stdout, " create a symlink with pointing to \n"); fprintf(stdout, "file tag +|-|~ :\n"); fprintf(stdout, " add/remove/unlink a filesystem location to/from a file in the location index - attention this does not move any data!\n"); fprintf(stdout, " unlink keeps the location in the list of deleted files e.g. the location get's a deletion request\n"); fprintf(stdout, "file touch [-a] [-n] [-0] |fid:|fxid: [linkpath|size [hexchecksum]] :\n"); fprintf(stdout, " create/touch a 0-size/0-replica file if does not exist or update modification time of an existing file to the present time\n"); fprintf(stdout, " - by default it uses placement logic - use [-n] to disable placement\n"); fprintf(stdout, " - use 'file touch -0 myfile' to truncate a file\n"); fprintf(stdout, " - use 'file touch -a myfile /external/path' if you want to adopt (absorb) a file which is provied by the hardlink argument - this means that the file disappears from the given hardlink path and is taken under control of an EOS FST\n"); fprintf(stdout, " - provide the optional size argument to preset the size\n"); fprintf(stdout, " - provide the optional linkpath argument to hard- or softlink the touched file to a shared filesystem\n"); fprintf(stdout, " - provide the optional checksum information for a new touched file\n"); fprintf(stdout, "file touch -l |fid:|fxid: [ [=user|app]] :\n"); fprintf(stdout, " - touch a file and create an extended attribute lock with (default 24h)\n"); fprintf(stdout, " - with one can relax the lock owner requirements to be either same user or same app - default is both have to match\n"); fprintf(stdout, " - if the lock is already held by another caller EBUSY is returned\n"); fprintf(stdout, " - if a lock is already held by the caller a second call will extend the liftime as provided\n"); fprintf(stdout, " - use in combination with 'eos -a application' to tag a client with a given application for the lock\n"); fprintf(stdout, "file touch -u |fxid: :\n"); fprintf(stdout, " - remove an extended attribute lock\n"); fprintf(stdout, " - if no lock was not present no error is returned - only an message\n"); fprintf(stdout, " - if the lock is held by someone else EBUSY is returned\n"); fprintf(stdout, " - use in combination with 'eos -a application' to tag a client with a given application for the lock\n"); fprintf(stdout, "file verify |fid:|fxid: [] [-checksum] [-commitchecksum] [-commitsize] [-rate ] : \n"); fprintf(stdout, " verify a file against the disk images\n"); fprintf(stdout, "file verify |fxid: -resync : \n"); fprintf(stdout, " ask all locations to resync their file md records\n"); fprintf(stdout, " : verifies only the replica on \n"); fprintf(stdout, " -checksum : trigger the checksum calculation during the verification process\n"); fprintf(stdout, " -commitchecksum : commit the computed checksum to the MGM\n"); fprintf(stdout, " -commitsize : commit the file size to the MGM\n"); fprintf(stdout, " -rate : restrict the verification speed to per node\n"); fprintf(stdout, "file version [purge-version] :\n"); fprintf(stdout, " create a new version of a file by cloning\n"); fprintf(stdout, " : defines the max. number of versions to keep\n"); fprintf(stdout, "file versions [grab-version] :\n"); fprintf(stdout, " list versions of a file\n"); fprintf(stdout, " grab a version [grab-version] of a file\n"); fprintf(stdout, "\n"); fprintf(stdout, " if not specified it will add a new version without purging any previous version\n"); fprintf(stdout, "file share [lifetime] :\n"); fprintf(stdout, " : path to create a share link\n"); fprintf(stdout, " : validity time of the share link like 1, 1s, 1d, 1w, 1mo, 1y, ... default is 28d\n"); fprintf(stdout, "\n"); fprintf(stdout, "file workflow |fid:|fxid: :\n"); fprintf(stdout, " trigger workflow with event on \n"); fprintf(stdout, "\n"); global_retc = EINVAL; return (0); }