diff --git a/3rdParty/iresearch/core/formats/formats_10.cpp b/3rdParty/iresearch/core/formats/formats_10.cpp index b922d93188..87b852ac96 100644 --- a/3rdParty/iresearch/core/formats/formats_10.cpp +++ b/3rdParty/iresearch/core/formats/formats_10.cpp @@ -1816,9 +1816,12 @@ class index_block { static const size_t SIZE = Size; bool push_back(doc_id_t key, uint64_t offset) { - assert(keys_ <= key_); + assert(key_ >= keys_); + assert(key_ < keys_ + Size); *key_++ = key; assert(key >= key_[-1]); + assert(offset_ >= offsets_); + assert(offset_ < offsets_ + Size); *offset_++ = offset; assert(offset >= offset_[-1]); return key_ == std::end(keys_); @@ -1931,6 +1934,13 @@ class writer final : public iresearch::columnstore_writer { // commit previous key and offset unless the 'reset' method has been called if (max_ != pending_key_) { + // flush block if we've overcome INDEX_BLOCK_SIZE size (before push_back) + if (INDEX_BLOCK_SIZE <= block_index_.size()) { + flush_block(); + min_ = key; + offset = block_buf_.size(); // reset offset to position in the current block + } + // will trigger 'flush_block' if offset >= MAX_DATA_BLOCK_SIZE offset = offsets_[size_t(block_index_.push_back(pending_key_, offset))]; max_ = pending_key_; diff --git a/arangod/Cluster/ClusterMethods.cpp b/arangod/Cluster/ClusterMethods.cpp index f448d37c57..7f9fc2e385 100644 --- a/arangod/Cluster/ClusterMethods.cpp +++ b/arangod/Cluster/ClusterMethods.cpp @@ -2647,7 +2647,7 @@ std::shared_ptr ClusterMethods::persistCollectionInAgency( } else { // system collections should never enforce replicationfactor // to allow them to come up with 1 dbserver - if (col->isSystem()) { + if (col->system()) { enforceReplicationFactor = false; } @@ -2685,7 +2685,9 @@ std::shared_ptr ClusterMethods::persistCollectionInAgency( }), dbServers.end()); } std::random_shuffle(dbServers.begin(), dbServers.end()); - shards = DistributeShardsEvenly(ci, numberOfShards, replicationFactor, dbServers, !col->isSystem()); + shards = DistributeShardsEvenly( + ci, numberOfShards, replicationFactor, dbServers, !col->system() + ); } if (shards->empty() && !col->isSmart()) { diff --git a/arangod/IResearch/IResearchViewDBServer.cpp b/arangod/IResearch/IResearchViewDBServer.cpp index d183b14933..433c078b93 100644 --- a/arangod/IResearch/IResearchViewDBServer.cpp +++ b/arangod/IResearch/IResearchViewDBServer.cpp @@ -43,6 +43,12 @@ typedef irs::async_utils::read_write_mutex::write_mutex WriteMutex; //////////////////////////////////////////////////////////////////////////////// const std::string COLLECTIONS_FIELD("collections"); +//////////////////////////////////////////////////////////////////////////////// +/// @brief the name of the field in the IResearch View definition denoting the +/// view deletion marker (from LogicalView.cpp) +//////////////////////////////////////////////////////////////////////////////// +const std::string DELETED_FIELD("deleted"); + //////////////////////////////////////////////////////////////////////////////// /// @brief the name of the field in the IResearch View definition denoting the /// view id (from LogicalView.cpp) @@ -67,12 +73,27 @@ const std::string LINKS_FIELD("links"); //////////////////////////////////////////////////////////////////////////////// const std::string NAME_FIELD("name"); +//////////////////////////////////////////////////////////////////////////////// +/// @brief the name of the field in the IResearch View definition denoting the +/// view plan ID (from LogicalView.cpp) +//////////////////////////////////////////////////////////////////////////////// +const std::string PLAN_ID_FIELD("planId"); + //////////////////////////////////////////////////////////////////////////////// /// @brief the name of the field in the IResearch View definition denoting the /// view properties (from LogicalView.cpp) //////////////////////////////////////////////////////////////////////////////// const std::string PROPERTIES_FIELD("properties"); +//////////////////////////////////////////////////////////////////////////////// +/// @brief the name of the field in the IResearch View definition denoting the +/// view type (from LogicalView.cpp) +//////////////////////////////////////////////////////////////////////////////// +const std::string TYPE_FIELD("type"); + +//////////////////////////////////////////////////////////////////////////////// +/// @brief the view name prefix of per-cid view instances +//////////////////////////////////////////////////////////////////////////////// static std::string const VIEW_NAME_PREFIX("_iresearch_"); //////////////////////////////////////////////////////////////////////////////// @@ -130,7 +151,10 @@ IResearchViewDBServer::IResearchViewDBServer( arangodb::DatabasePathFeature const& dbPathFeature, uint64_t planVersion ): LogicalView(vocbase, info, planVersion), - _meta(info), + _meta( + info.isObject() && info.get(PROPERTIES_FIELD).isObject() + ? info.get(PROPERTIES_FIELD) : emptyObjectSlice() + ), _persistedPath(getPersistedPath(dbPathFeature, id())) { } @@ -143,7 +167,7 @@ arangodb::Result IResearchViewDBServer::drop() { SCOPED_LOCK(mutex); // 'collections_' can be asynchronously read for (auto itr = _collections.begin(); itr != _collections.end();) { - auto res = vocbase().dropView(*(itr->second)); + auto res = vocbase().dropView(itr->second->id(), true); // per-cid collections always system if (!res.ok()) { return res; // fail on first failure @@ -164,7 +188,7 @@ arangodb::Result IResearchViewDBServer::drop(TRI_voc_cid_t cid) { return arangodb::Result(TRI_ERROR_ARANGO_DATA_SOURCE_NOT_FOUND); } - auto res = vocbase().dropView(*(itr->second)); + auto res = vocbase().dropView(itr->second->id(), true); // per-cid collections always system if (res.ok()) { _collections.erase(itr); @@ -187,45 +211,29 @@ std::shared_ptr IResearchViewDBServer::ensure( static const std::function acceptor = []( irs::string_ref const& key )->bool { - // ignored fields - return key != ID_FIELD - && key != IS_SYSTEM_FIELD - && key != NAME_FIELD - && key != PROPERTIES_FIELD; + return key != COLLECTIONS_FIELD && key != LINKS_FIELD; // ignored fields }; arangodb::velocypack::Builder builder; builder.openObject(); - builder.add(ID_FIELD, arangodb::velocypack::Value("0")); // force unique ID builder.add(IS_SYSTEM_FIELD, arangodb::velocypack::Value(true)); // required to for use of VIEW_NAME_PREFIX builder.add(NAME_FIELD, toValuePair(generateName(name(), id(), cid))); // mark the view definition as an internal per-cid instance + builder.add(TYPE_FIELD, toValuePair(DATA_SOURCE_TYPE.name())); // type required for proper factory selection - if (!mergeSliceSkipKeys(builder, _meta.slice(), acceptor)) { - LOG_TOPIC(WARN, arangodb::iresearch::TOPIC) - << "failure to generate definition while constructing IResearch View in database '" << vocbase().id() << "'"; + { + builder.add( + PROPERTIES_FIELD, + arangodb::velocypack::Value(arangodb::velocypack::ValueType::Object) + ); - return nullptr; - } - - auto props = _meta.slice().get(PROPERTIES_FIELD); - - if (props.isObject()) { - static const std::function propsAcceptor = []( - irs::string_ref const& key - )->bool { - return key != COLLECTIONS_FIELD && key != LINKS_FIELD; // ignored fields - }; - - builder.add(PROPERTIES_FIELD, VPackValue(VPackValueType::Object)); - - if (!mergeSliceSkipKeys(builder, props, propsAcceptor)) { + if (!mergeSliceSkipKeys(builder, _meta.slice(), acceptor)) { LOG_TOPIC(WARN, arangodb::iresearch::TOPIC) << "failure to generate properties definition while constructing IResearch View in database '" << vocbase().id() << "'"; return nullptr; } - builder.close(); + builder.close(); // close PROPERTIES_FIELD } builder.close(); @@ -467,7 +475,7 @@ void IResearchViewDBServer::open() { arangodb::Result IResearchViewDBServer::rename( std::string&& newName, - bool doSync + bool /*doSync*/ ) { ReadMutex mutex(_mutex); SCOPED_LOCK(mutex); // 'collections_' can be asynchronously modified @@ -482,25 +490,6 @@ arangodb::Result IResearchViewDBServer::rename( } } - static const std::function acceptor = []( - irs::string_ref const& key - )->bool { - return key != NAME_FIELD; // ignore name filed - }; - arangodb::velocypack::Builder builder; - - builder.openObject(); - builder.add(NAME_FIELD, arangodb::velocypack::Value(std::move(newName))); - - if (!mergeSliceSkipKeys(builder, _meta.slice(), acceptor)) { - return arangodb::Result( - TRI_ERROR_INTERNAL, - std::string("failure to generate definition while renaming IResearch View in database '") + vocbase().name() + "'" - ); - } - - builder.close(); - _meta = std::move(builder); name(std::move(newName)); return arangodb::Result(); @@ -509,60 +498,54 @@ arangodb::Result IResearchViewDBServer::rename( void IResearchViewDBServer::toVelocyPack( arangodb::velocypack::Builder& result, bool includeProperties, - bool /*includeSystem*/ + bool includeSystem ) const { TRI_ASSERT(result.isOpenObject()); - ReadMutex mutex(_mutex); - SCOPED_LOCK(mutex); // '_collections'/'_meta' can be asynchronously modified - static const std::function acceptor = []( - irs::string_ref const& key - )->bool { - return key != PROPERTIES_FIELD; // ignored fields - }; + result.add(ID_FIELD, arangodb::velocypack::Value(std::to_string(id()))); + result.add(NAME_FIELD, arangodb::velocypack::Value(name())); + result.add(TYPE_FIELD, arangodb::velocypack::Value(type().name())); - if (!mergeSliceSkipKeys(result, _meta.slice(), acceptor)) { - LOG_TOPIC(WARN, arangodb::iresearch::TOPIC) - << "failure to generate definition while for IResearch View in database '" << vocbase().name() << "'"; - - return; // error during output + if (includeSystem) { + result.add(DELETED_FIELD, arangodb::velocypack::Value(deleted())); + result.add(IS_SYSTEM_FIELD, arangodb::velocypack::Value(system())); + result.add(PLAN_ID_FIELD, arangodb::velocypack::Value(std::to_string(planId()))); } - if (!includeProperties) { - return; // nothing more to output - } + if (includeProperties) { + static const std::function acceptor = []( + irs::string_ref const& key + )->bool { + return key != COLLECTIONS_FIELD && key != LINKS_FIELD; // ignored fields + }; + ReadMutex mutex(_mutex); + SCOPED_LOCK(mutex); // '_collections'/'_meta' can be asynchronously modified - static const std::function propsAcceptor = []( - irs::string_ref const& key - )->bool { - return key != COLLECTIONS_FIELD && key != LINKS_FIELD; // ignored fields - }; - auto properties = _meta.slice().get(PROPERTIES_FIELD); - - result.add( - PROPERTIES_FIELD, - arangodb::velocypack::Value(arangodb::velocypack::ValueType::Object) - ); - - { result.add( - COLLECTIONS_FIELD, - arangodb::velocypack::Value(arangodb::velocypack::ValueType::Array) + PROPERTIES_FIELD, + arangodb::velocypack::Value(arangodb::velocypack::ValueType::Object) ); - for (auto& entry: _collections) { - result.add(arangodb::velocypack::Value(entry.first)); + { + result.add( + COLLECTIONS_FIELD, + arangodb::velocypack::Value(arangodb::velocypack::ValueType::Array) + ); + + for (auto& entry: _collections) { + result.add(arangodb::velocypack::Value(entry.first)); + } + + result.close(); // close COLLECTIONS_FIELD } - result.close(); // close COLLECTIONS_FIELD - } + if (!mergeSliceSkipKeys(result, _meta.slice(), acceptor)) { + LOG_TOPIC(WARN, arangodb::iresearch::TOPIC) + << "failure to generate definition while properties generating jSON IResearch View in database '" << vocbase().name() << "'"; + } - if (!mergeSliceSkipKeys(result, properties, propsAcceptor)) { - LOG_TOPIC(WARN, arangodb::iresearch::TOPIC) - << "failure to generate definition while properties generating jSON IResearch View in database '" << vocbase().name() << "'"; + result.close(); // close PROPERTIES_FIELD } - - result.close(); // close PROPERTIES_FIELD } arangodb::Result IResearchViewDBServer::updateProperties( @@ -605,7 +588,7 @@ arangodb::Result IResearchViewDBServer::updateProperties( if (partialUpdate) { IResearchViewMeta oldMeta; - if (!oldMeta.init(_meta.slice().get(PROPERTIES_FIELD), error) + if (!oldMeta.init(_meta.slice(), error) || !meta.init(props.slice(), error, oldMeta)) { return arangodb::Result( TRI_ERROR_BAD_PARAMETER, @@ -632,27 +615,10 @@ arangodb::Result IResearchViewDBServer::updateProperties( // prepare replacement '_meta' // ........................................................................... - static const std::function acceptor = []( - irs::string_ref const& key - )->bool { - return key != PROPERTIES_FIELD; // ignored fields - }; arangodb::velocypack::Builder builder; builder.openObject(); - if (!mergeSliceSkipKeys(builder, _meta.slice(), acceptor)) { - return arangodb::Result( - TRI_ERROR_INTERNAL, - std::string("failure to generate definition while updating IResearch View in database '") + vocbase().name() + "'" - ); - } - - builder.add( - PROPERTIES_FIELD, - arangodb::velocypack::Value(arangodb::velocypack::ValueType::Object) - ); - if (!meta.json(builder)) { return arangodb::Result( TRI_ERROR_INTERNAL, @@ -660,7 +626,6 @@ arangodb::Result IResearchViewDBServer::updateProperties( ); } - builder.close(); // close PROPERTIES_FIELD builder.close(); // ........................................................................... diff --git a/arangod/MMFiles/MMFilesWalRecoverState.cpp b/arangod/MMFiles/MMFilesWalRecoverState.cpp index e1f1e11304..3963613ff4 100644 --- a/arangod/MMFiles/MMFilesWalRecoverState.cpp +++ b/arangod/MMFiles/MMFilesWalRecoverState.cpp @@ -709,7 +709,7 @@ bool MMFilesWalRecoverState::ReplayMarker(MMFilesMarker const* marker, auto otherCid = other->id(); state->releaseCollection(otherCid); - vocbase->dropCollection(other.get(), true, -1.0); + vocbase->dropCollection(otherCid, true, -1.0); } } @@ -851,7 +851,7 @@ bool MMFilesWalRecoverState::ReplayMarker(MMFilesMarker const* marker, break; } - vocbase->dropView(*other); + vocbase->dropView(other->id(), true); } int res = vocbase->renameView(view, name); @@ -1058,7 +1058,7 @@ bool MMFilesWalRecoverState::ReplayMarker(MMFilesMarker const* marker, if (collection != nullptr) { // drop an existing collection - vocbase->dropCollection(collection, true, -1.0); + vocbase->dropCollection(collection->id(), true, -1.0); } MMFilesPersistentIndexFeature::dropCollection(databaseId, collectionId); @@ -1077,7 +1077,7 @@ bool MMFilesWalRecoverState::ReplayMarker(MMFilesMarker const* marker, auto otherCid = collection->id(); state->releaseCollection(otherCid); - vocbase->dropCollection(collection, true, -1.0); + vocbase->dropCollection(otherCid, true, -1.0); } } else { LOG_TOPIC(WARN, arangodb::Logger::ENGINES) @@ -1174,7 +1174,7 @@ bool MMFilesWalRecoverState::ReplayMarker(MMFilesMarker const* marker, vocbase->lookupView(viewId); if (view != nullptr) { - vocbase->dropView(*view); // drop an existing view + vocbase->dropView(view->id(), true); // drop an existing view } // check if there is another view with the same name as the one that @@ -1187,7 +1187,7 @@ bool MMFilesWalRecoverState::ReplayMarker(MMFilesMarker const* marker, view = vocbase->lookupView(name); if (view != nullptr) { - vocbase->dropView(*view); + vocbase->dropView(view->id(), true); } } else { LOG_TOPIC(WARN, arangodb::Logger::ENGINES) @@ -1397,7 +1397,7 @@ bool MMFilesWalRecoverState::ReplayMarker(MMFilesMarker const* marker, } if (collection != nullptr) { - vocbase->dropCollection(collection, true, -1.0); + vocbase->dropCollection(collection->id(), true, -1.0); } MMFilesPersistentIndexFeature::dropCollection(databaseId, collectionId); break; @@ -1427,7 +1427,7 @@ bool MMFilesWalRecoverState::ReplayMarker(MMFilesMarker const* marker, vocbase->lookupView(viewId); if (view != nullptr) { - vocbase->dropView(*view); + vocbase->dropView(view->id(), true); } break; diff --git a/arangod/Replication/DatabaseInitialSyncer.cpp b/arangod/Replication/DatabaseInitialSyncer.cpp index 31b45b217b..0e0c3262a3 100644 --- a/arangod/Replication/DatabaseInitialSyncer.cpp +++ b/arangod/Replication/DatabaseInitialSyncer.cpp @@ -817,7 +817,9 @@ Result DatabaseInitialSyncer::handleCollection(VPackSlice const& parameters, // in this case we must drop it because we will run into duplicate // name conflicts otherwise try { - int res = vocbase()->dropCollection(col, true, -1.0); + auto res = + vocbase()->dropCollection(col->id(), true, -1.0).errorNumber(); + if (res == TRI_ERROR_NO_ERROR) { col = nullptr; } @@ -876,7 +878,8 @@ Result DatabaseInitialSyncer::handleCollection(VPackSlice const& parameters, } setProgress("dropping " + collectionMsg); - int res = vocbase()->dropCollection(col, true, -1.0); + auto res = + vocbase()->dropCollection(col->id(), true, -1.0).errorNumber(); if (res != TRI_ERROR_NO_ERROR) { return Result(res, std::string("unable to drop ") + collectionMsg + ": " + TRI_errno_string(res)); diff --git a/arangod/Replication/GlobalInitialSyncer.cpp b/arangod/Replication/GlobalInitialSyncer.cpp index 7872a9184a..7b1482a10b 100644 --- a/arangod/Replication/GlobalInitialSyncer.cpp +++ b/arangod/Replication/GlobalInitialSyncer.cpp @@ -270,7 +270,7 @@ Result GlobalInitialSyncer::updateServerInventory(VPackSlice const& masterDataba return; } - if (collection->isSystem()) { + if (collection->system()) { // we will not drop system collections here return; } @@ -280,7 +280,9 @@ Result GlobalInitialSyncer::updateServerInventory(VPackSlice const& masterDataba for (auto const& collection : toDrop) { try { - int res = vocbase->dropCollection(collection, false, -1.0); + auto res = + vocbase->dropCollection(collection->id(), false, -1.0).errorNumber(); + if (res != TRI_ERROR_NO_ERROR) { LOG_TOPIC(ERR, Logger::FIXME) << "unable to drop collection " << collection->name() << ": " << TRI_errno_string(res); } diff --git a/arangod/Replication/Syncer.cpp b/arangod/Replication/Syncer.cpp index 965a8b1787..93fa119024 100644 --- a/arangod/Replication/Syncer.cpp +++ b/arangod/Replication/Syncer.cpp @@ -584,7 +584,7 @@ Result Syncer::createCollection(TRI_vocbase_t* vocbase, col = vocbase->lookupCollection(name).get(); if (col != nullptr) { - if (col->isSystem()) { + if (col->system()) { TRI_ASSERT(!simulate32Client() || col->globallyUniqueId() == col->name()); SingleCollectionTransaction trx( transaction::StandaloneContext::Create(vocbase), @@ -606,7 +606,7 @@ Result Syncer::createCollection(TRI_vocbase_t* vocbase, return trx.finish(opRes.result); } else { - vocbase->dropCollection(col, false, -1.0); + vocbase->dropCollection(col->id(), false, -1.0); } } @@ -665,7 +665,7 @@ Result Syncer::dropCollection(VPackSlice const& slice, bool reportError) { return Result(); } - return Result(vocbase->dropCollection(col, true, -1.0)); + return vocbase->dropCollection(col->id(), true, -1.0); } /// @brief creates an index, based on the VelocyPack provided diff --git a/arangod/Replication/TailingSyncer.cpp b/arangod/Replication/TailingSyncer.cpp index 24d4439a70..36577fa8c7 100644 --- a/arangod/Replication/TailingSyncer.cpp +++ b/arangod/Replication/TailingSyncer.cpp @@ -297,7 +297,8 @@ Result TailingSyncer::processDocument(TRI_replication_operation_e type, return Result(TRI_ERROR_ARANGO_DATA_SOURCE_NOT_FOUND); } - bool isSystem = coll->isSystem(); + bool isSystem = coll->system(); + // extract "data" VPackSlice const doc = slice.get("data"); @@ -576,7 +577,7 @@ Result TailingSyncer::renameCollection(VPackSlice const& slice) { TRI_ASSERT(col == nullptr); return Result(TRI_ERROR_ARANGO_DATA_SOURCE_NOT_FOUND, "unable to identify collection"); } - if (col->isSystem()) { + if (col->system()) { LOG_TOPIC(WARN, Logger::REPLICATION) << "Renaming system collection " << col->name(); } return Result(vocbase->renameCollection(col, name, true)); diff --git a/arangod/RestHandler/RestCollectionHandler.cpp b/arangod/RestHandler/RestCollectionHandler.cpp index 488129216c..ad1bf872ad 100644 --- a/arangod/RestHandler/RestCollectionHandler.cpp +++ b/arangod/RestHandler/RestCollectionHandler.cpp @@ -85,7 +85,8 @@ void RestCollectionHandler::handleCommandGet() { ExecContext const* exec = ExecContext::CURRENT; bool canUse = exec == nullptr || exec->canUseCollection(coll->name(), auth::Level::RO); - if (canUse && (!excludeSystem || !coll->isSystem())) { + + if (canUse && (!excludeSystem || !coll->system())) { collectionRepresentation(builder, coll, /*showProperties*/ false, /*showFigures*/ false, /*showCount*/ false, @@ -493,7 +494,7 @@ void RestCollectionHandler::collectionRepresentation( builder.add("type", VPackValue(coll->type())); if (!showProperties) { - builder.add("isSystem", VPackValue(coll->isSystem())); + builder.add("isSystem", VPackValue(coll->system())); builder.add("globallyUniqueId", VPackValue(coll->globallyUniqueId())); } else { Result res = methods::Collections::properties(coll, builder); diff --git a/arangod/RestHandler/RestReplicationHandler.cpp b/arangod/RestHandler/RestReplicationHandler.cpp index 058be1e5ad..14eb49fbb6 100644 --- a/arangod/RestHandler/RestReplicationHandler.cpp +++ b/arangod/RestHandler/RestReplicationHandler.cpp @@ -909,7 +909,7 @@ Result RestReplicationHandler::processRestoreCollection( // drop an existing collection if it exists if (col != nullptr) { if (dropExisting) { - Result res = _vocbase.dropCollection(col, true, -1.0); + auto res = _vocbase.dropCollection(col->id(), true, -1.0); if (res.errorNumber() == TRI_ERROR_FORBIDDEN) { // some collections must not be dropped @@ -2547,7 +2547,7 @@ int RestReplicationHandler::createCollection(VPackSlice slice, } /* Temporary ASSERTS to prove correctness of new constructor */ - TRI_ASSERT(col->isSystem() == (name[0] == '_')); + TRI_ASSERT(col->system() == (name[0] == '_')); #ifdef ARANGODB_ENABLE_MAINTAINER_MODE TRI_voc_cid_t planId = 0; VPackSlice const planIdSlice = slice.get("planId"); diff --git a/arangod/RestHandler/RestViewHandler.cpp b/arangod/RestHandler/RestViewHandler.cpp index 81e12206f2..3e228e14fc 100644 --- a/arangod/RestHandler/RestViewHandler.cpp +++ b/arangod/RestHandler/RestViewHandler.cpp @@ -227,6 +227,7 @@ void RestViewHandler::deleteView() { } std::string const& name = suffixes[0]; + auto allowDropSystem = _request->parsedValue("isSystem", false); auto view = _vocbase.lookupView(name); if (!view) { @@ -238,7 +239,7 @@ void RestViewHandler::deleteView() { return; } - auto res = _vocbase.dropView(*view).errorNumber(); + auto res = _vocbase.dropView(view->id(), allowDropSystem).errorNumber(); if (res == TRI_ERROR_NO_ERROR) { generateOk(rest::ResponseCode::OK, VPackSlice::trueSlice()); diff --git a/arangod/RocksDBEngine/RocksDBCollection.cpp b/arangod/RocksDBEngine/RocksDBCollection.cpp index 2304751c1d..ac8f1766a5 100644 --- a/arangod/RocksDBEngine/RocksDBCollection.cpp +++ b/arangod/RocksDBEngine/RocksDBCollection.cpp @@ -104,7 +104,7 @@ RocksDBCollection::RocksDBCollection(LogicalCollection* collection, _primaryIndex(nullptr), _cache(nullptr), _cachePresent(false), - _cacheEnabled(!collection->isSystem() && + _cacheEnabled(!collection->system() && basics::VelocyPackHelper::readBooleanValue( info, "cacheEnabled", false)) { VPackSlice s = info.get("isVolatile"); @@ -163,10 +163,12 @@ void RocksDBCollection::setPath(std::string const&) { Result RocksDBCollection::updateProperties(VPackSlice const& slice, bool doSync) { - bool isSys = _logicalCollection != nullptr && _logicalCollection->isSystem(); + auto isSys = _logicalCollection != nullptr && _logicalCollection->system(); + _cacheEnabled = !isSys && basics::VelocyPackHelper::readBooleanValue( slice, "cacheEnabled", _cacheEnabled); primaryIndex()->setCacheEnabled(_cacheEnabled); + if (_cacheEnabled) { createCache(); primaryIndex()->createCache(); diff --git a/arangod/RocksDBEngine/RocksDBIndex.cpp b/arangod/RocksDBEngine/RocksDBIndex.cpp index 45fc1b3e6c..e31bbddbd7 100644 --- a/arangod/RocksDBEngine/RocksDBIndex.cpp +++ b/arangod/RocksDBEngine/RocksDBIndex.cpp @@ -58,7 +58,7 @@ RocksDBIndex::RocksDBIndex( _cf(cf), _cache(nullptr), _cachePresent(false), - _cacheEnabled(useCache && !collection->isSystem()) { + _cacheEnabled(useCache && !collection->system()) { TRI_ASSERT(cf != nullptr && cf != RocksDBColumnFamily::definitions()); if (_cacheEnabled) { createCache(); @@ -79,7 +79,7 @@ RocksDBIndex::RocksDBIndex(TRI_idx_iid_t id, LogicalCollection* collection, _cf(cf), _cache(nullptr), _cachePresent(false), - _cacheEnabled(useCache && !collection->isSystem()) { + _cacheEnabled(useCache && !collection->system()) { TRI_ASSERT(cf != nullptr && cf != RocksDBColumnFamily::definitions()); if (_objectId == 0) { @@ -163,8 +163,9 @@ void RocksDBIndex::createCache() { return; } - TRI_ASSERT(!_collection->isSystem() && - !ServerState::instance()->isCoordinator()); + TRI_ASSERT( + !_collection->system() && !ServerState::instance()->isCoordinator() + ); TRI_ASSERT(_cache.get() == nullptr); TRI_ASSERT(CacheManagerFeature::MANAGER != nullptr); LOG_TOPIC(DEBUG, Logger::CACHE) << "Creating index cache"; diff --git a/arangod/StorageEngine/PhysicalCollection.cpp b/arangod/StorageEngine/PhysicalCollection.cpp index 368e005a18..00dba5cf97 100644 --- a/arangod/StorageEngine/PhysicalCollection.cpp +++ b/arangod/StorageEngine/PhysicalCollection.cpp @@ -277,8 +277,10 @@ int PhysicalCollection::newObjectForInsert( // _id uint8_t* p = builder.add(StaticStrings::IdString, VPackValuePair(9ULL, VPackValueType::Custom)); + *p++ = 0xf3; // custom type for _id - if (_isDBServer && !_logicalCollection->isSystem()) { + + if (_isDBServer && !_logicalCollection->system()) { // db server in cluster, note: the local collections _statistics, // _statisticsRaw and _statistics15 (which are the only system // collections) diff --git a/arangod/V8Server/v8-collection.cpp b/arangod/V8Server/v8-collection.cpp index 386e2db14e..c508444582 100644 --- a/arangod/V8Server/v8-collection.cpp +++ b/arangod/V8Server/v8-collection.cpp @@ -1920,10 +1920,12 @@ static void JS_PregelStart(v8::FunctionCallbackInfo const& args) { try { auto coll = ClusterInfo::instance()->getCollection(vocbase->name(), name); - if (coll->isSystem()) { + + if (coll->system()) { TRI_V8_THROW_EXCEPTION_USAGE( "Cannot use pregel on system collection"); } + if (coll->status() == TRI_VOC_COL_STATUS_DELETED || coll->deleted()) { TRI_V8_THROW_EXCEPTION_MESSAGE(TRI_ERROR_ARANGO_DATA_SOURCE_NOT_FOUND, name); } @@ -1943,16 +1945,19 @@ static void JS_PregelStart(v8::FunctionCallbackInfo const& args) { } std::vector edgeColls; + // load edge collection for (std::string const& name : paramEdges) { if (ss->isCoordinator()) { try { auto coll = ClusterInfo::instance()->getCollection(vocbase->name(), name); - if (coll->isSystem()) { + + if (coll->system()) { TRI_V8_THROW_EXCEPTION_USAGE( "Cannot use pregel on system collection"); } + if (!coll->isSmart()) { std::vector eKeys = coll->shardKeys(); if ( eKeys.size() != 1 || eKeys[0] != "vertex") { @@ -1961,11 +1966,14 @@ static void JS_PregelStart(v8::FunctionCallbackInfo const& args) { "smart graphs"); } } + if (coll->status() == TRI_VOC_COL_STATUS_DELETED || coll->deleted()) { TRI_V8_THROW_EXCEPTION_MESSAGE(TRI_ERROR_ARANGO_DATA_SOURCE_NOT_FOUND, name); } + // smart edge collections contain multiple actual collections std::vector actual = coll->realNamesForRead(); + edgeColls.insert(edgeColls.end(), actual.begin(), actual.end()); } catch (...) { TRI_V8_THROW_EXCEPTION_MESSAGE(TRI_ERROR_ARANGO_DATA_SOURCE_NOT_FOUND, name); diff --git a/arangod/V8Server/v8-views.cpp b/arangod/V8Server/v8-views.cpp index abae7eb94d..3af828bc46 100644 --- a/arangod/V8Server/v8-views.cpp +++ b/arangod/V8Server/v8-views.cpp @@ -218,19 +218,36 @@ static void JS_DropViewVocbase( TRI_V8_THROW_EXCEPTION(TRI_ERROR_ARANGO_DATABASE_NOT_FOUND); } - // we require exactly 1 argument - if (args.Length() != 1) { - TRI_V8_THROW_EXCEPTION_USAGE("_dropView()"); + // we require exactly 1 string argument and an optional boolean argument + if (args.Length() < 1 || args.Length() > 2) { + TRI_V8_THROW_EXCEPTION_USAGE("_dropView( [, allowDropSystem])"); } PREVENT_EMBEDDED_TRANSACTION(); + bool allowDropSystem = false; + + if (args.Length() > 1) { + // options + if (args[1]->IsObject()) { + TRI_GET_GLOBALS(); + v8::Handle optionsObject = args[1].As(); + TRI_GET_GLOBAL_STRING(IsSystemKey); + + if (optionsObject->Has(IsSystemKey)) { + allowDropSystem = TRI_ObjectToBoolean(optionsObject->Get(IsSystemKey)); + } + } else { + allowDropSystem = TRI_ObjectToBoolean(args[1]); + } + } + // extract the name std::string const name = TRI_ObjectToString(args[0]); auto view = vocbase->lookupView(name); if (view) { - auto res = vocbase->dropView(*view).errorNumber(); + auto res = vocbase->dropView(view->id(), allowDropSystem).errorNumber(); if (res != TRI_ERROR_NO_ERROR) { TRI_V8_THROW_EXCEPTION(res); @@ -259,7 +276,25 @@ static void JS_DropViewVocbaseObj( PREVENT_EMBEDDED_TRANSACTION(); - auto res = view->vocbase().dropView(*view).errorNumber(); + bool allowDropSystem = false; + + if (args.Length() > 0) { + // options + if (args[0]->IsObject()) { + TRI_GET_GLOBALS(); + v8::Handle optionsObject = args[0].As(); + TRI_GET_GLOBAL_STRING(IsSystemKey); + + if (optionsObject->Has(IsSystemKey)) { + allowDropSystem = TRI_ObjectToBoolean(optionsObject->Get(IsSystemKey)); + } + } else { + allowDropSystem = TRI_ObjectToBoolean(args[0]); + } + } + + auto res = + view->vocbase().dropView(view->id(), allowDropSystem).errorNumber(); if (res != TRI_ERROR_NO_ERROR) { TRI_V8_THROW_EXCEPTION_MESSAGE(res, "cannot drop view"); diff --git a/arangod/VocBase/LogicalCollection.cpp b/arangod/VocBase/LogicalCollection.cpp index 9199e07b13..9a2dbe843c 100644 --- a/arangod/VocBase/LogicalCollection.cpp +++ b/arangod/VocBase/LogicalCollection.cpp @@ -183,7 +183,6 @@ LogicalCollection::LogicalCollection(LogicalCollection const& other) _status(other.status()), _isSmart(other.isSmart()), _isLocal(false), - _isSystem(other.isSystem()), _waitForSync(other.waitForSync()), _version(other._version), _replicationFactor(other.replicationFactor()), @@ -220,6 +219,8 @@ LogicalCollection::LogicalCollection( ReadPlanId(info, 0), ReadStringValue(info, "name", ""), planVersion, + TRI_vocbase_t::IsSystemName(ReadStringValue(info, "name", "")) + && Helper::readBooleanValue(info, "isSystem", false), Helper::readBooleanValue(info, "deleted", false) ), _internalVersion(0), @@ -231,8 +232,6 @@ LogicalCollection::LogicalCollection( info, "status", TRI_VOC_COL_STATUS_CORRUPTED)), _isSmart(Helper::readBooleanValue(info, "isSmart", false)), _isLocal(!ServerState::instance()->isCoordinator()), - _isSystem(TRI_vocbase_t::IsSystemName(ReadStringValue(info, "name", "")) && - Helper::readBooleanValue(info, "isSystem", false)), _waitForSync(Helper::readBooleanValue(info, "waitForSync", false)), _version(Helper::readNumericValue(info, "version", currentVersion())), @@ -542,8 +541,6 @@ TRI_voc_rid_t LogicalCollection::revision(transaction::Methods* trx) const { bool LogicalCollection::isLocal() const { return _isLocal; } -bool LogicalCollection::isSystem() const { return _isSystem; } - bool LogicalCollection::waitForSync() const { return _waitForSync; } bool LogicalCollection::isSmart() const { return _isSmart; } @@ -765,9 +762,10 @@ void LogicalCollection::toVelocyPackForClusterInventory(VPackBuilder& result, bool useSystem, bool isReady, bool allInSync) const { - if (_isSystem && !useSystem) { + if (system() && !useSystem) { return; } + result.openObject(); result.add(VPackValue("parameters")); @@ -813,7 +811,7 @@ void LogicalCollection::toVelocyPack(VPackBuilder& result, bool translateCids, // Collection Flags result.add("deleted", VPackValue(deleted())); - result.add("isSystem", VPackValue(_isSystem)); + result.add("isSystem", VPackValue(system())); result.add("waitForSync", VPackValue(_waitForSync)); result.add("globallyUniqueId", VPackValue(_globallyUniqueId)); @@ -1362,7 +1360,7 @@ std::string LogicalCollection::generateGloballyUniqueId() const { result.push_back('/'); result.append(name()); } else { // single server - if (isSystem()) { // system collection can't be renamed + if (system()) { // system collection can't be renamed result.append(name()); } else { TRI_ASSERT(id()); diff --git a/arangod/VocBase/LogicalCollection.h b/arangod/VocBase/LogicalCollection.h index 3e3443bc1b..98e9243685 100644 --- a/arangod/VocBase/LogicalCollection.h +++ b/arangod/VocBase/LogicalCollection.h @@ -161,7 +161,6 @@ class LogicalCollection: public LogicalDataSource { // SECTION: Properties TRI_voc_rid_t revision(transaction::Methods*) const; bool isLocal() const; - bool isSystem() const; bool waitForSync() const; bool isSmart() const; bool isAStub() const { return _isAStub; } @@ -391,8 +390,6 @@ class LogicalCollection: public LogicalDataSource { // SECTION: Properties bool _isLocal; - bool const _isSystem; - bool _waitForSync; uint32_t _version; diff --git a/arangod/VocBase/LogicalDataSource.h b/arangod/VocBase/LogicalDataSource.h index 647c6e679c..769220ef3f 100644 --- a/arangod/VocBase/LogicalDataSource.h +++ b/arangod/VocBase/LogicalDataSource.h @@ -91,6 +91,7 @@ class LogicalDataSource { TRI_voc_cid_t planId, std::string&& name, uint64_t planVersion, + bool system, bool deleted ) noexcept : _name(std::move(name)), @@ -100,7 +101,8 @@ class LogicalDataSource { _id(id), _planId(planId ? planId : id), _planVersion(planVersion), - _deleted(deleted) { + _deleted(deleted), + _system(system) { } LogicalDataSource(LogicalDataSource const& other) @@ -111,7 +113,8 @@ class LogicalDataSource { _id(other._id), _planId(other._planId), _planVersion(other._planVersion), - _deleted(other._deleted) { + _deleted(other._deleted), + _system(other._system) { } virtual ~LogicalDataSource() = default; @@ -124,6 +127,7 @@ class LogicalDataSource { TRI_voc_cid_t planId() const noexcept { return _planId; } uint64_t planVersion() const noexcept { return _planVersion; } virtual Result rename(std::string&& newName, bool doSync) = 0; + bool system() const noexcept { return _system; } Type const& type() const noexcept { return _type; } TRI_vocbase_t& vocbase() const noexcept { return _vocbase; } @@ -145,6 +149,7 @@ class LogicalDataSource { // then the version in the agency Plan that underpins // the information in this object. Otherwise 0. bool _deleted; // data-source marked as deleted + bool const _system; // this instance represents a system data-source }; } // arangodb diff --git a/arangod/VocBase/LogicalView.cpp b/arangod/VocBase/LogicalView.cpp index a56982ddb9..3f2078b351 100644 --- a/arangod/VocBase/LogicalView.cpp +++ b/arangod/VocBase/LogicalView.cpp @@ -38,6 +38,24 @@ using Helper = arangodb::basics::VelocyPackHelper; namespace { +bool ReadIsSystem(arangodb::velocypack::Slice info) { + if (!info.isObject()) { + return false; + } + + auto name = + arangodb::basics::VelocyPackHelper::getStringValue(info, "name", ""); + + if (!TRI_vocbase_t::IsSystemName(name)) { + return false; + } + + // same condition as in LogicalCollection + return arangodb::basics::VelocyPackHelper::readBooleanValue( + info, "isSystem", false + ); +} + TRI_voc_cid_t ReadPlanId(VPackSlice info, TRI_voc_cid_t vid) { if (!info.isObject()) { // ERROR CASE @@ -112,6 +130,7 @@ LogicalView::LogicalView( ReadPlanId(definition, 0), arangodb::basics::VelocyPackHelper::getStringValue(definition, "name", ""), planVersion, + ReadIsSystem(definition), Helper::readBooleanValue(definition, "deleted", false) ) { if (!TRI_vocbase_t::IsAllowedName(definition)) { @@ -306,6 +325,7 @@ void DBServerLogicalView::toVelocyPack( if (includeSystem) { result.add("deleted", VPackValue(deleted())); + result.add("isSystem", VPackValue(system())); // FIXME not sure if the following is relevant // Cluster Specific diff --git a/arangod/VocBase/Methods/Collections.cpp b/arangod/VocBase/Methods/Collections.cpp index 89cd7b58b2..a13fad27fb 100644 --- a/arangod/VocBase/Methods/Collections.cpp +++ b/arangod/VocBase/Methods/Collections.cpp @@ -453,7 +453,7 @@ Result Collections::rename(LogicalCollection* coll, std::string const& newName, static Result DropVocbaseColCoordinator(arangodb::LogicalCollection* collection, bool allowDropSystem) { - if (collection->isSystem() && !allowDropSystem) { + if (collection->system() && !allowDropSystem) { return TRI_ERROR_FORBIDDEN; } @@ -502,7 +502,8 @@ Result Collections::drop(TRI_vocbase_t* vocbase, LogicalCollection* coll, res = DropVocbaseColCoordinator(coll, allowDropSystem); #endif } else { - int r = coll->vocbase().dropCollection(coll, allowDropSystem, timeout); + auto r = + coll->vocbase().dropCollection(coll->id(), allowDropSystem, timeout).errorNumber(); if (r != TRI_ERROR_NO_ERROR) { res.reset(r, "cannot drop collection"); diff --git a/arangod/VocBase/vocbase.cpp b/arangod/VocBase/vocbase.cpp index 34ba164b25..dff89baeab 100644 --- a/arangod/VocBase/vocbase.cpp +++ b/arangod/VocBase/vocbase.cpp @@ -1260,12 +1260,27 @@ int TRI_vocbase_t::unloadCollection(arangodb::LogicalCollection* collection, } /// @brief drops a collection -int TRI_vocbase_t::dropCollection(arangodb::LogicalCollection* collection, - bool allowDropSystem, double timeout) { - TRI_ASSERT(collection != nullptr); +arangodb::Result TRI_vocbase_t::dropCollection( + TRI_voc_cid_t cid, + bool allowDropSystem, + double timeout +) { + auto* collection = lookupCollection(cid).get(); + + if (!collection) { + return TRI_ERROR_ARANGO_DATA_SOURCE_NOT_FOUND; + } StorageEngine* engine = EngineSelectorFeature::ENGINE; - if (!allowDropSystem && collection->isSystem() && !engine->inRecovery()) { + + if (!engine) { + return arangodb::Result( + TRI_ERROR_INTERNAL, + std::string("failed to find StorageEngine while dropping collection '") + collection->name() + "'" + ); + } + + if (!allowDropSystem && collection->system() && !engine->inRecovery()) { // prevent dropping of system collections return TRI_set_errno(TRI_ERROR_FORBIDDEN); } @@ -1363,7 +1378,7 @@ int TRI_vocbase_t::renameCollection( std::string const& newName, bool doOverride ) { - if (collection->isSystem()) { + if (collection->system()) { return TRI_set_errno(TRI_ERROR_FORBIDDEN); } @@ -1678,12 +1693,36 @@ std::shared_ptr TRI_vocbase_t::createView( } /// @brief drops a view -arangodb::Result TRI_vocbase_t::dropView(arangodb::LogicalView& view) { +arangodb::Result TRI_vocbase_t::dropView( + TRI_voc_cid_t cid, + bool allowDropSystem +) { + auto view = lookupView(cid); + + if (!view) { + return TRI_ERROR_ARANGO_DATA_SOURCE_NOT_FOUND; + } + + if (!allowDropSystem && view->system()) { + StorageEngine* engine = EngineSelectorFeature::ENGINE; + + if (!engine) { + return arangodb::Result( + TRI_ERROR_INTERNAL, + std::string("failed to find StorageEngine while dropping view '") + view->name() + "'" + ); + } + + if (!engine->inRecovery()) { + return TRI_ERROR_FORBIDDEN; // prevent dropping of system views + } + } + if (ServerState::instance()->isCoordinator()) { ClusterInfo* ci = ClusterInfo::instance(); std::string errorMsg; auto res = - ci->dropViewCoordinator(name(), std::to_string(view.id()), errorMsg); + ci->dropViewCoordinator(name(), std::to_string(view->id()), errorMsg); if (res == TRI_ERROR_NO_ERROR) { return res; @@ -1705,7 +1744,7 @@ arangodb::Result TRI_vocbase_t::dropView(arangodb::LogicalView& view) { RECURSIVE_WRITE_LOCKER_NAMED(writeLocker, _dataSourceLock, _dataSourceLockWriteOwner, basics::ConditionalLocking::DoNotLock); CONDITIONAL_WRITE_LOCKER( - locker, view._lock, basics::ConditionalLocking::DoNotLock + locker, view->_lock, basics::ConditionalLocking::DoNotLock ); while (true) { @@ -1740,18 +1779,18 @@ arangodb::Result TRI_vocbase_t::dropView(arangodb::LogicalView& view) { arangodb::aql::PlanCache::instance()->invalidate(this); arangodb::aql::QueryCache::instance()->invalidate(this); - auto res = view.drop(); + auto res = view->drop(); if (!res.ok()) { return res; } - unregisterView(view); + unregisterView(*view); locker.unlock(); writeLocker.unlock(); - events::DropView(view.name(), TRI_ERROR_NO_ERROR); + events::DropView(view->name(), TRI_ERROR_NO_ERROR); if (DatabaseFeature::DATABASE != nullptr && DatabaseFeature::DATABASE->versionTracker() != nullptr) { diff --git a/arangod/VocBase/vocbase.h b/arangod/VocBase/vocbase.h index 3643bc4a68..bbb593dde4 100644 --- a/arangod/VocBase/vocbase.h +++ b/arangod/VocBase/vocbase.h @@ -280,7 +280,7 @@ struct TRI_vocbase_t { ); /// @brief drops a view - arangodb::Result dropView(arangodb::LogicalView& view); + arangodb::Result dropView(TRI_voc_cid_t cid, bool allowDropSystem); /// @brief returns all known collections with their parameters /// and optionally indexes @@ -348,8 +348,11 @@ struct TRI_vocbase_t { /// @brief drops a collection, no timeout if timeout is < 0.0, otherwise /// timeout is in seconds. Essentially, the timeout counts to acquire the /// write lock for using the collection. - int dropCollection(arangodb::LogicalCollection* collection, - bool allowDropSystem, double timeout); + arangodb::Result dropCollection( + TRI_voc_cid_t cid, + bool allowDropSystem, + double timeout + ); /// @brief callback for collection dropping static bool DropCollectionCallback(arangodb::LogicalCollection* collection); diff --git a/tests/IResearch/IResearchAnalyzerFeature-test.cpp b/tests/IResearch/IResearchAnalyzerFeature-test.cpp index 9d33be09eb..5d1ba7492d 100644 --- a/tests/IResearch/IResearchAnalyzerFeature-test.cpp +++ b/tests/IResearch/IResearchAnalyzerFeature-test.cpp @@ -535,7 +535,7 @@ SECTION("test_persistence") { auto collection = vocbase->lookupCollection("_iresearch_analyzers"); if (collection) { - vocbase->dropCollection(collection.get(), true, -1); + vocbase->dropCollection(collection->id(), true, -1); } collection = vocbase->lookupCollection("_iresearch_analyzers"); @@ -836,7 +836,7 @@ SECTION("test_start") { auto collection = vocbase->lookupCollection("_iresearch_analyzers"); if (collection) { - vocbase->dropCollection(collection.get(), true, -1); + vocbase->dropCollection(collection->id(), true, -1); } collection = vocbase->lookupCollection("_iresearch_analyzers"); @@ -871,7 +871,7 @@ SECTION("test_start") { auto collection = vocbase->lookupCollection("_iresearch_analyzers"); if (collection) { - vocbase->dropCollection(collection.get(), true, -1); + vocbase->dropCollection(collection->id(), true, -1); } collection = vocbase->lookupCollection("_iresearch_analyzers"); @@ -909,7 +909,7 @@ SECTION("test_start") { auto collection = vocbase->lookupCollection("_iresearch_analyzers"); if (collection) { - vocbase->dropCollection(collection.get(), true, -1); + vocbase->dropCollection(collection->id(), true, -1); } collection = vocbase->lookupCollection("_iresearch_analyzers"); @@ -950,7 +950,7 @@ SECTION("test_start") { auto collection = vocbase->lookupCollection("_iresearch_analyzers"); if (collection) { - vocbase->dropCollection(collection.get(), true, -1); + vocbase->dropCollection(collection->id(), true, -1); } collection = vocbase->lookupCollection("_iresearch_analyzers"); @@ -993,7 +993,7 @@ SECTION("test_start") { auto collection = vocbase->lookupCollection("_iresearch_analyzers"); if (collection) { - vocbase->dropCollection(collection.get(), true, -1); + vocbase->dropCollection(collection->id(), true, -1); } collection = vocbase->lookupCollection("_iresearch_analyzers"); @@ -1025,7 +1025,7 @@ SECTION("test_start") { auto collection = vocbase->lookupCollection("_iresearch_analyzers"); if (collection) { - vocbase->dropCollection(collection.get(), true, -1); + vocbase->dropCollection(collection->id(), true, -1); } collection = vocbase->lookupCollection("_iresearch_analyzers"); @@ -1059,7 +1059,7 @@ SECTION("test_start") { auto collection = vocbase->lookupCollection("_iresearch_analyzers"); if (collection) { - vocbase->dropCollection(collection.get(), true, -1); + vocbase->dropCollection(collection->id(), true, -1); } collection = vocbase->lookupCollection("_iresearch_analyzers"); @@ -1097,7 +1097,7 @@ SECTION("test_start") { auto collection = vocbase->lookupCollection("_iresearch_analyzers"); if (collection) { - vocbase->dropCollection(collection.get(), true, -1); + vocbase->dropCollection(collection->id(), true, -1); } collection = vocbase->lookupCollection("_iresearch_analyzers"); @@ -1158,7 +1158,7 @@ SECTION("test_tokens") { auto collection = vocbase->lookupCollection("_iresearch_analyzers"); if (collection) { - vocbase->dropCollection(collection.get(), true, -1); + vocbase->dropCollection(collection->id(), true, -1); } collection = vocbase->lookupCollection("_iresearch_analyzers"); diff --git a/tests/IResearch/IResearchView-test.cpp b/tests/IResearch/IResearchView-test.cpp index 3a4827a8fd..bb3035657d 100644 --- a/tests/IResearch/IResearchView-test.cpp +++ b/tests/IResearch/IResearchView-test.cpp @@ -252,10 +252,11 @@ SECTION("test_defaults") { arangodb::iresearch::IResearchViewMeta meta; std::string error; - CHECK(6 == slice.length()); + CHECK(7 == slice.length()); CHECK(slice.get("name").copyString() == "testView"); CHECK(slice.get("type").copyString() == arangodb::iresearch::DATA_SOURCE_TYPE.name()); CHECK(false == slice.get("deleted").getBool()); + CHECK(false == slice.get("isSystem").getBool()); slice = slice.get("properties"); CHECK(slice.isObject()); CHECK((5U == slice.length())); @@ -335,7 +336,7 @@ SECTION("test_drop") { CHECK((true == logicalCollection->getIndexes().empty())); CHECK((false == !vocbase.lookupView("testView"))); CHECK((true == TRI_IsDirectory(dataPath.c_str()))); - CHECK((true == vocbase.dropView(*view).ok())); + CHECK((true == vocbase.dropView(view->id(), false).ok())); CHECK((true == logicalCollection->getIndexes().empty())); CHECK((true == !vocbase.lookupView("testView"))); CHECK((false == TRI_IsDirectory(dataPath.c_str()))); @@ -373,7 +374,7 @@ SECTION("test_drop_with_link") { CHECK(true == res.ok()); CHECK((false == logicalCollection->getIndexes().empty())); - CHECK((true == vocbase.dropView(*view).ok())); + CHECK((true == vocbase.dropView(view->id(), false).ok())); CHECK((true == logicalCollection->getIndexes().empty())); CHECK((true == !vocbase.lookupView("testView"))); CHECK((false == TRI_IsDirectory(dataPath.c_str()))); @@ -1686,7 +1687,7 @@ SECTION("test_unregister_link") { StorageEngineMock::inRecoveryResult = true; auto restore = irs::make_finally([&before]()->void { StorageEngineMock::inRecoveryResult = before; }); persisted = false; - CHECK((TRI_ERROR_NO_ERROR == vocbase.dropCollection(logicalCollection, true, -1))); + CHECK((true == vocbase.dropCollection(logicalCollection->id(), true, -1).ok())); CHECK((false == persisted)); // link removal does not persist view meta CHECK((nullptr == vocbase.lookupCollection("testCollection"))); @@ -1706,7 +1707,7 @@ SECTION("test_unregister_link") { } CHECK((false == !vocbase.lookupView("testView"))); - CHECK((true == vocbase.dropView(*view).ok())); + CHECK((true == vocbase.dropView(view->id(), false).ok())); CHECK((true == !vocbase.lookupView("testView"))); } @@ -1766,7 +1767,7 @@ SECTION("test_unregister_link") { CHECK((nullptr != vocbase.lookupCollection("testCollection"))); persisted = false; - CHECK((TRI_ERROR_NO_ERROR == vocbase.dropCollection(logicalCollection, true, -1))); + CHECK((true == vocbase.dropCollection(logicalCollection->id(), true, -1).ok())); CHECK((true == persisted)); // collection removal persists view meta CHECK((nullptr == vocbase.lookupCollection("testCollection"))); @@ -1786,7 +1787,7 @@ SECTION("test_unregister_link") { } CHECK((false == !vocbase.lookupView("testView"))); - CHECK((true == vocbase.dropView(*view).ok())); + CHECK((true == vocbase.dropView(view->id(), false).ok())); CHECK((true == !vocbase.lookupView("testView"))); } @@ -1812,10 +1813,10 @@ SECTION("test_unregister_link") { view->visitCollections([&cids](TRI_voc_cid_t cid)->bool { cids.emplace(cid); return true; }); CHECK((1 == cids.size())); CHECK((false == !vocbase.lookupView("testView"))); - CHECK((true == vocbase.dropView(*view).ok())); + CHECK((true == vocbase.dropView(view->id(), false).ok())); CHECK((true == !vocbase.lookupView("testView"))); CHECK((nullptr != vocbase.lookupCollection("testCollection"))); - CHECK((TRI_ERROR_NO_ERROR == vocbase.dropCollection(logicalCollection, true, -1))); + CHECK((true == vocbase.dropCollection(logicalCollection->id(), true, -1).ok())); CHECK((nullptr == vocbase.lookupCollection("testCollection"))); } @@ -1838,7 +1839,7 @@ SECTION("test_unregister_link") { viewImpl->visitCollections([&cids](TRI_voc_cid_t cid)->bool { cids.emplace(cid); return true; }); CHECK((1 == cids.size())); logicalCollection->getIndexes()[0]->unload(); // release view reference to prevent deadlock due to ~IResearchView() waiting for IResearchLink::unload() - CHECK((true == vocbase.dropView(*logicalView).ok())); + CHECK((true == vocbase.dropView(logicalView->id(), false).ok())); CHECK((1 == logicalView.use_count())); // ensure destructor for ViewImplementation is called CHECK((false == logicalCollection->getIndexes().empty())); } @@ -2233,7 +2234,7 @@ SECTION("test_transaction_registration") { } // drop collection from vocbase - CHECK((TRI_ERROR_NO_ERROR == vocbase.dropCollection(logicalCollection1, true, 0))); + CHECK((true == vocbase.dropCollection(logicalCollection1->id(), true, 0).ok())); // read transaction (by id) (one collection dropped) { diff --git a/tests/IResearch/IResearchViewDBServer-test.cpp b/tests/IResearch/IResearchViewDBServer-test.cpp index badb4e1724..b562f67f1e 100644 --- a/tests/IResearch/IResearchViewDBServer-test.cpp +++ b/tests/IResearch/IResearchViewDBServer-test.cpp @@ -457,9 +457,9 @@ SECTION("test_toVelocyPack") { builder.close(); auto slice = builder.slice(); CHECK((3 == slice.length())); + CHECK((slice.hasKey("id") && slice.get("id").isString() && std::string("1") == slice.get("id").copyString())); CHECK((slice.hasKey("name") && slice.get("name").isString() && std::string("testView") == slice.get("name").copyString())); CHECK((slice.hasKey("type") && slice.get("type").isString() && arangodb::iresearch::DATA_SOURCE_TYPE.name() == slice.get("type").copyString())); - CHECK((slice.hasKey("unusedKey") && slice.get("unusedKey").isString() && std::string("unusedValue") == slice.get("unusedKey").copyString())); // ensure the original definition is fully stored } // includeProperties @@ -481,9 +481,9 @@ SECTION("test_toVelocyPack") { builder.close(); auto slice = builder.slice(); CHECK((4 == slice.length())); + CHECK((slice.hasKey("id") && slice.get("id").isString() && std::string("2") == slice.get("id").copyString())); CHECK((slice.hasKey("name") && slice.get("name").isString() && std::string("testView") == slice.get("name").copyString())); CHECK((slice.hasKey("type") && slice.get("type").isString() && arangodb::iresearch::DATA_SOURCE_TYPE.name() == slice.get("type").copyString())); - CHECK((slice.hasKey("unusedKey") && slice.get("unusedKey").isString() && std::string("unusedValue") == slice.get("unusedKey").copyString())); // ensure the original definition is fully stored CHECK((slice.hasKey("properties"))); auto props = slice.get("properties"); CHECK((props.isObject())); @@ -491,7 +491,7 @@ SECTION("test_toVelocyPack") { CHECK((props.hasKey("collections") && props.get("collections").isArray() && 0 == props.get("collections").length())); } - // includeSystem (same as base) + // includeSystem { s.agency->responses.clear(); s.agency->responses["POST /_api/agency/read HTTP/1.1\r\n\r\n[[\"/Sync/LatestID\"]]"] = "http/1.0 200\n\n[ { \"\": { \"Sync\": { \"LatestID\" : 1 } } } ]"; @@ -509,10 +509,13 @@ SECTION("test_toVelocyPack") { wiew->toVelocyPack(builder, false, true); builder.close(); auto slice = builder.slice(); - CHECK((3 == slice.length())); + CHECK((6 == slice.length())); + CHECK((slice.hasKey("deleted") && slice.get("deleted").isBoolean() && false == slice.get("deleted").getBoolean())); + CHECK((slice.hasKey("id") && slice.get("id").isString() && std::string("3") == slice.get("id").copyString())); + CHECK((slice.hasKey("isSystem") && slice.get("isSystem").isBoolean() && false == slice.get("isSystem").getBoolean())); CHECK((slice.hasKey("name") && slice.get("name").isString() && std::string("testView") == slice.get("name").copyString())); + CHECK((slice.hasKey("planId") && slice.get("planId").isString() && std::string("3") == slice.get("planId").copyString())); CHECK((slice.hasKey("type") && slice.get("type").isString() && arangodb::iresearch::DATA_SOURCE_TYPE.name() == slice.get("type").copyString())); - CHECK((slice.hasKey("unusedKey") && slice.get("unusedKey").isString() && std::string("unusedValue") == slice.get("unusedKey").copyString())); // ensure the original definition is fully stored } } @@ -759,7 +762,43 @@ SECTION("test_updateProperties") { } SECTION("test_visitCollections") { - // FIXME TODO implemet + // visit empty + { + s.agency->responses.clear(); + s.agency->responses["POST /_api/agency/read HTTP/1.1\r\n\r\n[[\"/Sync/LatestID\"]]"] = "http/1.0 200\n\n[ { \"\": { \"Sync\": { \"LatestID\" : 1 } } } ]"; + s.agency->responses["POST /_api/agency/write HTTP/1.1"] = "http/1.0 200\n\n{\"results\": []}"; + auto json = arangodb::velocypack::Parser::fromJson("{ \"name\": \"testView\", \"type\": \"arangosearch\" }"); + TRI_vocbase_t vocbase(TRI_vocbase_type_e::TRI_VOCBASE_TYPE_NORMAL, 1, "testVocbase"); + auto wiew = arangodb::iresearch::IResearchViewDBServer::make(vocbase, json->slice(), 42); + CHECK((false == !wiew)); + auto* impl = dynamic_cast(wiew.get()); + CHECK((nullptr != impl)); + + static auto visitor = [](TRI_voc_cid_t)->bool { return false; }; + CHECK((true == wiew->visitCollections(visitor))); // no collections in view + } + + // visit non-empty + { + s.agency->responses.clear(); + s.agency->responses["POST /_api/agency/read HTTP/1.1\r\n\r\n[[\"/Sync/LatestID\"]]"] = "http/1.0 200\n\n[ { \"\": { \"Sync\": { \"LatestID\" : 1 } } } ]"; + s.agency->responses["POST /_api/agency/write HTTP/1.1"] = "http/1.0 200\n\n{\"results\": []}"; + auto json = arangodb::velocypack::Parser::fromJson("{ \"name\": \"testView\", \"type\": \"arangosearch\" }"); + TRI_vocbase_t vocbase(TRI_vocbase_type_e::TRI_VOCBASE_TYPE_NORMAL, 1, "testVocbase"); + auto wiew = arangodb::iresearch::IResearchViewDBServer::make(vocbase, json->slice(), 42); + CHECK((false == !wiew)); + auto* impl = dynamic_cast(wiew.get()); + CHECK((nullptr != impl)); + + auto view = impl->ensure(123); + CHECK((false == !view)); + std::set cids = { 123 }; + static auto visitor = [&cids](TRI_voc_cid_t cid)->bool { return 1 == cids.erase(cid); }; + CHECK((true == wiew->visitCollections(visitor))); // all collections expected + CHECK((true == cids.empty())); + CHECK((true == impl->drop(123).ok())); + CHECK((true == wiew->visitCollections(visitor))); // no collections in view + } } //////////////////////////////////////////////////////////////////////////////// diff --git a/tests/Utils/CollectionNameResolver-test.cpp b/tests/Utils/CollectionNameResolver-test.cpp index 8c4cb6c53a..8d31a8fbe0 100644 --- a/tests/Utils/CollectionNameResolver-test.cpp +++ b/tests/Utils/CollectionNameResolver-test.cpp @@ -233,8 +233,8 @@ SECTION("test_getDataSource") { CHECK((true == !resolver.getView("testViewGUID"))); } - CHECK((TRI_ERROR_NO_ERROR == vocbase.dropCollection(collection, true, 0))); - CHECK((true == vocbase.dropView(*view).ok())); + CHECK((true == vocbase.dropCollection(collection->id(), true, 0).ok())); + CHECK((true == vocbase.dropView(view->id(), true).ok())); CHECK((true == collection->deleted())); CHECK((true == view->deleted())); diff --git a/tests/VocBase/vocbase-test.cpp b/tests/VocBase/vocbase-test.cpp index 5d70208f14..8fde736cbb 100644 --- a/tests/VocBase/vocbase-test.cpp +++ b/tests/VocBase/vocbase-test.cpp @@ -338,8 +338,8 @@ SECTION("test_lookupDataSource") { CHECK((true == !vocbase.lookupView("testViewGUID"))); } - CHECK((TRI_ERROR_NO_ERROR == vocbase.dropCollection(collection, true, 0))); - CHECK((true == vocbase.dropView(*view).ok())); + CHECK((true == vocbase.dropCollection(collection->id(), true, 0).ok())); + CHECK((true == vocbase.dropView(view->id(), true).ok())); CHECK((true == collection->deleted())); CHECK((true == view->deleted()));