in host/cxpslib/requesthandler.cpp [1369:1616]
void RequestHandler::renameFile()
{
SCOPE_GUARD sessionLogoutGuard = MAKE_SCOPE_GUARD(boost::bind(&RequestHandler::sessionLogout, this));
SCOPE_GUARD resetGuard = MAKE_SCOPE_GUARD(boost::bind(&RequestHandler::reset, this));
m_requestTelemetryData.AcquiredRequestType(RequestType_RenameFile);
if (!m_loggedIn) {
m_requestTelemetryData.SetRequestFailure(RequestFailure_NotLoggedIn);
badRequest(AT_LOC, "not logged in\n");
return;
}
if (putFileInProgress(HTTP_REQUEST_RENAMEFILE)) {
return;
}
tagValue_t::iterator oldNameTagValue(m_requestInfo.m_params.find(HTTP_PARAM_TAG_OLDNAME));
if (m_requestInfo.m_params.end() == oldNameTagValue) {
m_requestTelemetryData.SetRequestFailure(RequestFailure_MissingOldName);
throw ERROR_EXCEPTION << "missing oldname";
}
if ((*oldNameTagValue).second.empty()) {
m_requestTelemetryData.SetRequestFailure(RequestFailure_MissingOldName);
throw ERROR_EXCEPTION << "missing original file name";
}
// Note that the file type determiniation would also work for all kinds of new file name as well.
// TODO-SanKumar-1711: Assert FileTypeDetermined(OldFile) == FileTypeDetermined(NewFile)
m_requestTelemetryData.AcquiredFilePath(oldNameTagValue->second);
tagValue_t::iterator newNameTagValue(m_requestInfo.m_params.find(HTTP_PARAM_TAG_NEWNAME));
if (m_requestInfo.m_params.end() == newNameTagValue) {
m_requestTelemetryData.SetRequestFailure(RequestFailure_MissingNewName);
throw ERROR_EXCEPTION << " missing newname";
}
if ((*newNameTagValue).second.empty()) {
m_requestTelemetryData.SetRequestFailure(RequestFailure_MissingNewName);
throw ERROR_EXCEPTION << "missing new file name";
}
std::string ver;
if (!getVersion(ver)) {
m_requestTelemetryData.SetRequestFailure(RequestFailure_MissingVer);
badRequest(AT_LOC, "missing ver");
return;
}
tagValue_t::iterator idTagValue(m_requestInfo.m_params.find(HTTP_PARAM_TAG_ID));
if (m_requestInfo.m_params.end() == idTagValue) {
m_requestTelemetryData.SetRequestFailure(RequestFailure_MissingId);
throw ERROR_EXCEPTION << "missing id";
}
tagValue_t::iterator reqIdTagValue(m_requestInfo.m_params.find(HTTP_PARAM_TAG_REQ_ID));
if (m_requestInfo.m_params.end() == reqIdTagValue) {
m_requestTelemetryData.SetRequestFailure(RequestFailure_MissingReqId);
throw ERROR_EXCEPTION << "missing reqid";
}
boost::uint32_t reqId = boost::lexical_cast<boost::uint32_t>((*reqIdTagValue).second);
if (reqId <= m_reqId) {
m_requestTelemetryData.SetRequestFailure(RequestFailure_InvalidReqId);
throw ERROR_EXCEPTION << "invalid request id";
}
logRequestBegin();
if (!Authentication::verifyRenameFileId(m_hostId,
m_serverOptions->password(),
HTTP_METHOD_GET,
HTTP_REQUEST_RENAMEFILE,
m_cnonce,
m_sessionId,
m_snonce,
(*oldNameTagValue).second,
(*newNameTagValue).second,
ver,
reqId,
(*idTagValue).second)) {
m_requestTelemetryData.SetRequestFailure(RequestFailure_VerifRenFile);
std::string msg("invalid id for host: ");
msg += m_hostId;
msg += " request: ";
msg += HTTP_REQUEST_RENAMEFILE;
badRequest(AT_LOC, msg.c_str());
return;
}
m_reqId = reqId;
m_requestTelemetryData.StartingOp();
tagValue_t::iterator appendMTimeUtcTagValue(m_requestInfo.m_params.find(HTTP_PARAM_TAG_APPENDMTIMEUTC));
bool shouldAppendMTimeInUtc =
(appendMTimeUtcTagValue != m_requestInfo.m_params.end()) &&
(appendMTimeUtcTagValue->second == "1");
tagValue_t::iterator finalPathsTagValue(m_requestInfo.m_params.find(HTTP_PARAM_TAG_FINAL_PATHS));
std::replace((*oldNameTagValue).second.begin(), (*oldNameTagValue).second.end(), '\\', '/');
std::replace((*newNameTagValue).second.begin(), (*newNameTagValue).second.end(), '\\', '/');
std::string sessionId;
try {
boost::filesystem::path oldFullNamePath;
getFullPathName((*oldNameTagValue).second, oldFullNamePath);
extendedLengthPath_t extOldName(ExtendedLengthPath::name(oldFullNamePath.string()));
if (!boost::filesystem::exists(extOldName)) {
std::string str(oldFullNamePath.string() + "not found");
sendError(ResponseCode::RESPONSE_NOT_FOUND, str.data(), str.length());
m_requestTelemetryData.SuccessfullyResponded(); // Not a critical error.
logRequestNotFound();
} else {
std::string sessionId = g_sessionTracker->checkOpenFile(oldFullNamePath, false, true);
if (!sessionId.empty()) {
m_requestTelemetryData.SetRequestFailure(RequestFailure_FileOpenInSession);
m_putFileInfo.m_name.clear(); // this prevents this session from deleting the putfile while another session is using it
throw ERROR_EXCEPTION << "(sid: " << m_sessionId << ") rename file "
<< (*oldNameTagValue).second << " currently opened by session "
<< sessionId << " can not be renamed at this time";
}
bool compress = compressFile((*newNameTagValue).second);
if (compress) {
(*newNameTagValue).second += ".gz";
std::string::size_type idx = (*newNameTagValue).second.find("tmp_");
if (std::string::npos != idx) {
(*newNameTagValue).second.erase(idx, 4);
}
}
if (m_requestInfo.m_params.end() != finalPathsTagValue) {
if ((*finalPathsTagValue).second.empty()) {
m_requestTelemetryData.SetRequestFailure(RequestFailure_MissingPathsTag);
throw ERROR_EXCEPTION << "missing values for paths tag";
}
// taking over final rename so need to remove tmp_ prefix if it exists
// note if inline compression on, that will already have removed the tmp_
// so only need to check if not inline compress
if (!compress) {
std::string::size_type idx = (*newNameTagValue).second.find("tmp_");
if (std::string::npos != idx) {
(*newNameTagValue).second.erase(idx, 4);
}
}
// need to prepend completed_ediff and append time if a diff file
std::string::size_type idx = (*newNameTagValue).second.find("completed_diff_");
if (std::string::npos != idx) {
boost::filesystem::path tmpNewPath((*newNameTagValue).second);
std::string tmpNewName(tmpNewPath.filename().string());
tmpNewName.insert(0, "completed_ediff");
std::time_t mtime = last_write_time(extOldName);
idx = tmpNewName.find(".dat");
if (std::string::npos == idx) {
// todo: is this good enough .dat should always be there for this file
idx = tmpNewName.size();
}
tmpNewName.insert(idx, "_");
++idx;
tmpNewName.insert(idx, boost::lexical_cast<std::string>(mtime));
if (tmpNewPath.has_parent_path()) {
tmpNewPath.remove_filename();
tmpNewPath /= tmpNewName;
} else {
tmpNewPath = tmpNewName;
}
(*newNameTagValue).second = tmpNewPath.string();
shouldAppendMTimeInUtc = false; // since already appended
}
}
if (shouldAppendMTimeInUtc) {
std::time_t mtime = last_write_time(extOldName);
boost::filesystem::path tmpNewPath(newNameTagValue->second);
std::string tmpNewName(tmpNewPath.stem().string());
tmpNewName += '_';
tmpNewName += boost::lexical_cast<std::string>(mtime);
tmpNewName += tmpNewPath.extension().string();
if (tmpNewPath.has_parent_path()) {
tmpNewPath.remove_filename();
tmpNewPath /= tmpNewName;
}
else {
tmpNewPath = tmpNewName;
}
newNameTagValue->second = tmpNewPath.string();
}
boost::filesystem::path newFullNamePath;
// do not perform allowed_dir check in case finalPathsTagValue is set; will be performed later
getFullPathName((*newNameTagValue).second, newFullNamePath, m_requestInfo.m_params.end() == finalPathsTagValue);
extendedLengthPath_t extNewName(ExtendedLengthPath::name(newFullNamePath.string()));
if (m_requestInfo.m_params.end() == finalPathsTagValue) {
// boost rename is too restrictive, so for case were rename
// should be allowed, need to delete new name if it exists
if (boost::filesystem::exists(extNewName)
&& boost::filesystem::is_regular_file(extNewName)) {
boost::filesystem::remove(extNewName);
}
boost::filesystem::rename(extOldName, extNewName);
} else {
RenameFinal::rename(extOldName,
extNewName,
m_putFileInfo.m_createDirs || m_serverOptions->createPaths(),
(*finalPathsTagValue).second,
m_serverOptions->copyOnRenameLinkFailure(),
MAKE_GET_FULL_PATH_CALLBACK_MEM_FUN(&RequestHandler::getFullPathNameWrapper, this),
MAKE_CLOSE_FILE_CALLBACK_MEM_FUN(&RequestHandler::closeFileCallback, this));
// FIXME: if clustered, need to update the other cluster nodes too
updateRpoMonitor(extOldName);
}
if (GetCSMode() == CS_MODE_RCM)
{
std::string fileName = extNewName.filename().string();
// Only updating the monitor.txt file in case of diff, tso and tag files
if (fileName.find("_diff_") != std::string::npos ||
fileName.find("_tso_") != std::string::npos ||
fileName.find("_tag_") != std::string::npos)
{
updateRpoMonitor(extNewName);
}
}
sendSuccess();
logRequestDone();
}
} catch (std::exception const & e) {
m_requestTelemetryData.SetRequestFailure(RequestFailure_RenameFileFailed);
throw ERROR_EXCEPTION << (*oldNameTagValue).second <<" to " << (*newNameTagValue).second << " failed: " << e.what();
}
m_requestTelemetryData.CompletingOp();
sessionLogoutGuard.dismiss();
m_requestInfo.m_completedCallback();
}