mirror of https://gitee.com/bigwinds/arangodb
moved path-related functionality into engine
This commit is contained in:
parent
6e47a19d37
commit
6b9a4a2e7f
|
@ -27,6 +27,7 @@
|
|||
#include "Basics/VelocyPackHelper.h"
|
||||
#include "Basics/WriteLocker.h"
|
||||
#include "Basics/files.h"
|
||||
#include "Random/RandomGenerator.h"
|
||||
#include "RestServer/DatabaseFeature.h"
|
||||
#include "RestServer/DatabasePathFeature.h"
|
||||
#include "StorageEngine/EngineSelectorFeature.h"
|
||||
|
@ -124,9 +125,9 @@ void MMFilesEngine::prepare() {
|
|||
TRI_ASSERT(EngineSelectorFeature::ENGINE = this);
|
||||
|
||||
// get base path from DatabaseServerFeature
|
||||
auto database = application_features::ApplicationServer::getFeature<DatabasePathFeature>("DatabasePath");
|
||||
_basePath = database->directory();
|
||||
_databasePath += database->subdirectoryName("databases") + TRI_DIR_SEPARATOR_CHAR;
|
||||
auto databasePathFeature = application_features::ApplicationServer::getFeature<DatabasePathFeature>("DatabasePath");
|
||||
_basePath = databasePathFeature->directory();
|
||||
_databasePath += databasePathFeature->subdirectoryName("databases") + TRI_DIR_SEPARATOR_CHAR;
|
||||
|
||||
TRI_ASSERT(!_basePath.empty());
|
||||
TRI_ASSERT(!_databasePath.empty());
|
||||
|
@ -255,7 +256,7 @@ void MMFilesEngine::getDatabases(arangodb::velocypack::Builder& result) {
|
|||
// a valid database directory
|
||||
|
||||
// now read data from parameter.json file
|
||||
std::string const file = parametersFile(id);
|
||||
std::string const file = databaseParametersFilename(id);
|
||||
|
||||
if (!TRI_ExistsFile(file.c_str())) {
|
||||
// no parameter.json file
|
||||
|
@ -474,6 +475,8 @@ int MMFilesEngine::prepareDropDatabase(TRI_vocbase_t* vocbase) {
|
|||
|
||||
// perform a physical deletion of the database
|
||||
int MMFilesEngine::dropDatabase(TRI_vocbase_t* vocbase) {
|
||||
_collectionPaths.erase(vocbase->id());
|
||||
|
||||
return dropDatabaseDirectory(databaseDirectory(vocbase->id()));
|
||||
}
|
||||
|
||||
|
@ -516,8 +519,103 @@ int MMFilesEngine::waitUntilDeletion(TRI_voc_tick_t id, bool force) {
|
|||
// and throw only then, so that subsequent collection creation requests will not fail.
|
||||
// the WAL entry for the collection creation will be written *after* the call
|
||||
// to "createCollection" returns
|
||||
void MMFilesEngine::createCollection(TRI_voc_tick_t databaseId, TRI_voc_cid_t id,
|
||||
arangodb::velocypack::Slice const& data) {
|
||||
std::string MMFilesEngine::createCollection(TRI_vocbase_t* vocbase, TRI_voc_cid_t id,
|
||||
arangodb::VocbaseCollectionInfo const& parameters) {
|
||||
std::string const path = databasePath(vocbase);
|
||||
|
||||
// sanity check
|
||||
if (sizeof(TRI_df_header_marker_t) + sizeof(TRI_df_footer_marker_t) > parameters.maximalSize()) {
|
||||
LOG(ERR) << "cannot create datafile '" << parameters.name() << "' in '"
|
||||
<< path << "', maximal size '"
|
||||
<< parameters.maximalSize() << "' is too small";
|
||||
THROW_ARANGO_EXCEPTION(TRI_ERROR_ARANGO_DATAFILE_FULL);
|
||||
}
|
||||
|
||||
if (!TRI_IsDirectory(path.c_str())) {
|
||||
LOG(ERR) << "cannot create collection '" << path << "', path is not a directory";
|
||||
THROW_ARANGO_EXCEPTION(TRI_ERROR_ARANGO_DATADIR_INVALID);
|
||||
}
|
||||
|
||||
std::string const dirname = createCollectionDirectoryName(path, id);
|
||||
registerCollectionPath(vocbase->id(), id, dirname);
|
||||
|
||||
// directory must not exist
|
||||
if (TRI_ExistsFile(dirname.c_str())) {
|
||||
LOG(ERR) << "cannot create collection '" << parameters.name()
|
||||
<< "' in directory '" << dirname << "': directory already exists";
|
||||
THROW_ARANGO_EXCEPTION(TRI_ERROR_ARANGO_COLLECTION_DIRECTORY_ALREADY_EXISTS);
|
||||
}
|
||||
|
||||
// use a temporary directory first. this saves us from leaving an empty
|
||||
// directory behind, and the server refusing to start
|
||||
std::string const tmpname = dirname + ".tmp";
|
||||
|
||||
// create directory
|
||||
std::string errorMessage;
|
||||
long systemError;
|
||||
int res = TRI_CreateDirectory(tmpname.c_str(), systemError, errorMessage);
|
||||
|
||||
if (res != TRI_ERROR_NO_ERROR) {
|
||||
LOG(ERR) << "cannot create collection '" << parameters.name()
|
||||
<< "' in directory '" << path << "': " << TRI_errno_string(res)
|
||||
<< " - " << systemError << " - " << errorMessage;
|
||||
THROW_ARANGO_EXCEPTION(res);
|
||||
}
|
||||
|
||||
TRI_IF_FAILURE("CreateCollection::tempDirectory") { THROW_ARANGO_EXCEPTION(TRI_ERROR_DEBUG); }
|
||||
|
||||
// create a temporary file (.tmp)
|
||||
std::string const tmpfile(
|
||||
arangodb::basics::FileUtils::buildFilename(tmpname.c_str(), ".tmp"));
|
||||
res = TRI_WriteFile(tmpfile.c_str(), "", 0);
|
||||
|
||||
// this file will be renamed to this filename later...
|
||||
std::string const tmpfile2(
|
||||
arangodb::basics::FileUtils::buildFilename(dirname.c_str(), ".tmp"));
|
||||
|
||||
TRI_IF_FAILURE("CreateCollection::tempFile") { THROW_ARANGO_EXCEPTION(TRI_ERROR_DEBUG); }
|
||||
|
||||
if (res != TRI_ERROR_NO_ERROR) {
|
||||
LOG(ERR) << "cannot create collection '" << parameters.name()
|
||||
<< "' in directory '" << path << "': " << TRI_errno_string(res)
|
||||
<< " - " << systemError << " - " << errorMessage;
|
||||
TRI_RemoveDirectory(tmpname.c_str());
|
||||
THROW_ARANGO_EXCEPTION(res);
|
||||
}
|
||||
|
||||
TRI_IF_FAILURE("CreateCollection::renameDirectory") { THROW_ARANGO_EXCEPTION(TRI_ERROR_DEBUG); }
|
||||
|
||||
res = TRI_RenameFile(tmpname.c_str(), dirname.c_str());
|
||||
|
||||
if (res != TRI_ERROR_NO_ERROR) {
|
||||
LOG(ERR) << "cannot create collection '" << parameters.name()
|
||||
<< "' in directory '" << path << "': " << TRI_errno_string(res)
|
||||
<< " - " << systemError << " - " << errorMessage;
|
||||
TRI_RemoveDirectory(tmpname.c_str());
|
||||
THROW_ARANGO_EXCEPTION(res);
|
||||
}
|
||||
|
||||
// now we have the collection directory in place with the correct name and a
|
||||
// .tmp file in it
|
||||
|
||||
// delete .tmp file
|
||||
TRI_UnlinkFile(tmpfile2.c_str());
|
||||
|
||||
// save the parameters file
|
||||
auto doSync = application_features::ApplicationServer::getFeature<DatabaseFeature>("Database")->forceSyncProperties();
|
||||
res = parameters.saveToFile(dirname, doSync);
|
||||
|
||||
if (res != TRI_ERROR_NO_ERROR) {
|
||||
LOG(ERR) << "cannot save collection parameters in directory '" << dirname << "': '" << TRI_last_error() << "'";
|
||||
THROW_ARANGO_EXCEPTION(res);
|
||||
}
|
||||
|
||||
/* TODO: is this necessary?
|
||||
// remove the temporary file
|
||||
std::string tmpfile = dirname + ".tmp";
|
||||
TRI_UnlinkFile(tmpfile.c_str());
|
||||
*/
|
||||
return dirname;
|
||||
}
|
||||
|
||||
// asks the storage engine to drop the specified collection and persist the
|
||||
|
@ -530,6 +628,7 @@ void MMFilesEngine::createCollection(TRI_voc_tick_t databaseId, TRI_voc_cid_t id
|
|||
// to "dropCollection" returns
|
||||
void MMFilesEngine::dropCollection(TRI_voc_tick_t databaseId, TRI_voc_cid_t id,
|
||||
std::function<bool()> const& canRemovePhysically) {
|
||||
unregisterCollectionPath(databaseId, id);
|
||||
}
|
||||
|
||||
// asks the storage engine to rename the collection as specified in the VPack
|
||||
|
@ -540,8 +639,19 @@ void MMFilesEngine::dropCollection(TRI_voc_tick_t databaseId, TRI_voc_cid_t id,
|
|||
// and throw only then, so that subsequent collection creation/rename requests will
|
||||
// not fail. the WAL entry for the rename will be written *after* the call
|
||||
// to "renameCollection" returns
|
||||
void MMFilesEngine::renameCollection(TRI_voc_tick_t databaseId, TRI_voc_cid_t id,
|
||||
arangodb::velocypack::Slice const& data) {
|
||||
void MMFilesEngine::renameCollection(TRI_vocbase_t* vocbase, TRI_voc_cid_t id,
|
||||
std::string const& name) {
|
||||
std::string const path = collectionDirectory(vocbase->id(), id);
|
||||
|
||||
arangodb::VocbaseCollectionInfo info =
|
||||
arangodb::VocbaseCollectionInfo::fromFile(path, vocbase, name, true);
|
||||
|
||||
auto doSync = application_features::ApplicationServer::getFeature<DatabaseFeature>("Database")->forceSyncProperties();
|
||||
int res = info.saveToFile(path, doSync);
|
||||
|
||||
if (res != TRI_ERROR_NO_ERROR) {
|
||||
THROW_ARANGO_EXCEPTION(res);
|
||||
}
|
||||
}
|
||||
|
||||
// asks the storage engine to change properties of the collection as specified in
|
||||
|
@ -862,7 +972,7 @@ int MMFilesEngine::saveDatabaseParameters(TRI_voc_tick_t id,
|
|||
TRI_ASSERT(!name.empty());
|
||||
|
||||
VPackBuilder builder = databaseToVelocyPack(id, name, deleted);
|
||||
std::string const file = parametersFile(id);
|
||||
std::string const file = databaseParametersFilename(id);
|
||||
|
||||
if (!arangodb::basics::VelocyPackHelper::velocyPackToFile(
|
||||
file.c_str(), builder.slice(), true)) {
|
||||
|
@ -893,10 +1003,25 @@ std::string MMFilesEngine::databaseDirectory(TRI_voc_tick_t id) const {
|
|||
return _databasePath + "database-" + std::to_string(id);
|
||||
}
|
||||
|
||||
std::string MMFilesEngine::parametersFile(TRI_voc_tick_t id) const {
|
||||
std::string MMFilesEngine::databaseParametersFilename(TRI_voc_tick_t id) const {
|
||||
return basics::FileUtils::buildFilename(databaseDirectory(id), TRI_VOC_PARAMETER_FILE);
|
||||
}
|
||||
|
||||
std::string MMFilesEngine::collectionDirectory(TRI_voc_tick_t databaseId, TRI_voc_cid_t id) const {
|
||||
auto it = _collectionPaths.find(databaseId);
|
||||
|
||||
if (it == _collectionPaths.end()) {
|
||||
THROW_ARANGO_EXCEPTION_MESSAGE(TRI_ERROR_INTERNAL, "trying to determine directory for unknown collection");
|
||||
}
|
||||
|
||||
auto it2 = (*it).second.find(id);
|
||||
|
||||
if (it2 == (*it).second.end()) {
|
||||
THROW_ARANGO_EXCEPTION_MESSAGE(TRI_ERROR_INTERNAL, "trying to determine directory for unknown collection");
|
||||
}
|
||||
return (*it2).second;
|
||||
}
|
||||
|
||||
/// @brief open an existing database. internal function
|
||||
TRI_vocbase_t* MMFilesEngine::openExistingDatabase(TRI_voc_tick_t id, std::string const& name,
|
||||
bool wasCleanShutdown, bool isUpgrade) {
|
||||
|
@ -1007,3 +1132,31 @@ bool MMFilesEngine::findMaxTickInJournals(std::string const& path) {
|
|||
return iterateFiles(structure.journals);
|
||||
}
|
||||
|
||||
/// @brief create a full directory name for a collection
|
||||
std::string MMFilesEngine::createCollectionDirectoryName(std::string const& basePath, TRI_voc_cid_t cid) {
|
||||
std::string filename("collection-");
|
||||
filename.append(std::to_string(cid));
|
||||
filename.push_back('-');
|
||||
filename.append(std::to_string(RandomGenerator::interval(UINT32_MAX)));
|
||||
|
||||
return arangodb::basics::FileUtils::buildFilename(basePath, filename);
|
||||
}
|
||||
|
||||
void MMFilesEngine::registerCollectionPath(TRI_voc_tick_t databaseId, TRI_voc_cid_t id, std::string const& path) {
|
||||
auto it = _collectionPaths.find(databaseId);
|
||||
|
||||
if (it == _collectionPaths.end()) {
|
||||
it = _collectionPaths.emplace(databaseId, std::unordered_map<TRI_voc_cid_t, std::string>()).first;
|
||||
}
|
||||
(*it).second[id] = path;
|
||||
}
|
||||
|
||||
void MMFilesEngine::unregisterCollectionPath(TRI_voc_tick_t databaseId, TRI_voc_cid_t id) {
|
||||
auto it = _collectionPaths.find(databaseId);
|
||||
|
||||
if (it == _collectionPaths.end()) {
|
||||
return;
|
||||
}
|
||||
(*it).second.erase(id);
|
||||
}
|
||||
|
||||
|
|
|
@ -89,6 +89,9 @@ class MMFilesEngine final : public StorageEngine {
|
|||
// return the path for a database
|
||||
std::string databasePath(TRI_vocbase_t const* vocbase) const override { return databaseDirectory(vocbase->id()); }
|
||||
|
||||
// return the path for a collection
|
||||
std::string collectionPath(TRI_vocbase_t const* vocbase, TRI_voc_cid_t id) const override { return collectionDirectory(vocbase->id(), id); }
|
||||
|
||||
TRI_vocbase_t* openDatabase(arangodb::velocypack::Slice const& parameters, bool isUpgrade) override;
|
||||
|
||||
// database, collection and index management
|
||||
|
@ -127,8 +130,8 @@ class MMFilesEngine final : public StorageEngine {
|
|||
// and throw only then, so that subsequent collection creation requests will not fail.
|
||||
// the WAL entry for the collection creation will be written *after* the call
|
||||
// to "createCollection" returns
|
||||
void createCollection(TRI_voc_tick_t databaseId, TRI_voc_cid_t id,
|
||||
arangodb::velocypack::Slice const& data) override;
|
||||
std::string createCollection(TRI_vocbase_t* vocbase, TRI_voc_cid_t id,
|
||||
arangodb::VocbaseCollectionInfo const& parameters) override;
|
||||
|
||||
// asks the storage engine to drop the specified collection and persist the
|
||||
// deletion info. Note that physical deletion of the collection data must not
|
||||
|
@ -149,8 +152,8 @@ class MMFilesEngine final : public StorageEngine {
|
|||
// and throw only then, so that subsequent collection creation/rename requests will
|
||||
// not fail. the WAL entry for the rename will be written *after* the call
|
||||
// to "renameCollection" returns
|
||||
void renameCollection(TRI_voc_tick_t databaseId, TRI_voc_cid_t id,
|
||||
arangodb::velocypack::Slice const& data) override;
|
||||
void renameCollection(TRI_vocbase_t* vocbase, TRI_voc_cid_t id,
|
||||
std::string const& name) override;
|
||||
|
||||
// asks the storage engine to change properties of the collection as specified in
|
||||
// the VPack Slice object and persist them. If this operation fails
|
||||
|
@ -223,7 +226,9 @@ class MMFilesEngine final : public StorageEngine {
|
|||
bool deleted) const;
|
||||
|
||||
std::string databaseDirectory(TRI_voc_tick_t id) const;
|
||||
std::string parametersFile(TRI_voc_tick_t id) const;
|
||||
std::string databaseParametersFilename(TRI_voc_tick_t id) const;
|
||||
std::string collectionDirectory(TRI_voc_tick_t id, TRI_voc_cid_t cid) const;
|
||||
|
||||
int openDatabases();
|
||||
|
||||
/// @brief open an existing database. internal function
|
||||
|
@ -244,6 +249,12 @@ class MMFilesEngine final : public StorageEngine {
|
|||
/// @brief find the maximum tick in a collection's journals
|
||||
bool findMaxTickInJournals(std::string const& path);
|
||||
|
||||
/// @brief create a full directory name for a collection
|
||||
std::string createCollectionDirectoryName(std::string const& basePath, TRI_voc_cid_t cid);
|
||||
|
||||
void registerCollectionPath(TRI_voc_tick_t databaseId, TRI_voc_cid_t id, std::string const& path);
|
||||
void unregisterCollectionPath(TRI_voc_tick_t databaseId, TRI_voc_cid_t id);
|
||||
|
||||
public:
|
||||
static std::string const EngineName;
|
||||
|
||||
|
@ -254,6 +265,8 @@ class MMFilesEngine final : public StorageEngine {
|
|||
bool _isUpgrade;
|
||||
TRI_voc_tick_t _maxTick;
|
||||
std::vector<std::pair<std::string, std::string>> _deleted;
|
||||
|
||||
std::unordered_map<TRI_voc_tick_t, std::unordered_map<TRI_voc_cid_t, std::string>> _collectionPaths;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -102,8 +102,9 @@ int OtherEngine::waitUntilDeletion(TRI_voc_tick_t id, bool force) {
|
|||
// and throw only then, so that subsequent collection creation requests will not fail.
|
||||
// the WAL entry for the collection creation will be written *after* the call
|
||||
// to "createCollection" returns
|
||||
void OtherEngine::createCollection(TRI_voc_tick_t databaseId, TRI_voc_cid_t id,
|
||||
arangodb::velocypack::Slice const& data) {
|
||||
std::string OtherEngine::createCollection(TRI_vocbase_t* vocbase, TRI_voc_cid_t id,
|
||||
arangodb::VocbaseCollectionInfo const& parameters) {
|
||||
return "test";
|
||||
}
|
||||
|
||||
// asks the storage engine to drop the specified collection and persist the
|
||||
|
@ -126,8 +127,8 @@ void OtherEngine::dropCollection(TRI_voc_tick_t databaseId, TRI_voc_cid_t id,
|
|||
// and throw only then, so that subsequent collection creation/rename requests will
|
||||
// not fail. the WAL entry for the rename will be written *after* the call
|
||||
// to "renameCollection" returns
|
||||
void OtherEngine::renameCollection(TRI_voc_tick_t databaseId, TRI_voc_cid_t id,
|
||||
arangodb::velocypack::Slice const& data) {
|
||||
void OtherEngine::renameCollection(TRI_vocbase_t* vocbase, TRI_voc_cid_t id,
|
||||
std::string const& name) {
|
||||
}
|
||||
|
||||
// asks the storage engine to change properties of the collection as specified in
|
||||
|
|
|
@ -70,6 +70,9 @@ class OtherEngine final : public StorageEngine {
|
|||
// return the path for a database
|
||||
std::string databasePath(TRI_vocbase_t const*) const override { return "none"; }
|
||||
|
||||
// return the path for a collection
|
||||
std::string collectionPath(TRI_vocbase_t const*, TRI_voc_cid_t) const override { return "none"; }
|
||||
|
||||
TRI_vocbase_t* openDatabase(arangodb::velocypack::Slice const& parameters, bool isUpgrade) override {
|
||||
return nullptr;
|
||||
}
|
||||
|
@ -110,8 +113,8 @@ class OtherEngine final : public StorageEngine {
|
|||
// and throw only then, so that subsequent collection creation requests will not fail.
|
||||
// the WAL entry for the collection creation will be written *after* the call
|
||||
// to "createCollection" returns
|
||||
void createCollection(TRI_voc_tick_t databaseId, TRI_voc_cid_t id,
|
||||
arangodb::velocypack::Slice const& data) override;
|
||||
std::string createCollection(TRI_vocbase_t* vocbase, TRI_voc_cid_t id,
|
||||
arangodb::VocbaseCollectionInfo const& parameters) override;
|
||||
|
||||
// asks the storage engine to drop the specified collection and persist the
|
||||
// deletion info. Note that physical deletion of the collection data must not
|
||||
|
@ -132,8 +135,8 @@ class OtherEngine final : public StorageEngine {
|
|||
// and throw only then, so that subsequent collection creation/rename requests will
|
||||
// not fail. the WAL entry for the rename will be written *after* the call
|
||||
// to "renameCollection" returns
|
||||
void renameCollection(TRI_voc_tick_t databaseId, TRI_voc_cid_t id,
|
||||
arangodb::velocypack::Slice const& data) override;
|
||||
void renameCollection(TRI_vocbase_t* vocbase, TRI_voc_cid_t id,
|
||||
std::string const& name) override;
|
||||
|
||||
// asks the storage engine to change properties of the collection as specified in
|
||||
// the VPack Slice object and persist them. If this operation fails
|
||||
|
|
|
@ -33,6 +33,7 @@
|
|||
#include <velocypack/Slice.h>
|
||||
|
||||
namespace arangodb {
|
||||
class VocbaseCollectionInfo;
|
||||
|
||||
class StorageEngine : public application_features::ApplicationFeature {
|
||||
public:
|
||||
|
@ -84,6 +85,9 @@ class StorageEngine : public application_features::ApplicationFeature {
|
|||
|
||||
// return the path for a database
|
||||
virtual std::string databasePath(TRI_vocbase_t const* vocbase) const = 0;
|
||||
|
||||
// return the path for a collection
|
||||
virtual std::string collectionPath(TRI_vocbase_t const* vocbase, TRI_voc_cid_t id) const = 0;
|
||||
|
||||
virtual TRI_vocbase_t* openDatabase(arangodb::velocypack::Slice const& parameters, bool isUpgrade) = 0;
|
||||
|
||||
|
@ -123,8 +127,8 @@ class StorageEngine : public application_features::ApplicationFeature {
|
|||
// and throw only then, so that subsequent collection creation requests will not fail.
|
||||
// the WAL entry for the collection creation will be written *after* the call
|
||||
// to "createCollection" returns
|
||||
virtual void createCollection(TRI_voc_tick_t databaseId, TRI_voc_cid_t id,
|
||||
arangodb::velocypack::Slice const& data) = 0;
|
||||
virtual std::string createCollection(TRI_vocbase_t* vocbase, TRI_voc_cid_t id,
|
||||
arangodb::VocbaseCollectionInfo const& parameters) = 0;
|
||||
|
||||
// asks the storage engine to drop the specified collection and persist the
|
||||
// deletion info. Note that physical deletion of the collection data must not
|
||||
|
@ -145,8 +149,8 @@ class StorageEngine : public application_features::ApplicationFeature {
|
|||
// and throw only then, so that subsequent collection creation/rename requests will
|
||||
// not fail. the WAL entry for the rename will be written *after* the call
|
||||
// to "renameCollection" returns
|
||||
virtual void renameCollection(TRI_voc_tick_t databaseId, TRI_voc_cid_t id,
|
||||
arangodb::velocypack::Slice const& data) = 0;
|
||||
virtual void renameCollection(TRI_vocbase_t* vocbase, TRI_voc_cid_t id,
|
||||
std::string const& name) = 0;
|
||||
|
||||
// asks the storage engine to change properties of the collection as specified in
|
||||
// the VPack Slice object and persist them. If this operation fails
|
||||
|
|
|
@ -47,7 +47,6 @@
|
|||
#include "Indexes/PrimaryIndex.h"
|
||||
#include "Indexes/SkiplistIndex.h"
|
||||
#include "Logger/Logger.h"
|
||||
#include "Random/RandomGenerator.h"
|
||||
#include "RestServer/DatabaseFeature.h"
|
||||
#include "StorageEngine/EngineSelectorFeature.h"
|
||||
#include "StorageEngine/StorageEngine.h"
|
||||
|
@ -1631,19 +1630,6 @@ bool TRI_collection_t::closeDataFiles(std::vector<TRI_datafile_t*> const& files)
|
|||
return result;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief get the full directory name for a collection
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static std::string GetCollectionDirectory(std::string const& path, TRI_voc_cid_t cid) {
|
||||
std::string filename("collection-");
|
||||
filename.append(std::to_string(cid));
|
||||
filename.push_back('-');
|
||||
filename.append(std::to_string(RandomGenerator::interval(UINT32_MAX)));
|
||||
|
||||
return arangodb::basics::FileUtils::buildFilename(path, filename);
|
||||
}
|
||||
|
||||
|
||||
VocbaseCollectionInfo::VocbaseCollectionInfo(CollectionInfo const& other)
|
||||
: _version(TRI_COL_VERSION),
|
||||
|
@ -2248,94 +2234,6 @@ int TRI_collection_t::close() {
|
|||
return TRI_ERROR_NO_ERROR;
|
||||
}
|
||||
|
||||
/// @brief creates a new collection, worker function
|
||||
int TRI_collection_t::createWorker() {
|
||||
StorageEngine* engine = EngineSelectorFeature::ENGINE;
|
||||
std::string const path = engine->databasePath(_vocbase);
|
||||
|
||||
// sanity check
|
||||
if (sizeof(TRI_df_header_marker_t) + sizeof(TRI_df_footer_marker_t) >
|
||||
_info.maximalSize()) {
|
||||
LOG(ERR) << "cannot create datafile '" << _info.name() << "' in '"
|
||||
<< path << "', maximal size '"
|
||||
<< (unsigned int)_info.maximalSize() << "' is too small";
|
||||
return TRI_ERROR_ARANGO_DATAFILE_FULL;
|
||||
}
|
||||
|
||||
if (!TRI_IsDirectory(path.c_str())) {
|
||||
LOG(ERR) << "cannot create collection '" << path << "', path is not a directory";
|
||||
return TRI_ERROR_ARANGO_DATADIR_INVALID;
|
||||
}
|
||||
|
||||
std::string const dirname =
|
||||
GetCollectionDirectory(path, _info.id());
|
||||
|
||||
// directory must not exist
|
||||
if (TRI_ExistsFile(dirname.c_str())) {
|
||||
LOG(ERR) << "cannot create collection '" << _info.name()
|
||||
<< "' in directory '" << dirname << "': directory already exists";
|
||||
return TRI_ERROR_ARANGO_COLLECTION_DIRECTORY_ALREADY_EXISTS;
|
||||
}
|
||||
|
||||
// use a temporary directory first. this saves us from leaving an empty
|
||||
// directory behind, and the server refusing to start
|
||||
std::string const tmpname = dirname + ".tmp";
|
||||
|
||||
// create directory
|
||||
std::string errorMessage;
|
||||
long systemError;
|
||||
int res = TRI_CreateDirectory(tmpname.c_str(), systemError, errorMessage);
|
||||
|
||||
if (res != TRI_ERROR_NO_ERROR) {
|
||||
LOG(ERR) << "cannot create collection '" << _info.name()
|
||||
<< "' in directory '" << path << "': " << TRI_errno_string(res)
|
||||
<< " - " << systemError << " - " << errorMessage;
|
||||
return res;
|
||||
}
|
||||
|
||||
TRI_IF_FAILURE("CreateCollection::tempDirectory") { return TRI_ERROR_DEBUG; }
|
||||
|
||||
// create a temporary file (.tmp)
|
||||
std::string const tmpfile(
|
||||
arangodb::basics::FileUtils::buildFilename(tmpname.c_str(), ".tmp"));
|
||||
res = TRI_WriteFile(tmpfile.c_str(), "", 0);
|
||||
|
||||
// this file will be renamed to this filename later...
|
||||
std::string const tmpfile2(
|
||||
arangodb::basics::FileUtils::buildFilename(dirname.c_str(), ".tmp"));
|
||||
|
||||
TRI_IF_FAILURE("CreateCollection::tempFile") { return TRI_ERROR_DEBUG; }
|
||||
|
||||
if (res != TRI_ERROR_NO_ERROR) {
|
||||
LOG(ERR) << "cannot create collection '" << _info.name()
|
||||
<< "' in directory '" << path << "': " << TRI_errno_string(res)
|
||||
<< " - " << systemError << " - " << errorMessage;
|
||||
TRI_RemoveDirectory(tmpname.c_str());
|
||||
return res;
|
||||
}
|
||||
|
||||
TRI_IF_FAILURE("CreateCollection::renameDirectory") { return TRI_ERROR_DEBUG; }
|
||||
|
||||
res = TRI_RenameFile(tmpname.c_str(), dirname.c_str());
|
||||
|
||||
if (res != TRI_ERROR_NO_ERROR) {
|
||||
LOG(ERR) << "cannot create collection '" << _info.name()
|
||||
<< "' in directory '" << path << "': " << TRI_errno_string(res)
|
||||
<< " - " << systemError << " - " << errorMessage;
|
||||
TRI_RemoveDirectory(tmpname.c_str());
|
||||
return res;
|
||||
}
|
||||
|
||||
// now we have the collection directory in place with the correct name and a
|
||||
// .tmp file in it
|
||||
_path = dirname;
|
||||
|
||||
// delete .tmp file
|
||||
TRI_UnlinkFile(tmpfile2.c_str());
|
||||
|
||||
return TRI_ERROR_NO_ERROR;
|
||||
}
|
||||
|
||||
/// @brief garbage-collect a collection's indexes
|
||||
int TRI_collection_t::cleanupIndexes() {
|
||||
int res = TRI_ERROR_NO_ERROR;
|
||||
|
@ -5436,37 +5334,21 @@ TRI_collection_t* TRI_collection_t::create(
|
|||
}
|
||||
|
||||
parameters.setCollectionId(cid);
|
||||
|
||||
|
||||
auto collection = std::make_unique<TRI_collection_t>(vocbase, parameters);
|
||||
|
||||
int res = collection->createWorker();
|
||||
|
||||
if (res != TRI_ERROR_NO_ERROR) {
|
||||
LOG(ERR) << "cannot create document collection";
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// create document collection
|
||||
res = collection->createInitialIndexes();
|
||||
int res = collection->createInitialIndexes();
|
||||
|
||||
if (res != TRI_ERROR_NO_ERROR) {
|
||||
LOG(ERR) << "cannot initialize document collection";
|
||||
LOG(ERR) << "cannot initialize collection";
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// save the parameters block (within create, no need to lock)
|
||||
bool doSync = application_features::ApplicationServer::getFeature<DatabaseFeature>("Database")->forceSyncProperties();
|
||||
res = parameters.saveToFile(collection->path(), doSync);
|
||||
|
||||
if (res != TRI_ERROR_NO_ERROR) {
|
||||
LOG(ERR) << "cannot save collection parameters in directory '" << collection->path() << "': '" << TRI_last_error() << "'";
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// remove the temporary file
|
||||
std::string tmpfile = collection->path() + ".tmp";
|
||||
TRI_UnlinkFile(tmpfile.c_str());
|
||||
|
||||
|
||||
StorageEngine* engine = EngineSelectorFeature::ENGINE;
|
||||
std::string const path = engine->createCollection(vocbase, cid, parameters);
|
||||
collection->setPath(path);
|
||||
|
||||
return collection.release();
|
||||
}
|
||||
|
||||
|
|
|
@ -366,6 +366,8 @@ struct TRI_collection_t {
|
|||
inline bool useSecondaryIndexes() const { return _useSecondaryIndexes; }
|
||||
|
||||
void useSecondaryIndexes(bool value) { _useSecondaryIndexes = value; }
|
||||
|
||||
void setPath(std::string const& path) { _path = path; }
|
||||
|
||||
/// @brief renames a collection
|
||||
int rename(std::string const& name);
|
||||
|
@ -493,9 +495,6 @@ struct TRI_collection_t {
|
|||
TRI_voc_size_t journalSize,
|
||||
bool isCompactor);
|
||||
|
||||
// worker function for creating a collection
|
||||
int createWorker();
|
||||
|
||||
/// @brief creates the initial indexes for the collection
|
||||
int createInitialIndexes();
|
||||
|
||||
|
|
|
@ -492,12 +492,12 @@ int TRI_vocbase_t::renameCollectionWorker(TRI_vocbase_col_t* collection,
|
|||
std::string const& newName) {
|
||||
// cannot rename a corrupted collection
|
||||
if (collection->status() == TRI_VOC_COL_STATUS_CORRUPTED) {
|
||||
return TRI_set_errno(TRI_ERROR_ARANGO_CORRUPTED_COLLECTION);
|
||||
return TRI_ERROR_ARANGO_CORRUPTED_COLLECTION;
|
||||
}
|
||||
|
||||
// cannot rename a deleted collection
|
||||
if (collection->status() == TRI_VOC_COL_STATUS_DELETED) {
|
||||
return TRI_set_errno(TRI_ERROR_ARANGO_COLLECTION_NOT_FOUND);
|
||||
return TRI_ERROR_ARANGO_COLLECTION_NOT_FOUND;
|
||||
}
|
||||
|
||||
{
|
||||
|
@ -507,28 +507,15 @@ int TRI_vocbase_t::renameCollectionWorker(TRI_vocbase_col_t* collection,
|
|||
auto it = _collectionsByName.find(newName);
|
||||
|
||||
if (it != _collectionsByName.end()) {
|
||||
return TRI_set_errno(TRI_ERROR_ARANGO_DUPLICATE_NAME);
|
||||
return TRI_ERROR_ARANGO_DUPLICATE_NAME;
|
||||
}
|
||||
|
||||
if (collection->status() == TRI_VOC_COL_STATUS_UNLOADED) {
|
||||
// collection is unloaded
|
||||
collection->setName(newName);
|
||||
|
||||
try {
|
||||
arangodb::VocbaseCollectionInfo info =
|
||||
arangodb::VocbaseCollectionInfo::fromFile(collection->path(),
|
||||
this, newName, true);
|
||||
|
||||
bool doSync = application_features::ApplicationServer::getFeature<DatabaseFeature>("Database")->forceSyncProperties();
|
||||
int res = info.saveToFile(collection->path(), doSync);
|
||||
|
||||
if (res != TRI_ERROR_NO_ERROR) {
|
||||
return TRI_set_errno(res);
|
||||
}
|
||||
|
||||
} catch (arangodb::basics::Exception const& e) {
|
||||
return TRI_set_errno(e.code());
|
||||
}
|
||||
StorageEngine* engine = EngineSelectorFeature::ENGINE;
|
||||
engine->renameCollection(this, collection->cid(), newName);
|
||||
// fall-through intentional
|
||||
}
|
||||
else if (collection->status() == TRI_VOC_COL_STATUS_LOADED ||
|
||||
|
@ -538,13 +525,13 @@ int TRI_vocbase_t::renameCollectionWorker(TRI_vocbase_col_t* collection,
|
|||
int res = collection->_collection->rename(newName);
|
||||
|
||||
if (res != TRI_ERROR_NO_ERROR) {
|
||||
return TRI_set_errno(res);
|
||||
return res;
|
||||
}
|
||||
// fall-through intentional
|
||||
}
|
||||
else {
|
||||
// unknown status
|
||||
return TRI_set_errno(TRI_ERROR_INTERNAL);
|
||||
return TRI_ERROR_INTERNAL;
|
||||
}
|
||||
|
||||
#ifdef ARANGODB_ENABLE_MAINTAINER_MODE
|
||||
|
|
Loading…
Reference in New Issue