#include "temp.h" #include "errors.h" #include #include namespace NYT { //////////////////////////////////////////////////////////////////////////////// TTempTable::TTempTable( IClientBasePtr client, const TString& prefix, const TYPath& directory, const TCreateOptions& options) : Client_(std::move(client)) { Name_ = CreateTempTable(Client_, prefix, directory, options); } TTempTable::TTempTable(TTempTable::TPrivateConstuctorTag, IClientBasePtr client, TYPath path, const TCreateOptions& options) : Client_(std::move(client)) , Name_(std::move(path)) { Client_->Create(Name_, NT_TABLE, options); } TTempTable::TTempTable(TTempTable&& sourceTable) : Client_(sourceTable.Client_) , Name_(sourceTable.Name_) , Owns_(sourceTable.Owns_) { sourceTable.Owns_ = false; } TTempTable& TTempTable::operator=(TTempTable&& sourceTable) { if (&sourceTable == this) { return *this; } if (Owns_) { RemoveTable(); } Client_ = sourceTable.Client_; Name_ = sourceTable.Name_; Owns_ = sourceTable.Owns_; sourceTable.Owns_ = false; return *this; } TTempTable TTempTable::CreateAutoremovingTable(IClientBasePtr client, TYPath path, const TCreateOptions& options) { return TTempTable(TTempTable::TPrivateConstuctorTag(), std::move(client), std::move(path), options); } void TTempTable::RemoveTable() { if (TConfig::Get()->KeepTempTables) { return; } Client_->Remove(Name_, TRemoveOptions().Force(true)); } TTempTable::~TTempTable() { if (Owns_) { try { RemoveTable(); } catch (...) { } } } TString TTempTable::Name() const & { return Name_; } TString TTempTable::Release() { Y_ASSERT(Owns_); Owns_ = false; return Name_; } //////////////////////////////////////////////////////////////////////////////// TYPath CreateTempTable( const IClientBasePtr& client, const TString& prefix, const TYPath& directory, const TCreateOptions& options) { TYPath result; bool createDirectory = false; if (directory) { result = directory; } else { result = TConfig::Get()->RemoteTempTablesDirectory; // User might override configuration above. // Class used to create directory in such cases if it doesn't exist. // We keep this behaviour. createDirectory = true; } if (result == DefaultRemoteTempTablesDirectory) { result += "/"; result += client->GetParentClient()->WhoAmI().Login; createDirectory = true; } auto resultDirectory = result; result += "/"; result += prefix; result += CreateGuidAsString(); if (!createDirectory) { client->Create(result, NT_TABLE, options); } else { // Directory we are going to create our table in can be missing. // We create it explicitly outside of any transactions, // because concurrent processes might want to create the same directory from other transactions. // // It's unlikely but directory might be removed between directory creation and table creation // we retry attempt if it was failed with path resolution error. const int maxAttempts = 3; for (int i = 0; i < maxAttempts; ++i) { client->GetParentClient()->Create(resultDirectory, NT_MAP, TCreateOptions().Recursive(true).IgnoreExisting(true)); try { client->Create(result, NT_TABLE, options); break; } catch (const TErrorResponse& error) { if (error.IsResolveError()) { if (i < maxAttempts - 1) { continue; } } throw; } } } return result; } //////////////////////////////////////////////////////////////////////////////// } // namespace NYT