diff --git a/arangod/Cluster/ClusterInfo.cpp b/arangod/Cluster/ClusterInfo.cpp index 7fc1dad207..4faf0aab8b 100644 --- a/arangod/Cluster/ClusterInfo.cpp +++ b/arangod/Cluster/ClusterInfo.cpp @@ -1437,7 +1437,7 @@ int ClusterInfo::ensureIndexCoordinator( } // now create a new index - c->toVelocyPack(*collectionBuilder); + c->toVelocyPack(*collectionBuilder, false); } VPackSlice const collectionSlice = collectionBuilder->slice(); diff --git a/arangod/RestHandler/RestReplicationHandler.cpp b/arangod/RestHandler/RestReplicationHandler.cpp index 4736b51cdb..7da8ca5eff 100644 --- a/arangod/RestHandler/RestReplicationHandler.cpp +++ b/arangod/RestHandler/RestReplicationHandler.cpp @@ -1333,7 +1333,7 @@ int RestReplicationHandler::createCollection(VPackSlice const& slice, TRI_ASSERT(col->isSystem() == (name[0] == '_')); TRI_ASSERT(col->indexBuckets() == arangodb::basics::VelocyPackHelper::getNumericValue( - slice, "indexBuckets", DatabaseFeature::DefaultIndexBuckets)); + slice, "indexBuckets", DatabaseFeature::defaultIndexBuckets())); #ifdef ARANGODB_ENABLE_MAINTAINER_MODE TRI_voc_cid_t planId = 0; VPackSlice const planIdSlice = slice.get("planId"); diff --git a/arangod/RestServer/DatabaseFeature.cpp b/arangod/RestServer/DatabaseFeature.cpp index 7d62690dea..b6ba8e875b 100644 --- a/arangod/RestServer/DatabaseFeature.cpp +++ b/arangod/RestServer/DatabaseFeature.cpp @@ -64,8 +64,6 @@ using namespace arangodb::application_features; using namespace arangodb::basics; using namespace arangodb::options; -uint32_t const DatabaseFeature::DefaultIndexBuckets = 8; - DatabaseFeature* DatabaseFeature::DATABASE = nullptr; /// @brief database manager thread main loop diff --git a/arangod/RestServer/DatabaseFeature.h b/arangod/RestServer/DatabaseFeature.h index 5343cfe14e..f089818910 100644 --- a/arangod/RestServer/DatabaseFeature.h +++ b/arangod/RestServer/DatabaseFeature.h @@ -78,6 +78,9 @@ class DatabaseFeature final : public application_features::ApplicationFeature { int recoveryDone(); public: + + static constexpr uint32_t defaultIndexBuckets() { return 8; } + /// @brief get the ids of all local coordinator databases std::vector getDatabaseIdsCoordinator(bool includeSystem); std::vector getDatabaseIds(bool includeSystem); @@ -168,9 +171,6 @@ class DatabaseFeature final : public application_features::ApplicationFeature { /// @brief lock for serializing the creation of databases arangodb::Mutex _databaseCreateLock; - - public: - static uint32_t const DefaultIndexBuckets; }; } diff --git a/arangod/StorageEngine/MMFilesEngine.cpp b/arangod/StorageEngine/MMFilesEngine.cpp index 50e9d94855..c5c04b1642 100644 --- a/arangod/StorageEngine/MMFilesEngine.cpp +++ b/arangod/StorageEngine/MMFilesEngine.cpp @@ -458,28 +458,15 @@ int MMFilesEngine::getCollectionsAndIndexes(TRI_vocbase_t* vocbase, int res = TRI_ERROR_NO_ERROR; try { - arangodb::VocbaseCollectionInfo info = loadCollectionInfo(vocbase, "", directory, true); + std::unique_ptr collection(loadCollectionInfo(vocbase, directory)); - if (info.deleted()) { - _deleted.emplace_back(std::make_pair(info.name(), directory)); + if (collection->deleted()) { + _deleted.emplace_back(std::make_pair(collection->name(), directory)); continue; } - if (info.version() < VocbaseCollectionInfo::version() && !isUpgrade) { - // collection is too "old" - LOG(ERR) << "collection '" << info.name() - << "' has a too old version. Please start the server " - "with the --database.auto-upgrade option."; - - return TRI_ERROR_FAILED; - } - // add collection info - result.openObject(); - info.toVelocyPack(result); - result.add("path", VPackValue(directory)); - result.close(); - + collection->toVelocyPack(result, true); } catch (arangodb::basics::Exception const& e) { std::string tmpfile = FileUtils::buildFilename(directory, ".tmp"); @@ -1216,36 +1203,43 @@ TRI_vocbase_t* MMFilesEngine::openExistingDatabase(TRI_voc_tick_t id, std::strin auto vocbase = std::make_unique(TRI_VOCBASE_TYPE_NORMAL, id, name); // scan the database path for collections - VPackBuilder builder; - int res = getCollectionsAndIndexes(vocbase.get(), builder, wasCleanShutdown, isUpgrade); + try { + VPackBuilder builder; + int res = getCollectionsAndIndexes(vocbase.get(), builder, wasCleanShutdown, isUpgrade); - if (res != TRI_ERROR_NO_ERROR) { - THROW_ARANGO_EXCEPTION(res); - } - - VPackSlice slice = builder.slice(); - TRI_ASSERT(slice.isArray()); + if (res != TRI_ERROR_NO_ERROR) { + THROW_ARANGO_EXCEPTION(res); + } + + VPackSlice slice = builder.slice(); + TRI_ASSERT(slice.isArray()); - for (auto const& it : VPackArrayIterator(slice)) { - // we found a collection that is still active - TRI_ASSERT(!it.get("id").isNone() || !it.get("cid").isNone()); - arangodb::LogicalCollection* collection = StorageEngine::registerCollection(ConditionalWriteLocker::DoLock(), vocbase.get(), it); + for (auto const& it : VPackArrayIterator(slice)) { + // we found a collection that is still active + TRI_ASSERT(!it.get("id").isNone() || !it.get("cid").isNone()); + arangodb::LogicalCollection* collection = StorageEngine::registerCollection(ConditionalWriteLocker::DoLock(), vocbase.get(), it); - registerCollectionPath(vocbase->id(), collection->cid(), collection->path()); + registerCollectionPath(vocbase->id(), collection->cid(), collection->path()); - if (!wasCleanShutdown) { - // iterating markers may be time-consuming. we'll only do it if - // we have to - findMaxTickInJournals(collection->path()); + if (!wasCleanShutdown) { + // iterating markers may be time-consuming. we'll only do it if + // we have to + findMaxTickInJournals(collection->path()); + } + + LOG(DEBUG) << "added document collection '" << collection->name() << "'"; } - LOG(DEBUG) << "added document collection '" << collection->name() << "'"; + // start cleanup thread + startCleanup(vocbase.get()); + + return vocbase.release(); + } catch (std::exception const& ex) { + LOG(ERR) << "error while opening database: " << ex.what(); + throw; + } catch (...) { + LOG(ERR) << "error while opening database: unknown exception"; } - - // start cleanup thread - startCleanup(vocbase.get()); - - return vocbase.release(); } /// @brief physically erases the database directory @@ -1336,7 +1330,7 @@ void MMFilesEngine::saveCollectionInfo(TRI_vocbase_t* vocbase, std::string const filename = collectionParametersFilename(vocbase->id(), id); VPackBuilder builder; - parameters->toVelocyPack(builder); + parameters->toVelocyPack(builder, false); TRI_ASSERT(id != 0); @@ -1350,8 +1344,7 @@ void MMFilesEngine::saveCollectionInfo(TRI_vocbase_t* vocbase, } } -VocbaseCollectionInfo MMFilesEngine::loadCollectionInfo(TRI_vocbase_t* vocbase, - std::string const& collectionName, std::string const& path, bool versionWarning) { +LogicalCollection* MMFilesEngine::loadCollectionInfo(TRI_vocbase_t* vocbase, std::string const& path) { // find parameter file std::string filename = arangodb::basics::FileUtils::buildFilename(path, parametersFilename()); @@ -1372,8 +1365,6 @@ VocbaseCollectionInfo MMFilesEngine::loadCollectionInfo(TRI_vocbase_t* vocbase, THROW_ARANGO_EXCEPTION(TRI_ERROR_ARANGO_ILLEGAL_PARAMETER_FILE); } - - if (filename.substr(filename.size() - 4, 4) == ".tmp") { // we got a tmp file. Now try saving the original file arangodb::basics::VelocyPackHelper::velocyPackToFile(filename.substr(0, filename.size() - 4), @@ -1389,27 +1380,16 @@ VocbaseCollectionInfo MMFilesEngine::loadCollectionInfo(TRI_vocbase_t* vocbase, } } - VPackBuilder bx; - bx.openObject(); - bx.add("isSystem", VPackValue(isSystemValue)); - bx.add("path", VPackValue(path)); - bx.close(); - VPackSlice isSystem = bx.slice(); + VPackBuilder patch; + patch.openObject(); + patch.add("isSystem", VPackValue(isSystemValue)); + patch.add("path", VPackValue(path)); + patch.close(); + VPackSlice isSystem = patch.slice(); VPackBuilder b2 = VPackCollection::merge(slice, isSystem, false); slice = b2.slice(); - VocbaseCollectionInfo info(vocbase, collectionName, slice, isSystemValue); - - // warn about wrong version of the collection - if (versionWarning && info.version() < VocbaseCollectionInfo::version()) { - if (info.name()[0] != '\0') { - // only warn if the collection version is older than expected, and if it's - // not a shape collection - LOG(WARN) << "collection '" << info.name() - << "' has an old version and needs to be upgraded."; - } - } - return info; + return new LogicalCollection(vocbase, slice); } /// @brief remove data of expired compaction blockers diff --git a/arangod/StorageEngine/MMFilesEngine.h b/arangod/StorageEngine/MMFilesEngine.h index 2c39b00e08..1e513e48c1 100644 --- a/arangod/StorageEngine/MMFilesEngine.h +++ b/arangod/StorageEngine/MMFilesEngine.h @@ -319,8 +319,7 @@ class MMFilesEngine final : public StorageEngine { arangodb::LogicalCollection const* parameters, bool forceSync) const; - VocbaseCollectionInfo loadCollectionInfo(TRI_vocbase_t* vocbase, - std::string const& collectionName, std::string const& path, bool versionWarning); + LogicalCollection* loadCollectionInfo(TRI_vocbase_t* vocbase, std::string const& path); // start the cleanup thread for the database int startCleanup(TRI_vocbase_t* vocbase); diff --git a/arangod/StorageEngine/StorageEngine.h b/arangod/StorageEngine/StorageEngine.h index 3043b7f03f..9080b696da 100644 --- a/arangod/StorageEngine/StorageEngine.h +++ b/arangod/StorageEngine/StorageEngine.h @@ -37,7 +37,6 @@ namespace arangodb { class LogicalCollection; class PhysicalCollection; -class VocbaseCollectionInfo; class StorageEngine : public application_features::ApplicationFeature { public: diff --git a/arangod/V8Server/v8-collection.cpp b/arangod/V8Server/v8-collection.cpp index 33b32711e5..1edebb8a8b 100644 --- a/arangod/V8Server/v8-collection.cpp +++ b/arangod/V8Server/v8-collection.cpp @@ -1229,7 +1229,7 @@ static void JS_PropertiesVocbaseCol( try { VPackBuilder infoBuilder; - collection->toVelocyPack(infoBuilder); + collection->toVelocyPack(infoBuilder, false); // now log the property changes res = TRI_ERROR_NO_ERROR; @@ -2436,7 +2436,7 @@ static void JS_VersionVocbaseCol( TRI_V8_THROW_EXCEPTION_INTERNAL("cannot extract collection"); } - TRI_V8_RETURN(v8::Number::New(isolate, 5)); // TODO: fix hard-coded version number + TRI_V8_RETURN(v8::Number::New(isolate, collection->version())); TRI_V8_TRY_CATCH_END } diff --git a/arangod/V8Server/v8-vocbase.cpp b/arangod/V8Server/v8-vocbase.cpp index e600167c61..48f5d6ec12 100644 --- a/arangod/V8Server/v8-vocbase.cpp +++ b/arangod/V8Server/v8-vocbase.cpp @@ -1840,7 +1840,7 @@ static void MapGetVocBase(v8::Local const name, if (collection != nullptr && collection->vocbase() == vocbase) { TRI_vocbase_col_status_e status = collection->getStatusLocked(); TRI_voc_cid_t cid = collection->cid(); - uint32_t internalVersion = collection->version(); + uint32_t internalVersion = collection->internalVersion(); // check if the collection is still alive if (status != TRI_VOC_COL_STATUS_DELETED && cid > 0 && diff --git a/arangod/V8Server/v8-vocindex.cpp b/arangod/V8Server/v8-vocindex.cpp index 85507b0da5..9c27d0b5d0 100644 --- a/arangod/V8Server/v8-vocindex.cpp +++ b/arangod/V8Server/v8-vocindex.cpp @@ -638,16 +638,12 @@ static void EnsureIndex(v8::FunctionCallbackInfo const& args, static void CreateCollectionCoordinator( v8::FunctionCallbackInfo const& args, TRI_col_type_e collectionType, std::string const& databaseName, - VocbaseCollectionInfo& parameters, TRI_vocbase_t* vocbase) { + LogicalCollection* parameters) { v8::Isolate* isolate = args.GetIsolate(); v8::HandleScope scope(isolate); std::string const name = TRI_ObjectToString(args[0]); - if (!TRI_collection_t::IsAllowedName(parameters.isSystem(), name.c_str())) { - TRI_V8_THROW_EXCEPTION(TRI_ERROR_ARANGO_ILLEGAL_NAME); - } - bool allowUserKeys = true; uint64_t numberOfShards = 1; std::vector shardKeys; @@ -758,7 +754,7 @@ static void CreateCollectionCoordinator( std::vector dbServers; if (!distributeShardsLike.empty()) { - CollectionNameResolver resolver(vocbase); + CollectionNameResolver resolver(parameters->vocbase()); TRI_voc_cid_t otherCid = resolver.getCollectionIdCluster(distributeShardsLike); if (otherCid != 0) { @@ -807,13 +803,13 @@ static void CreateCollectionCoordinator( ("name", Value(name)) ("type", Value((int) collectionType)) ("status", Value((int) TRI_VOC_COL_STATUS_LOADED)) - ("deleted", Value(parameters.deleted())) - ("doCompact", Value(parameters.doCompact())) - ("isSystem", Value(parameters.isSystem())) - ("isVolatile", Value(parameters.isVolatile())) - ("waitForSync", Value(parameters.waitForSync())) - ("journalSize", Value(parameters.maximalSize())) - ("indexBuckets", Value(parameters.indexBuckets())) + ("deleted", Value(parameters->deleted())) + ("doCompact", Value(parameters->doCompact())) + ("isSystem", Value(parameters->isSystem())) + ("isVolatile", Value(parameters->isVolatile())) + ("waitForSync", Value(parameters->waitForSync())) + ("journalSize", Value(parameters->journalSize())) + ("indexBuckets", Value(parameters->indexBuckets())) ("replicationFactor", Value(replicationFactor)) ("keyOptions", Value(ValueType::Object)) ("type", Value("traditional")) @@ -1255,11 +1251,9 @@ static void CreateVocBase(v8::FunctionCallbackInfo const& args, infoSlice = builder.slice(); if (ServerState::instance()->isCoordinator()) { - //TODO FIXME - VocbaseCollectionInfo parameters(vocbase, name.c_str(), collectionType, - infoSlice, false); + auto parameters = std::make_unique(vocbase, infoSlice); CreateCollectionCoordinator(args, collectionType, vocbase->name(), - parameters, vocbase); + parameters.get()); return; } diff --git a/arangod/VocBase/LogicalCollection.cpp b/arangod/VocBase/LogicalCollection.cpp index 4b042e23a9..3f3275fb24 100644 --- a/arangod/VocBase/LogicalCollection.cpp +++ b/arangod/VocBase/LogicalCollection.cpp @@ -311,6 +311,7 @@ LogicalCollection::LogicalCollection( _waitForSync(other->waitForSync()), _journalSize(other->journalSize()), _keyOptions(other->_keyOptions), + _version(other->_version), _indexBuckets(other->indexBuckets()), _indexes(), _replicationFactor(other->replicationFactor()), @@ -368,7 +369,8 @@ LogicalCollection::LogicalCollection(TRI_vocbase_t* vocbase, VPackSlice info) ReadNumericValue(info, "journalSize", TRI_JOURNAL_DEFAULT_SIZE))), _keyOptions(CopySliceValue(info, "keyOptions")), - _indexBuckets(ReadNumericValue(info, "indexBuckets", DatabaseFeature::DefaultIndexBuckets)), + _version(ReadNumericValue(info, "version", minimumVersion())), + _indexBuckets(ReadNumericValue(info, "indexBuckets", DatabaseFeature::defaultIndexBuckets())), _replicationFactor(ReadNumericValue(info, "replicationFactor", 1)), _numberOfShards(GetObjectLength(info, "shards", 1)), _allowUserKeys(ReadBooleanValue(info, "allowUserKeys", true)), @@ -383,6 +385,18 @@ LogicalCollection::LogicalCollection(TRI_vocbase_t* vocbase, VPackSlice info) _numberDocuments(0), _collection(nullptr), _lock() { + + if (!IsAllowedName(info)) { + THROW_ARANGO_EXCEPTION(TRI_ERROR_ARANGO_ILLEGAL_NAME); + } + + if (_version < minimumVersion()) { + // collection is too "old" + std::string errorMsg(std::string("collection '") + _name + "' has a too old version. Please start the server with the --database.auto-upgrade option."); + + THROW_ARANGO_EXCEPTION_MESSAGE(TRI_ERROR_FAILED, errorMsg); + } + if (_isVolatile && _waitForSync) { // Illegal collection configuration THROW_ARANGO_EXCEPTION_MESSAGE( @@ -508,9 +522,7 @@ size_t LogicalCollection::journalSize() const { return _journalSize; } -// SECTION: Meta Information - -uint32_t LogicalCollection::version() const { +uint32_t LogicalCollection::internalVersion() const { return _internalVersion; } @@ -773,7 +785,7 @@ int LogicalCollection::rename(std::string const& newName) { } // CHECK if this ordering is okay. Before change the version was increased after swapping in vocbase mapping. - increaseVersion(); + increaseInternalVersion(); return TRI_ERROR_NO_ERROR; } @@ -821,7 +833,7 @@ void LogicalCollection::setStatus(TRI_vocbase_col_status_e status) { } } -void LogicalCollection::toVelocyPack(VPackBuilder& result) const { +void LogicalCollection::toVelocyPack(VPackBuilder& result, bool withPath) const { result.openObject(); result.add("id", VPackValue(std::to_string(_cid))); result.add("cid", VPackValue(std::to_string(_cid))); // export cid for compatibility, too @@ -834,11 +846,15 @@ void LogicalCollection::toVelocyPack(VPackBuilder& result) const { result.add("isVolatile", VPackValue(_isVolatile)); result.add("waitForSync", VPackValue(_waitForSync)); result.add("journalSize", VPackValue(_journalSize)); - result.add("version", VPackValue(5)); // hard-coded version number, here for compatibility only + result.add("version", VPackValue(5)); // FIX: hard-coded version number, here for compatibility only if (_keyOptions != nullptr) { result.add("keyOptions", VPackSlice(_keyOptions->data())); } + if (withPath) { + result.add("path", VPackValue(_path)); + } + result.add("indexBuckets", VPackValue(_indexBuckets)); result.add(VPackValue("indexes")); getIndexesVPack(result, true); @@ -875,7 +891,7 @@ TRI_vocbase_t* LogicalCollection::vocbase() const { return _vocbase; } -void LogicalCollection::increaseVersion() { +void LogicalCollection::increaseInternalVersion() { ++_internalVersion; } diff --git a/arangod/VocBase/LogicalCollection.h b/arangod/VocBase/LogicalCollection.h index 032253aa8c..1be52d09e8 100644 --- a/arangod/VocBase/LogicalCollection.h +++ b/arangod/VocBase/LogicalCollection.h @@ -72,6 +72,11 @@ class LogicalCollection { LogicalCollection(LogicalCollection const&) = delete; LogicalCollection& operator=(LogicalCollection const&) = delete; LogicalCollection() = delete; + + /// @brief hard-coded minimum version number for collections + static constexpr uint32_t minimumVersion() { + return 5; + } /// @brief determine whether a collection name is a system collection name static inline bool IsSystemName(std::string const& name) { @@ -84,7 +89,11 @@ class LogicalCollection { static bool IsAllowedName(arangodb::velocypack::Slice parameters); // SECTION: Meta Information - uint32_t version() const; + uint32_t version() const { + return _version; + } + + uint32_t internalVersion() const; TRI_voc_cid_t cid() const; std::string cid_as_string() const; @@ -165,7 +174,7 @@ class LogicalCollection { void setStatus(TRI_vocbase_col_status_e); // SECTION: Serialisation - void toVelocyPack(arangodb::velocypack::Builder&) const; + void toVelocyPack(arangodb::velocypack::Builder&, bool withPath) const; /// @brief transform the information for this collection to velocypack /// The builder has to be an opened Type::Object @@ -177,7 +186,6 @@ class LogicalCollection { void updateCount(size_t); // Update this collection. - void increaseVersion(); int update(arangodb::velocypack::Slice const&, bool); /// @brief return the figures for a collection @@ -396,7 +404,7 @@ class LogicalCollection { std::string const& rev, arangodb::velocypack::Builder& builder); - + void increaseInternalVersion(); private: // SECTION: Private variables @@ -439,6 +447,8 @@ class LogicalCollection { // TODO Really VPack? std::shared_ptr const> _keyOptions; // options for key creation + + uint32_t _version; // SECTION: Indexes uint32_t _indexBuckets; @@ -448,7 +458,6 @@ class LogicalCollection { // SECTION: Replication int const _replicationFactor; - private: // SECTION: Sharding int const _numberOfShards; bool const _allowUserKeys; diff --git a/arangod/VocBase/collection.cpp b/arangod/VocBase/collection.cpp index 24a5165007..34f357ab6e 100644 --- a/arangod/VocBase/collection.cpp +++ b/arangod/VocBase/collection.cpp @@ -205,291 +205,6 @@ bool TRI_collection_t::IsAllowedName(bool allowSystem, std::string const& name) return true; } -VocbaseCollectionInfo::VocbaseCollectionInfo(TRI_vocbase_t* vocbase, - std::string const& name, - TRI_col_type_e type, - TRI_voc_size_t maximalSize, - VPackSlice const& keyOptions) - : _type(type), - _cid(0), - _planId(0), - _maximalSize(32 * 1024 * 1024), // just to have a default - _initialCount(-1), - _indexBuckets(DatabaseFeature::DefaultIndexBuckets), - _keyOptions(nullptr), - _isSystem(false), - _deleted(false), - _doCompact(true), - _isVolatile(false), - _waitForSync(false) { - - auto database = application_features::ApplicationServer::getFeature("Database"); - _maximalSize = static_cast(database->maximalJournalSize()); - _waitForSync = database->waitForSync(); - - size_t pageSize = PageSizeFeature::getPageSize(); - _maximalSize = - static_cast((maximalSize / pageSize) * pageSize); - if (_maximalSize == 0 && maximalSize != 0) { - _maximalSize = static_cast(pageSize); - } - memset(_name, 0, sizeof(_name)); - TRI_CopyString(_name, name.c_str(), sizeof(_name) - 1); - - if (!keyOptions.isNone()) { - VPackBuilder builder; - builder.add(keyOptions); - _keyOptions = builder.steal(); - } -} - -VocbaseCollectionInfo::VocbaseCollectionInfo(TRI_vocbase_t* vocbase, - std::string const& name, - VPackSlice const& options, - bool forceIsSystem) - : VocbaseCollectionInfo(vocbase, name, TRI_COL_TYPE_DOCUMENT, options, - forceIsSystem) {} - -VocbaseCollectionInfo::VocbaseCollectionInfo(TRI_vocbase_t* vocbase, - std::string const& name, - TRI_col_type_e type, - VPackSlice const& options, - bool forceIsSystem) - : _type(type), - _cid(0), - _planId(0), - _maximalSize(32 * 1024 * 1024), // just to have a default - _initialCount(-1), - _indexBuckets(DatabaseFeature::DefaultIndexBuckets), - _keyOptions(nullptr), - _isSystem(false), - _deleted(false), - _doCompact(true), - _isVolatile(false), - _waitForSync(false) { - - auto database = application_features::ApplicationServer::getFeature("Database"); - _maximalSize = static_cast(database->maximalJournalSize()); - _waitForSync = database->waitForSync(); - - memset(_name, 0, sizeof(_name)); - - TRI_CopyString(_name, name.c_str(), sizeof(_name) - 1); - - if (options.isObject()) { - TRI_voc_size_t maximalSize; - if (options.hasKey("journalSize")) { - maximalSize = - arangodb::basics::VelocyPackHelper::getNumericValue( - options, "journalSize", _maximalSize); - } else { - maximalSize = - arangodb::basics::VelocyPackHelper::getNumericValue( - options, "maximalSize", _maximalSize); - } - - size_t pageSize = PageSizeFeature::getPageSize(); - _maximalSize = - static_cast((maximalSize / pageSize) * pageSize); - if (_maximalSize == 0 && maximalSize != 0) { - _maximalSize = static_cast(pageSize); - } - - if (options.hasKey("count")) { - _initialCount = - arangodb::basics::VelocyPackHelper::getNumericValue( - options, "count", -1); - } - - _doCompact = arangodb::basics::VelocyPackHelper::getBooleanValue( - options, "doCompact", true); - _waitForSync = arangodb::basics::VelocyPackHelper::getBooleanValue( - options, "waitForSync", _waitForSync); - _isVolatile = arangodb::basics::VelocyPackHelper::getBooleanValue( - options, "isVolatile", false); - _indexBuckets = - arangodb::basics::VelocyPackHelper::getNumericValue( - options, "indexBuckets", DatabaseFeature::DefaultIndexBuckets); - _type = static_cast( - arangodb::basics::VelocyPackHelper::getNumericValue( - options, "type", _type)); - - std::string cname = - arangodb::basics::VelocyPackHelper::getStringValue(options, "name", ""); - if (!cname.empty()) { - TRI_CopyString(_name, cname.c_str(), sizeof(_name) - 1); - } - - TRI_voc_cid_t cid = arangodb::basics::VelocyPackHelper::extractIdValue(options); - if (cid != 0) { - _cid = cid; - } - - if (options.hasKey("isSystem")) { - VPackSlice isSystemSlice = options.get("isSystem"); - if (isSystemSlice.isBoolean()) { - _isSystem = isSystemSlice.getBoolean(); - } - } else { - _isSystem = false; - } - - if (options.hasKey("journalSize")) { - VPackSlice maxSizeSlice = options.get("journalSize"); - TRI_voc_size_t maximalSize = - maxSizeSlice.getNumericValue(); - if (maximalSize < TRI_JOURNAL_MINIMAL_SIZE) { - THROW_ARANGO_EXCEPTION_MESSAGE(TRI_ERROR_BAD_PARAMETER, - "journalSize is too small"); - } - } - - VPackSlice const planIdSlice = options.get("planId"); - TRI_voc_cid_t planId = 0; - if (planIdSlice.isNumber()) { - planId = planIdSlice.getNumericValue(); - } else if (planIdSlice.isString()) { - std::string tmp = planIdSlice.copyString(); - planId = static_cast(StringUtils::uint64(tmp)); - } - - if (planId > 0) { - _planId = planId; - } - - _cid = arangodb::basics::VelocyPackHelper::extractIdValue(options); - - if (options.hasKey("keyOptions")) { - VPackSlice const slice = options.get("keyOptions"); - VPackBuilder builder; - builder.add(slice); - // Copy the ownership of the options over - _keyOptions = builder.steal(); - } - - if (options.hasKey("deleted")) { - VPackSlice const slice = options.get("deleted"); - if (slice.isBoolean()) { - _deleted = slice.getBoolean(); - } - } - } - -#ifndef TRI_HAVE_ANONYMOUS_MMAP - if (_isVolatile) { - THROW_ARANGO_EXCEPTION_MESSAGE( - TRI_ERROR_BAD_PARAMETER, - "volatile collections are not supported on this platform"); - } -#endif - - if (_isVolatile && _waitForSync) { - // the combination of waitForSync and isVolatile makes no sense - THROW_ARANGO_EXCEPTION_MESSAGE( - TRI_ERROR_BAD_PARAMETER, - "volatile collections do not support the waitForSync option"); - } - - if (_indexBuckets < 1 || _indexBuckets > 1024) { - THROW_ARANGO_EXCEPTION_MESSAGE( - TRI_ERROR_BAD_PARAMETER, - "indexBuckets must be a two-power between 1 and 1024"); - } - - if (!TRI_collection_t::IsAllowedName(_isSystem || forceIsSystem, _name)) { - THROW_ARANGO_EXCEPTION(TRI_ERROR_ARANGO_ILLEGAL_NAME); - } - - // fix _isSystem value if mis-specified by user - _isSystem = (*_name == '_'); -} - -// collection type -TRI_col_type_e VocbaseCollectionInfo::type() const { return _type; } - -// local collection identifier -TRI_voc_cid_t VocbaseCollectionInfo::id() const { return _cid; } - -// cluster-wide collection identifier -TRI_voc_cid_t VocbaseCollectionInfo::planId() const { return _planId; } - -// maximal size of memory mapped file -TRI_voc_size_t VocbaseCollectionInfo::maximalSize() const { - return _maximalSize; -} - -// initial count, used when loading a collection -int64_t VocbaseCollectionInfo::initialCount() const { return _initialCount; } - -// number of buckets used in hash tables for indexes -uint32_t VocbaseCollectionInfo::indexBuckets() const { return _indexBuckets; } - -// name of the collection -std::string VocbaseCollectionInfo::name() const { return std::string(_name); } - -// options for key creation -std::shared_ptr const> -VocbaseCollectionInfo::keyOptions() const { - return _keyOptions; -} - -// If true, collection has been deleted -bool VocbaseCollectionInfo::deleted() const { return _deleted; } - -// If true, collection will be compacted -bool VocbaseCollectionInfo::doCompact() const { return _doCompact; } - -// If true, collection is a system collection -bool VocbaseCollectionInfo::isSystem() const { return _isSystem; } - -// If true, collection is memory-only -bool VocbaseCollectionInfo::isVolatile() const { return _isVolatile; } - -// If true waits for mysnc -bool VocbaseCollectionInfo::waitForSync() const { return _waitForSync; } - -void VocbaseCollectionInfo::clearKeyOptions() { _keyOptions.reset(); } - -std::shared_ptr VocbaseCollectionInfo::toVelocyPack() const { - auto builder = std::make_shared(); - builder->openObject(); - toVelocyPack(*builder); - builder->close(); - return builder; -} - -void VocbaseCollectionInfo::toVelocyPack(VPackBuilder& builder) const { - TRI_ASSERT(!builder.isClosed()); - - std::string planIdString = std::to_string(planId()); - - builder.add("version", VPackValue(version())); - builder.add("type", VPackValue(type())); - builder.add("id", VPackValue(std::to_string(id()))); - - if (planId() > 0) { - builder.add("planId", VPackValue(planIdString)); - } - - if (initialCount() >= 0) { - builder.add("count", VPackValue(initialCount())); - } - builder.add("indexBuckets", VPackValue(indexBuckets())); - builder.add("deleted", VPackValue(deleted())); - builder.add("doCompact", VPackValue(doCompact())); - builder.add("maximalSize", VPackValue(maximalSize())); - builder.add("name", VPackValue(name())); - builder.add("isVolatile", VPackValue(isVolatile())); - builder.add("waitForSync", VPackValue(waitForSync())); - builder.add("isSystem", VPackValue(isSystem())); - - auto opts = keyOptions(); - if (opts.get() != nullptr) { - VPackSlice const slice(opts->data()); - builder.add("keyOptions", slice); - } -} - /// @brief state during opening of a collection struct OpenIteratorState { LogicalCollection* _collection; diff --git a/arangod/VocBase/collection.h b/arangod/VocBase/collection.h index d9072466cb..3efbe5b6a4 100644 --- a/arangod/VocBase/collection.h +++ b/arangod/VocBase/collection.h @@ -45,104 +45,6 @@ struct DocumentOperation; /// @brief predefined collection name for users #define TRI_COL_NAME_USERS "_users" -namespace arangodb { - -/// @brief collection info block saved to disk as json -class VocbaseCollectionInfo { - private: - TRI_col_type_e _type; // collection type - TRI_voc_cid_t _cid; // local collection identifier - TRI_voc_cid_t _planId; // cluster-wide collection identifier - TRI_voc_size_t _maximalSize; // maximal size of memory mapped file - int64_t _initialCount; // initial count, used when loading a collection - uint32_t _indexBuckets; // number of buckets used in hash tables for indexes - - char _name[512]; // name of the collection - std::shared_ptr const> - _keyOptions; // options for key creation - - // flags - bool _isSystem; // if true, this is a system collection - bool _deleted; // if true, collection has been deleted - bool _doCompact; // if true, collection will be compacted - bool _isVolatile; // if true, collection is memory-only - bool _waitForSync; // if true, wait for msync - - public: - VocbaseCollectionInfo() = default; - ~VocbaseCollectionInfo() = default; - - VocbaseCollectionInfo(TRI_vocbase_t*, std::string const&, TRI_col_type_e, - TRI_voc_size_t, arangodb::velocypack::Slice const&); - - VocbaseCollectionInfo(TRI_vocbase_t*, std::string const&, - arangodb::velocypack::Slice const&, - bool forceIsSystem); - - VocbaseCollectionInfo(TRI_vocbase_t*, std::string const&, TRI_col_type_e, - arangodb::velocypack::Slice const&, - bool forceIsSystem); - - std::shared_ptr toVelocyPack() const; - void toVelocyPack(VPackBuilder& builder) const; - - // collection version - static constexpr uint32_t version() { return 5; } - - // collection type - TRI_col_type_e type() const; - - // local collection identifier - TRI_voc_cid_t id() const; - - // cluster-wide collection identifier - TRI_voc_cid_t planId() const; - - // last revision id written - TRI_voc_rid_t revision() const; - - // maximal size of memory mapped file - TRI_voc_size_t maximalSize() const; - - // initial count, used when loading a collection - int64_t initialCount() const; - - // number of buckets used in hash tables for indexes - uint32_t indexBuckets() const; - - // name of the collection - std::string name() const; - - ////////////////////////////////////////////////////////////////////////////// - /// @brief returns a copy of the key options - /// the caller is responsible for freeing it - ////////////////////////////////////////////////////////////////////////////// - - std::shared_ptr const> keyOptions() - const; - - // If true, collection has been deleted - bool deleted() const; - - // If true, collection will be compacted - bool doCompact() const; - - // If true, collection is a system collection - bool isSystem() const; - - // If true, collection is memory-only - bool isVolatile() const; - - // If true waits for mysnc - bool waitForSync() const; - - - - void clearKeyOptions(); -}; - -} // namespace arangodb - struct TRI_collection_t { public: TRI_collection_t(TRI_collection_t const&) = delete; diff --git a/arangod/VocBase/vocbase.cpp b/arangod/VocBase/vocbase.cpp index 7c40a1891b..5e20bcbec8 100644 --- a/arangod/VocBase/vocbase.cpp +++ b/arangod/VocBase/vocbase.cpp @@ -322,7 +322,7 @@ arangodb::LogicalCollection* TRI_vocbase_t::createCollectionWorker( collection->setStatus(TRI_VOC_COL_STATUS_LOADED); if (writeMarker) { - collection->toVelocyPack(builder); + collection->toVelocyPack(builder, false); } // FIXME Temporary until move is finished // ok, construct the collection