1
0
Fork 0

issue 383.3: implement remainder of IResearchViewDBServer tests, use the data-source id (primary key) instead of an arbitrary instance for dropCollection()/dropView(), backport from iresearch upstream: ensure block is flushed if key index is full (#5176)

This commit is contained in:
Vasiliy 2018-04-23 00:33:46 +03:00 committed by Andrey Abramov
parent da4519df43
commit 9062c41592
28 changed files with 342 additions and 206 deletions

View File

@ -1816,9 +1816,12 @@ class index_block {
static const size_t SIZE = Size; static const size_t SIZE = Size;
bool push_back(doc_id_t key, uint64_t offset) { bool push_back(doc_id_t key, uint64_t offset) {
assert(keys_ <= key_); assert(key_ >= keys_);
assert(key_ < keys_ + Size);
*key_++ = key; *key_++ = key;
assert(key >= key_[-1]); assert(key >= key_[-1]);
assert(offset_ >= offsets_);
assert(offset_ < offsets_ + Size);
*offset_++ = offset; *offset_++ = offset;
assert(offset >= offset_[-1]); assert(offset >= offset_[-1]);
return key_ == std::end(keys_); 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 // commit previous key and offset unless the 'reset' method has been called
if (max_ != pending_key_) { 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 // will trigger 'flush_block' if offset >= MAX_DATA_BLOCK_SIZE
offset = offsets_[size_t(block_index_.push_back(pending_key_, offset))]; offset = offsets_[size_t(block_index_.push_back(pending_key_, offset))];
max_ = pending_key_; max_ = pending_key_;

View File

@ -2647,7 +2647,7 @@ std::shared_ptr<LogicalCollection> ClusterMethods::persistCollectionInAgency(
} else { } else {
// system collections should never enforce replicationfactor // system collections should never enforce replicationfactor
// to allow them to come up with 1 dbserver // to allow them to come up with 1 dbserver
if (col->isSystem()) { if (col->system()) {
enforceReplicationFactor = false; enforceReplicationFactor = false;
} }
@ -2685,7 +2685,9 @@ std::shared_ptr<LogicalCollection> ClusterMethods::persistCollectionInAgency(
}), dbServers.end()); }), dbServers.end());
} }
std::random_shuffle(dbServers.begin(), 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()) { if (shards->empty() && !col->isSmart()) {

View File

@ -43,6 +43,12 @@ typedef irs::async_utils::read_write_mutex::write_mutex WriteMutex;
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
const std::string COLLECTIONS_FIELD("collections"); 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 /// @brief the name of the field in the IResearch View definition denoting the
/// view id (from LogicalView.cpp) /// view id (from LogicalView.cpp)
@ -67,12 +73,27 @@ const std::string LINKS_FIELD("links");
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
const std::string NAME_FIELD("name"); 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 /// @brief the name of the field in the IResearch View definition denoting the
/// view properties (from LogicalView.cpp) /// view properties (from LogicalView.cpp)
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
const std::string PROPERTIES_FIELD("properties"); 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_"); static std::string const VIEW_NAME_PREFIX("_iresearch_");
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
@ -130,7 +151,10 @@ IResearchViewDBServer::IResearchViewDBServer(
arangodb::DatabasePathFeature const& dbPathFeature, arangodb::DatabasePathFeature const& dbPathFeature,
uint64_t planVersion uint64_t planVersion
): LogicalView(vocbase, info, planVersion), ): LogicalView(vocbase, info, planVersion),
_meta(info), _meta(
info.isObject() && info.get(PROPERTIES_FIELD).isObject()
? info.get(PROPERTIES_FIELD) : emptyObjectSlice()
),
_persistedPath(getPersistedPath(dbPathFeature, id())) { _persistedPath(getPersistedPath(dbPathFeature, id())) {
} }
@ -143,7 +167,7 @@ arangodb::Result IResearchViewDBServer::drop() {
SCOPED_LOCK(mutex); // 'collections_' can be asynchronously read SCOPED_LOCK(mutex); // 'collections_' can be asynchronously read
for (auto itr = _collections.begin(); itr != _collections.end();) { 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()) { if (!res.ok()) {
return res; // fail on first failure 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); 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()) { if (res.ok()) {
_collections.erase(itr); _collections.erase(itr);
@ -187,45 +211,29 @@ std::shared_ptr<arangodb::LogicalView> IResearchViewDBServer::ensure(
static const std::function<bool(irs::string_ref const& key)> acceptor = []( static const std::function<bool(irs::string_ref const& key)> acceptor = [](
irs::string_ref const& key irs::string_ref const& key
)->bool { )->bool {
// ignored fields return key != COLLECTIONS_FIELD && key != LINKS_FIELD; // ignored fields
return key != ID_FIELD
&& key != IS_SYSTEM_FIELD
&& key != NAME_FIELD
&& key != PROPERTIES_FIELD;
}; };
arangodb::velocypack::Builder builder; arangodb::velocypack::Builder builder;
builder.openObject(); 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(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(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) builder.add(
<< "failure to generate definition while constructing IResearch View in database '" << vocbase().id() << "'"; PROPERTIES_FIELD,
arangodb::velocypack::Value(arangodb::velocypack::ValueType::Object)
);
return nullptr; if (!mergeSliceSkipKeys(builder, _meta.slice(), acceptor)) {
}
auto props = _meta.slice().get(PROPERTIES_FIELD);
if (props.isObject()) {
static const std::function<bool(irs::string_ref const& key)> 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)) {
LOG_TOPIC(WARN, arangodb::iresearch::TOPIC) LOG_TOPIC(WARN, arangodb::iresearch::TOPIC)
<< "failure to generate properties definition while constructing IResearch View in database '" << vocbase().id() << "'"; << "failure to generate properties definition while constructing IResearch View in database '" << vocbase().id() << "'";
return nullptr; return nullptr;
} }
builder.close(); builder.close(); // close PROPERTIES_FIELD
} }
builder.close(); builder.close();
@ -467,7 +475,7 @@ void IResearchViewDBServer::open() {
arangodb::Result IResearchViewDBServer::rename( arangodb::Result IResearchViewDBServer::rename(
std::string&& newName, std::string&& newName,
bool doSync bool /*doSync*/
) { ) {
ReadMutex mutex(_mutex); ReadMutex mutex(_mutex);
SCOPED_LOCK(mutex); // 'collections_' can be asynchronously modified SCOPED_LOCK(mutex); // 'collections_' can be asynchronously modified
@ -482,25 +490,6 @@ arangodb::Result IResearchViewDBServer::rename(
} }
} }
static const std::function<bool(irs::string_ref const& key)> 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)); name(std::move(newName));
return arangodb::Result(); return arangodb::Result();
@ -509,60 +498,54 @@ arangodb::Result IResearchViewDBServer::rename(
void IResearchViewDBServer::toVelocyPack( void IResearchViewDBServer::toVelocyPack(
arangodb::velocypack::Builder& result, arangodb::velocypack::Builder& result,
bool includeProperties, bool includeProperties,
bool /*includeSystem*/ bool includeSystem
) const { ) const {
TRI_ASSERT(result.isOpenObject()); TRI_ASSERT(result.isOpenObject());
ReadMutex mutex(_mutex);
SCOPED_LOCK(mutex); // '_collections'/'_meta' can be asynchronously modified
static const std::function<bool(irs::string_ref const& key)> acceptor = []( result.add(ID_FIELD, arangodb::velocypack::Value(std::to_string(id())));
irs::string_ref const& key result.add(NAME_FIELD, arangodb::velocypack::Value(name()));
)->bool { result.add(TYPE_FIELD, arangodb::velocypack::Value(type().name()));
return key != PROPERTIES_FIELD; // ignored fields
};
if (!mergeSliceSkipKeys(result, _meta.slice(), acceptor)) { if (includeSystem) {
LOG_TOPIC(WARN, arangodb::iresearch::TOPIC) result.add(DELETED_FIELD, arangodb::velocypack::Value(deleted()));
<< "failure to generate definition while for IResearch View in database '" << vocbase().name() << "'"; result.add(IS_SYSTEM_FIELD, arangodb::velocypack::Value(system()));
result.add(PLAN_ID_FIELD, arangodb::velocypack::Value(std::to_string(planId())));
return; // error during output
} }
if (!includeProperties) { if (includeProperties) {
return; // nothing more to output static const std::function<bool(irs::string_ref const& key)> 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<bool(irs::string_ref const& key)> 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( result.add(
COLLECTIONS_FIELD, PROPERTIES_FIELD,
arangodb::velocypack::Value(arangodb::velocypack::ValueType::Array) 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)) { result.close(); // close PROPERTIES_FIELD
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
} }
arangodb::Result IResearchViewDBServer::updateProperties( arangodb::Result IResearchViewDBServer::updateProperties(
@ -605,7 +588,7 @@ arangodb::Result IResearchViewDBServer::updateProperties(
if (partialUpdate) { if (partialUpdate) {
IResearchViewMeta oldMeta; IResearchViewMeta oldMeta;
if (!oldMeta.init(_meta.slice().get(PROPERTIES_FIELD), error) if (!oldMeta.init(_meta.slice(), error)
|| !meta.init(props.slice(), error, oldMeta)) { || !meta.init(props.slice(), error, oldMeta)) {
return arangodb::Result( return arangodb::Result(
TRI_ERROR_BAD_PARAMETER, TRI_ERROR_BAD_PARAMETER,
@ -632,27 +615,10 @@ arangodb::Result IResearchViewDBServer::updateProperties(
// prepare replacement '_meta' // prepare replacement '_meta'
// ........................................................................... // ...........................................................................
static const std::function<bool(irs::string_ref const& key)> acceptor = [](
irs::string_ref const& key
)->bool {
return key != PROPERTIES_FIELD; // ignored fields
};
arangodb::velocypack::Builder builder; arangodb::velocypack::Builder builder;
builder.openObject(); 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)) { if (!meta.json(builder)) {
return arangodb::Result( return arangodb::Result(
TRI_ERROR_INTERNAL, TRI_ERROR_INTERNAL,
@ -660,7 +626,6 @@ arangodb::Result IResearchViewDBServer::updateProperties(
); );
} }
builder.close(); // close PROPERTIES_FIELD
builder.close(); builder.close();
// ........................................................................... // ...........................................................................

View File

@ -709,7 +709,7 @@ bool MMFilesWalRecoverState::ReplayMarker(MMFilesMarker const* marker,
auto otherCid = other->id(); auto otherCid = other->id();
state->releaseCollection(otherCid); 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; break;
} }
vocbase->dropView(*other); vocbase->dropView(other->id(), true);
} }
int res = vocbase->renameView(view, name); int res = vocbase->renameView(view, name);
@ -1058,7 +1058,7 @@ bool MMFilesWalRecoverState::ReplayMarker(MMFilesMarker const* marker,
if (collection != nullptr) { if (collection != nullptr) {
// drop an existing collection // drop an existing collection
vocbase->dropCollection(collection, true, -1.0); vocbase->dropCollection(collection->id(), true, -1.0);
} }
MMFilesPersistentIndexFeature::dropCollection(databaseId, collectionId); MMFilesPersistentIndexFeature::dropCollection(databaseId, collectionId);
@ -1077,7 +1077,7 @@ bool MMFilesWalRecoverState::ReplayMarker(MMFilesMarker const* marker,
auto otherCid = collection->id(); auto otherCid = collection->id();
state->releaseCollection(otherCid); state->releaseCollection(otherCid);
vocbase->dropCollection(collection, true, -1.0); vocbase->dropCollection(otherCid, true, -1.0);
} }
} else { } else {
LOG_TOPIC(WARN, arangodb::Logger::ENGINES) LOG_TOPIC(WARN, arangodb::Logger::ENGINES)
@ -1174,7 +1174,7 @@ bool MMFilesWalRecoverState::ReplayMarker(MMFilesMarker const* marker,
vocbase->lookupView(viewId); vocbase->lookupView(viewId);
if (view != nullptr) { 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 // 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); view = vocbase->lookupView(name);
if (view != nullptr) { if (view != nullptr) {
vocbase->dropView(*view); vocbase->dropView(view->id(), true);
} }
} else { } else {
LOG_TOPIC(WARN, arangodb::Logger::ENGINES) LOG_TOPIC(WARN, arangodb::Logger::ENGINES)
@ -1397,7 +1397,7 @@ bool MMFilesWalRecoverState::ReplayMarker(MMFilesMarker const* marker,
} }
if (collection != nullptr) { if (collection != nullptr) {
vocbase->dropCollection(collection, true, -1.0); vocbase->dropCollection(collection->id(), true, -1.0);
} }
MMFilesPersistentIndexFeature::dropCollection(databaseId, collectionId); MMFilesPersistentIndexFeature::dropCollection(databaseId, collectionId);
break; break;
@ -1427,7 +1427,7 @@ bool MMFilesWalRecoverState::ReplayMarker(MMFilesMarker const* marker,
vocbase->lookupView(viewId); vocbase->lookupView(viewId);
if (view != nullptr) { if (view != nullptr) {
vocbase->dropView(*view); vocbase->dropView(view->id(), true);
} }
break; break;

View File

@ -817,7 +817,9 @@ Result DatabaseInitialSyncer::handleCollection(VPackSlice const& parameters,
// in this case we must drop it because we will run into duplicate // in this case we must drop it because we will run into duplicate
// name conflicts otherwise // name conflicts otherwise
try { 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) { if (res == TRI_ERROR_NO_ERROR) {
col = nullptr; col = nullptr;
} }
@ -876,7 +878,8 @@ Result DatabaseInitialSyncer::handleCollection(VPackSlice const& parameters,
} }
setProgress("dropping " + collectionMsg); 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) { if (res != TRI_ERROR_NO_ERROR) {
return Result(res, std::string("unable to drop ") + collectionMsg + ": " + TRI_errno_string(res)); return Result(res, std::string("unable to drop ") + collectionMsg + ": " + TRI_errno_string(res));

View File

@ -270,7 +270,7 @@ Result GlobalInitialSyncer::updateServerInventory(VPackSlice const& masterDataba
return; return;
} }
if (collection->isSystem()) { if (collection->system()) {
// we will not drop system collections here // we will not drop system collections here
return; return;
} }
@ -280,7 +280,9 @@ Result GlobalInitialSyncer::updateServerInventory(VPackSlice const& masterDataba
for (auto const& collection : toDrop) { for (auto const& collection : toDrop) {
try { 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) { if (res != TRI_ERROR_NO_ERROR) {
LOG_TOPIC(ERR, Logger::FIXME) << "unable to drop collection " << collection->name() << ": " << TRI_errno_string(res); LOG_TOPIC(ERR, Logger::FIXME) << "unable to drop collection " << collection->name() << ": " << TRI_errno_string(res);
} }

View File

@ -584,7 +584,7 @@ Result Syncer::createCollection(TRI_vocbase_t* vocbase,
col = vocbase->lookupCollection(name).get(); col = vocbase->lookupCollection(name).get();
if (col != nullptr) { if (col != nullptr) {
if (col->isSystem()) { if (col->system()) {
TRI_ASSERT(!simulate32Client() || col->globallyUniqueId() == col->name()); TRI_ASSERT(!simulate32Client() || col->globallyUniqueId() == col->name());
SingleCollectionTransaction trx( SingleCollectionTransaction trx(
transaction::StandaloneContext::Create(vocbase), transaction::StandaloneContext::Create(vocbase),
@ -606,7 +606,7 @@ Result Syncer::createCollection(TRI_vocbase_t* vocbase,
return trx.finish(opRes.result); return trx.finish(opRes.result);
} else { } 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();
} }
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 /// @brief creates an index, based on the VelocyPack provided

View File

@ -297,7 +297,8 @@ Result TailingSyncer::processDocument(TRI_replication_operation_e type,
return Result(TRI_ERROR_ARANGO_DATA_SOURCE_NOT_FOUND); return Result(TRI_ERROR_ARANGO_DATA_SOURCE_NOT_FOUND);
} }
bool isSystem = coll->isSystem(); bool isSystem = coll->system();
// extract "data" // extract "data"
VPackSlice const doc = slice.get("data"); VPackSlice const doc = slice.get("data");
@ -576,7 +577,7 @@ Result TailingSyncer::renameCollection(VPackSlice const& slice) {
TRI_ASSERT(col == nullptr); TRI_ASSERT(col == nullptr);
return Result(TRI_ERROR_ARANGO_DATA_SOURCE_NOT_FOUND, "unable to identify collection"); 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(); LOG_TOPIC(WARN, Logger::REPLICATION) << "Renaming system collection " << col->name();
} }
return Result(vocbase->renameCollection(col, name, true)); return Result(vocbase->renameCollection(col, name, true));

View File

@ -85,7 +85,8 @@ void RestCollectionHandler::handleCommandGet() {
ExecContext const* exec = ExecContext::CURRENT; ExecContext const* exec = ExecContext::CURRENT;
bool canUse = exec == nullptr || bool canUse = exec == nullptr ||
exec->canUseCollection(coll->name(), auth::Level::RO); exec->canUseCollection(coll->name(), auth::Level::RO);
if (canUse && (!excludeSystem || !coll->isSystem())) {
if (canUse && (!excludeSystem || !coll->system())) {
collectionRepresentation(builder, coll, collectionRepresentation(builder, coll,
/*showProperties*/ false, /*showProperties*/ false,
/*showFigures*/ false, /*showCount*/ false, /*showFigures*/ false, /*showCount*/ false,
@ -493,7 +494,7 @@ void RestCollectionHandler::collectionRepresentation(
builder.add("type", VPackValue(coll->type())); builder.add("type", VPackValue(coll->type()));
if (!showProperties) { if (!showProperties) {
builder.add("isSystem", VPackValue(coll->isSystem())); builder.add("isSystem", VPackValue(coll->system()));
builder.add("globallyUniqueId", VPackValue(coll->globallyUniqueId())); builder.add("globallyUniqueId", VPackValue(coll->globallyUniqueId()));
} else { } else {
Result res = methods::Collections::properties(coll, builder); Result res = methods::Collections::properties(coll, builder);

View File

@ -909,7 +909,7 @@ Result RestReplicationHandler::processRestoreCollection(
// drop an existing collection if it exists // drop an existing collection if it exists
if (col != nullptr) { if (col != nullptr) {
if (dropExisting) { 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) { if (res.errorNumber() == TRI_ERROR_FORBIDDEN) {
// some collections must not be dropped // some collections must not be dropped
@ -2547,7 +2547,7 @@ int RestReplicationHandler::createCollection(VPackSlice slice,
} }
/* Temporary ASSERTS to prove correctness of new constructor */ /* 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 #ifdef ARANGODB_ENABLE_MAINTAINER_MODE
TRI_voc_cid_t planId = 0; TRI_voc_cid_t planId = 0;
VPackSlice const planIdSlice = slice.get("planId"); VPackSlice const planIdSlice = slice.get("planId");

View File

@ -227,6 +227,7 @@ void RestViewHandler::deleteView() {
} }
std::string const& name = suffixes[0]; std::string const& name = suffixes[0];
auto allowDropSystem = _request->parsedValue("isSystem", false);
auto view = _vocbase.lookupView(name); auto view = _vocbase.lookupView(name);
if (!view) { if (!view) {
@ -238,7 +239,7 @@ void RestViewHandler::deleteView() {
return; return;
} }
auto res = _vocbase.dropView(*view).errorNumber(); auto res = _vocbase.dropView(view->id(), allowDropSystem).errorNumber();
if (res == TRI_ERROR_NO_ERROR) { if (res == TRI_ERROR_NO_ERROR) {
generateOk(rest::ResponseCode::OK, VPackSlice::trueSlice()); generateOk(rest::ResponseCode::OK, VPackSlice::trueSlice());

View File

@ -104,7 +104,7 @@ RocksDBCollection::RocksDBCollection(LogicalCollection* collection,
_primaryIndex(nullptr), _primaryIndex(nullptr),
_cache(nullptr), _cache(nullptr),
_cachePresent(false), _cachePresent(false),
_cacheEnabled(!collection->isSystem() && _cacheEnabled(!collection->system() &&
basics::VelocyPackHelper::readBooleanValue( basics::VelocyPackHelper::readBooleanValue(
info, "cacheEnabled", false)) { info, "cacheEnabled", false)) {
VPackSlice s = info.get("isVolatile"); VPackSlice s = info.get("isVolatile");
@ -163,10 +163,12 @@ void RocksDBCollection::setPath(std::string const&) {
Result RocksDBCollection::updateProperties(VPackSlice const& slice, Result RocksDBCollection::updateProperties(VPackSlice const& slice,
bool doSync) { bool doSync) {
bool isSys = _logicalCollection != nullptr && _logicalCollection->isSystem(); auto isSys = _logicalCollection != nullptr && _logicalCollection->system();
_cacheEnabled = !isSys && basics::VelocyPackHelper::readBooleanValue( _cacheEnabled = !isSys && basics::VelocyPackHelper::readBooleanValue(
slice, "cacheEnabled", _cacheEnabled); slice, "cacheEnabled", _cacheEnabled);
primaryIndex()->setCacheEnabled(_cacheEnabled); primaryIndex()->setCacheEnabled(_cacheEnabled);
if (_cacheEnabled) { if (_cacheEnabled) {
createCache(); createCache();
primaryIndex()->createCache(); primaryIndex()->createCache();

View File

@ -58,7 +58,7 @@ RocksDBIndex::RocksDBIndex(
_cf(cf), _cf(cf),
_cache(nullptr), _cache(nullptr),
_cachePresent(false), _cachePresent(false),
_cacheEnabled(useCache && !collection->isSystem()) { _cacheEnabled(useCache && !collection->system()) {
TRI_ASSERT(cf != nullptr && cf != RocksDBColumnFamily::definitions()); TRI_ASSERT(cf != nullptr && cf != RocksDBColumnFamily::definitions());
if (_cacheEnabled) { if (_cacheEnabled) {
createCache(); createCache();
@ -79,7 +79,7 @@ RocksDBIndex::RocksDBIndex(TRI_idx_iid_t id, LogicalCollection* collection,
_cf(cf), _cf(cf),
_cache(nullptr), _cache(nullptr),
_cachePresent(false), _cachePresent(false),
_cacheEnabled(useCache && !collection->isSystem()) { _cacheEnabled(useCache && !collection->system()) {
TRI_ASSERT(cf != nullptr && cf != RocksDBColumnFamily::definitions()); TRI_ASSERT(cf != nullptr && cf != RocksDBColumnFamily::definitions());
if (_objectId == 0) { if (_objectId == 0) {
@ -163,8 +163,9 @@ void RocksDBIndex::createCache() {
return; return;
} }
TRI_ASSERT(!_collection->isSystem() && TRI_ASSERT(
!ServerState::instance()->isCoordinator()); !_collection->system() && !ServerState::instance()->isCoordinator()
);
TRI_ASSERT(_cache.get() == nullptr); TRI_ASSERT(_cache.get() == nullptr);
TRI_ASSERT(CacheManagerFeature::MANAGER != nullptr); TRI_ASSERT(CacheManagerFeature::MANAGER != nullptr);
LOG_TOPIC(DEBUG, Logger::CACHE) << "Creating index cache"; LOG_TOPIC(DEBUG, Logger::CACHE) << "Creating index cache";

View File

@ -277,8 +277,10 @@ int PhysicalCollection::newObjectForInsert(
// _id // _id
uint8_t* p = builder.add(StaticStrings::IdString, uint8_t* p = builder.add(StaticStrings::IdString,
VPackValuePair(9ULL, VPackValueType::Custom)); VPackValuePair(9ULL, VPackValueType::Custom));
*p++ = 0xf3; // custom type for _id *p++ = 0xf3; // custom type for _id
if (_isDBServer && !_logicalCollection->isSystem()) {
if (_isDBServer && !_logicalCollection->system()) {
// db server in cluster, note: the local collections _statistics, // db server in cluster, note: the local collections _statistics,
// _statisticsRaw and _statistics15 (which are the only system // _statisticsRaw and _statistics15 (which are the only system
// collections) // collections)

View File

@ -1920,10 +1920,12 @@ static void JS_PregelStart(v8::FunctionCallbackInfo<v8::Value> const& args) {
try { try {
auto coll = auto coll =
ClusterInfo::instance()->getCollection(vocbase->name(), name); ClusterInfo::instance()->getCollection(vocbase->name(), name);
if (coll->isSystem()) {
if (coll->system()) {
TRI_V8_THROW_EXCEPTION_USAGE( TRI_V8_THROW_EXCEPTION_USAGE(
"Cannot use pregel on system collection"); "Cannot use pregel on system collection");
} }
if (coll->status() == TRI_VOC_COL_STATUS_DELETED || coll->deleted()) { if (coll->status() == TRI_VOC_COL_STATUS_DELETED || coll->deleted()) {
TRI_V8_THROW_EXCEPTION_MESSAGE(TRI_ERROR_ARANGO_DATA_SOURCE_NOT_FOUND, name); TRI_V8_THROW_EXCEPTION_MESSAGE(TRI_ERROR_ARANGO_DATA_SOURCE_NOT_FOUND, name);
} }
@ -1943,16 +1945,19 @@ static void JS_PregelStart(v8::FunctionCallbackInfo<v8::Value> const& args) {
} }
std::vector<CollectionID> edgeColls; std::vector<CollectionID> edgeColls;
// load edge collection // load edge collection
for (std::string const& name : paramEdges) { for (std::string const& name : paramEdges) {
if (ss->isCoordinator()) { if (ss->isCoordinator()) {
try { try {
auto coll = auto coll =
ClusterInfo::instance()->getCollection(vocbase->name(), name); ClusterInfo::instance()->getCollection(vocbase->name(), name);
if (coll->isSystem()) {
if (coll->system()) {
TRI_V8_THROW_EXCEPTION_USAGE( TRI_V8_THROW_EXCEPTION_USAGE(
"Cannot use pregel on system collection"); "Cannot use pregel on system collection");
} }
if (!coll->isSmart()) { if (!coll->isSmart()) {
std::vector<std::string> eKeys = coll->shardKeys(); std::vector<std::string> eKeys = coll->shardKeys();
if ( eKeys.size() != 1 || eKeys[0] != "vertex") { if ( eKeys.size() != 1 || eKeys[0] != "vertex") {
@ -1961,11 +1966,14 @@ static void JS_PregelStart(v8::FunctionCallbackInfo<v8::Value> const& args) {
"smart graphs"); "smart graphs");
} }
} }
if (coll->status() == TRI_VOC_COL_STATUS_DELETED || coll->deleted()) { if (coll->status() == TRI_VOC_COL_STATUS_DELETED || coll->deleted()) {
TRI_V8_THROW_EXCEPTION_MESSAGE(TRI_ERROR_ARANGO_DATA_SOURCE_NOT_FOUND, name); TRI_V8_THROW_EXCEPTION_MESSAGE(TRI_ERROR_ARANGO_DATA_SOURCE_NOT_FOUND, name);
} }
// smart edge collections contain multiple actual collections // smart edge collections contain multiple actual collections
std::vector<std::string> actual = coll->realNamesForRead(); std::vector<std::string> actual = coll->realNamesForRead();
edgeColls.insert(edgeColls.end(), actual.begin(), actual.end()); edgeColls.insert(edgeColls.end(), actual.begin(), actual.end());
} catch (...) { } catch (...) {
TRI_V8_THROW_EXCEPTION_MESSAGE(TRI_ERROR_ARANGO_DATA_SOURCE_NOT_FOUND, name); TRI_V8_THROW_EXCEPTION_MESSAGE(TRI_ERROR_ARANGO_DATA_SOURCE_NOT_FOUND, name);

View File

@ -218,19 +218,36 @@ static void JS_DropViewVocbase(
TRI_V8_THROW_EXCEPTION(TRI_ERROR_ARANGO_DATABASE_NOT_FOUND); TRI_V8_THROW_EXCEPTION(TRI_ERROR_ARANGO_DATABASE_NOT_FOUND);
} }
// we require exactly 1 argument // we require exactly 1 string argument and an optional boolean argument
if (args.Length() != 1) { if (args.Length() < 1 || args.Length() > 2) {
TRI_V8_THROW_EXCEPTION_USAGE("_dropView(<name>)"); TRI_V8_THROW_EXCEPTION_USAGE("_dropView(<name> [, allowDropSystem])");
} }
PREVENT_EMBEDDED_TRANSACTION(); PREVENT_EMBEDDED_TRANSACTION();
bool allowDropSystem = false;
if (args.Length() > 1) {
// options
if (args[1]->IsObject()) {
TRI_GET_GLOBALS();
v8::Handle<v8::Object> optionsObject = args[1].As<v8::Object>();
TRI_GET_GLOBAL_STRING(IsSystemKey);
if (optionsObject->Has(IsSystemKey)) {
allowDropSystem = TRI_ObjectToBoolean(optionsObject->Get(IsSystemKey));
}
} else {
allowDropSystem = TRI_ObjectToBoolean(args[1]);
}
}
// extract the name // extract the name
std::string const name = TRI_ObjectToString(args[0]); std::string const name = TRI_ObjectToString(args[0]);
auto view = vocbase->lookupView(name); auto view = vocbase->lookupView(name);
if (view) { if (view) {
auto res = vocbase->dropView(*view).errorNumber(); auto res = vocbase->dropView(view->id(), allowDropSystem).errorNumber();
if (res != TRI_ERROR_NO_ERROR) { if (res != TRI_ERROR_NO_ERROR) {
TRI_V8_THROW_EXCEPTION(res); TRI_V8_THROW_EXCEPTION(res);
@ -259,7 +276,25 @@ static void JS_DropViewVocbaseObj(
PREVENT_EMBEDDED_TRANSACTION(); 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<v8::Object> optionsObject = args[0].As<v8::Object>();
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) { if (res != TRI_ERROR_NO_ERROR) {
TRI_V8_THROW_EXCEPTION_MESSAGE(res, "cannot drop view"); TRI_V8_THROW_EXCEPTION_MESSAGE(res, "cannot drop view");

View File

@ -183,7 +183,6 @@ LogicalCollection::LogicalCollection(LogicalCollection const& other)
_status(other.status()), _status(other.status()),
_isSmart(other.isSmart()), _isSmart(other.isSmart()),
_isLocal(false), _isLocal(false),
_isSystem(other.isSystem()),
_waitForSync(other.waitForSync()), _waitForSync(other.waitForSync()),
_version(other._version), _version(other._version),
_replicationFactor(other.replicationFactor()), _replicationFactor(other.replicationFactor()),
@ -220,6 +219,8 @@ LogicalCollection::LogicalCollection(
ReadPlanId(info, 0), ReadPlanId(info, 0),
ReadStringValue(info, "name", ""), ReadStringValue(info, "name", ""),
planVersion, planVersion,
TRI_vocbase_t::IsSystemName(ReadStringValue(info, "name", ""))
&& Helper::readBooleanValue(info, "isSystem", false),
Helper::readBooleanValue(info, "deleted", false) Helper::readBooleanValue(info, "deleted", false)
), ),
_internalVersion(0), _internalVersion(0),
@ -231,8 +232,6 @@ LogicalCollection::LogicalCollection(
info, "status", TRI_VOC_COL_STATUS_CORRUPTED)), info, "status", TRI_VOC_COL_STATUS_CORRUPTED)),
_isSmart(Helper::readBooleanValue(info, "isSmart", false)), _isSmart(Helper::readBooleanValue(info, "isSmart", false)),
_isLocal(!ServerState::instance()->isCoordinator()), _isLocal(!ServerState::instance()->isCoordinator()),
_isSystem(TRI_vocbase_t::IsSystemName(ReadStringValue(info, "name", "")) &&
Helper::readBooleanValue(info, "isSystem", false)),
_waitForSync(Helper::readBooleanValue(info, "waitForSync", false)), _waitForSync(Helper::readBooleanValue(info, "waitForSync", false)),
_version(Helper::readNumericValue<uint32_t>(info, "version", _version(Helper::readNumericValue<uint32_t>(info, "version",
currentVersion())), currentVersion())),
@ -542,8 +541,6 @@ TRI_voc_rid_t LogicalCollection::revision(transaction::Methods* trx) const {
bool LogicalCollection::isLocal() const { return _isLocal; } bool LogicalCollection::isLocal() const { return _isLocal; }
bool LogicalCollection::isSystem() const { return _isSystem; }
bool LogicalCollection::waitForSync() const { return _waitForSync; } bool LogicalCollection::waitForSync() const { return _waitForSync; }
bool LogicalCollection::isSmart() const { return _isSmart; } bool LogicalCollection::isSmart() const { return _isSmart; }
@ -765,9 +762,10 @@ void LogicalCollection::toVelocyPackForClusterInventory(VPackBuilder& result,
bool useSystem, bool useSystem,
bool isReady, bool isReady,
bool allInSync) const { bool allInSync) const {
if (_isSystem && !useSystem) { if (system() && !useSystem) {
return; return;
} }
result.openObject(); result.openObject();
result.add(VPackValue("parameters")); result.add(VPackValue("parameters"));
@ -813,7 +811,7 @@ void LogicalCollection::toVelocyPack(VPackBuilder& result, bool translateCids,
// Collection Flags // Collection Flags
result.add("deleted", VPackValue(deleted())); result.add("deleted", VPackValue(deleted()));
result.add("isSystem", VPackValue(_isSystem)); result.add("isSystem", VPackValue(system()));
result.add("waitForSync", VPackValue(_waitForSync)); result.add("waitForSync", VPackValue(_waitForSync));
result.add("globallyUniqueId", VPackValue(_globallyUniqueId)); result.add("globallyUniqueId", VPackValue(_globallyUniqueId));
@ -1362,7 +1360,7 @@ std::string LogicalCollection::generateGloballyUniqueId() const {
result.push_back('/'); result.push_back('/');
result.append(name()); result.append(name());
} else { // single server } else { // single server
if (isSystem()) { // system collection can't be renamed if (system()) { // system collection can't be renamed
result.append(name()); result.append(name());
} else { } else {
TRI_ASSERT(id()); TRI_ASSERT(id());

View File

@ -161,7 +161,6 @@ class LogicalCollection: public LogicalDataSource {
// SECTION: Properties // SECTION: Properties
TRI_voc_rid_t revision(transaction::Methods*) const; TRI_voc_rid_t revision(transaction::Methods*) const;
bool isLocal() const; bool isLocal() const;
bool isSystem() const;
bool waitForSync() const; bool waitForSync() const;
bool isSmart() const; bool isSmart() const;
bool isAStub() const { return _isAStub; } bool isAStub() const { return _isAStub; }
@ -391,8 +390,6 @@ class LogicalCollection: public LogicalDataSource {
// SECTION: Properties // SECTION: Properties
bool _isLocal; bool _isLocal;
bool const _isSystem;
bool _waitForSync; bool _waitForSync;
uint32_t _version; uint32_t _version;

View File

@ -91,6 +91,7 @@ class LogicalDataSource {
TRI_voc_cid_t planId, TRI_voc_cid_t planId,
std::string&& name, std::string&& name,
uint64_t planVersion, uint64_t planVersion,
bool system,
bool deleted bool deleted
) noexcept ) noexcept
: _name(std::move(name)), : _name(std::move(name)),
@ -100,7 +101,8 @@ class LogicalDataSource {
_id(id), _id(id),
_planId(planId ? planId : id), _planId(planId ? planId : id),
_planVersion(planVersion), _planVersion(planVersion),
_deleted(deleted) { _deleted(deleted),
_system(system) {
} }
LogicalDataSource(LogicalDataSource const& other) LogicalDataSource(LogicalDataSource const& other)
@ -111,7 +113,8 @@ class LogicalDataSource {
_id(other._id), _id(other._id),
_planId(other._planId), _planId(other._planId),
_planVersion(other._planVersion), _planVersion(other._planVersion),
_deleted(other._deleted) { _deleted(other._deleted),
_system(other._system) {
} }
virtual ~LogicalDataSource() = default; virtual ~LogicalDataSource() = default;
@ -124,6 +127,7 @@ class LogicalDataSource {
TRI_voc_cid_t planId() const noexcept { return _planId; } TRI_voc_cid_t planId() const noexcept { return _planId; }
uint64_t planVersion() const noexcept { return _planVersion; } uint64_t planVersion() const noexcept { return _planVersion; }
virtual Result rename(std::string&& newName, bool doSync) = 0; virtual Result rename(std::string&& newName, bool doSync) = 0;
bool system() const noexcept { return _system; }
Type const& type() const noexcept { return _type; } Type const& type() const noexcept { return _type; }
TRI_vocbase_t& vocbase() const noexcept { return _vocbase; } TRI_vocbase_t& vocbase() const noexcept { return _vocbase; }
@ -145,6 +149,7 @@ class LogicalDataSource {
// then the version in the agency Plan that underpins // then the version in the agency Plan that underpins
// the information in this object. Otherwise 0. // the information in this object. Otherwise 0.
bool _deleted; // data-source marked as deleted bool _deleted; // data-source marked as deleted
bool const _system; // this instance represents a system data-source
}; };
} // arangodb } // arangodb

View File

@ -38,6 +38,24 @@ using Helper = arangodb::basics::VelocyPackHelper;
namespace { 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) { TRI_voc_cid_t ReadPlanId(VPackSlice info, TRI_voc_cid_t vid) {
if (!info.isObject()) { if (!info.isObject()) {
// ERROR CASE // ERROR CASE
@ -112,6 +130,7 @@ LogicalView::LogicalView(
ReadPlanId(definition, 0), ReadPlanId(definition, 0),
arangodb::basics::VelocyPackHelper::getStringValue(definition, "name", ""), arangodb::basics::VelocyPackHelper::getStringValue(definition, "name", ""),
planVersion, planVersion,
ReadIsSystem(definition),
Helper::readBooleanValue(definition, "deleted", false) Helper::readBooleanValue(definition, "deleted", false)
) { ) {
if (!TRI_vocbase_t::IsAllowedName(definition)) { if (!TRI_vocbase_t::IsAllowedName(definition)) {
@ -306,6 +325,7 @@ void DBServerLogicalView::toVelocyPack(
if (includeSystem) { if (includeSystem) {
result.add("deleted", VPackValue(deleted())); result.add("deleted", VPackValue(deleted()));
result.add("isSystem", VPackValue(system()));
// FIXME not sure if the following is relevant // FIXME not sure if the following is relevant
// Cluster Specific // Cluster Specific

View File

@ -453,7 +453,7 @@ Result Collections::rename(LogicalCollection* coll, std::string const& newName,
static Result DropVocbaseColCoordinator(arangodb::LogicalCollection* collection, static Result DropVocbaseColCoordinator(arangodb::LogicalCollection* collection,
bool allowDropSystem) { bool allowDropSystem) {
if (collection->isSystem() && !allowDropSystem) { if (collection->system() && !allowDropSystem) {
return TRI_ERROR_FORBIDDEN; return TRI_ERROR_FORBIDDEN;
} }
@ -502,7 +502,8 @@ Result Collections::drop(TRI_vocbase_t* vocbase, LogicalCollection* coll,
res = DropVocbaseColCoordinator(coll, allowDropSystem); res = DropVocbaseColCoordinator(coll, allowDropSystem);
#endif #endif
} else { } 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) { if (r != TRI_ERROR_NO_ERROR) {
res.reset(r, "cannot drop collection"); res.reset(r, "cannot drop collection");

View File

@ -1260,12 +1260,27 @@ int TRI_vocbase_t::unloadCollection(arangodb::LogicalCollection* collection,
} }
/// @brief drops a collection /// @brief drops a collection
int TRI_vocbase_t::dropCollection(arangodb::LogicalCollection* collection, arangodb::Result TRI_vocbase_t::dropCollection(
bool allowDropSystem, double timeout) { TRI_voc_cid_t cid,
TRI_ASSERT(collection != nullptr); bool allowDropSystem,
double timeout
) {
auto* collection = lookupCollection(cid).get();
if (!collection) {
return TRI_ERROR_ARANGO_DATA_SOURCE_NOT_FOUND;
}
StorageEngine* engine = EngineSelectorFeature::ENGINE; 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 // prevent dropping of system collections
return TRI_set_errno(TRI_ERROR_FORBIDDEN); return TRI_set_errno(TRI_ERROR_FORBIDDEN);
} }
@ -1363,7 +1378,7 @@ int TRI_vocbase_t::renameCollection(
std::string const& newName, std::string const& newName,
bool doOverride bool doOverride
) { ) {
if (collection->isSystem()) { if (collection->system()) {
return TRI_set_errno(TRI_ERROR_FORBIDDEN); return TRI_set_errno(TRI_ERROR_FORBIDDEN);
} }
@ -1678,12 +1693,36 @@ std::shared_ptr<arangodb::LogicalView> TRI_vocbase_t::createView(
} }
/// @brief drops a view /// @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()) { if (ServerState::instance()->isCoordinator()) {
ClusterInfo* ci = ClusterInfo::instance(); ClusterInfo* ci = ClusterInfo::instance();
std::string errorMsg; std::string errorMsg;
auto res = 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) { if (res == TRI_ERROR_NO_ERROR) {
return res; return res;
@ -1705,7 +1744,7 @@ arangodb::Result TRI_vocbase_t::dropView(arangodb::LogicalView& view) {
RECURSIVE_WRITE_LOCKER_NAMED(writeLocker, _dataSourceLock, _dataSourceLockWriteOwner, RECURSIVE_WRITE_LOCKER_NAMED(writeLocker, _dataSourceLock, _dataSourceLockWriteOwner,
basics::ConditionalLocking::DoNotLock); basics::ConditionalLocking::DoNotLock);
CONDITIONAL_WRITE_LOCKER( CONDITIONAL_WRITE_LOCKER(
locker, view._lock, basics::ConditionalLocking::DoNotLock locker, view->_lock, basics::ConditionalLocking::DoNotLock
); );
while (true) { while (true) {
@ -1740,18 +1779,18 @@ arangodb::Result TRI_vocbase_t::dropView(arangodb::LogicalView& view) {
arangodb::aql::PlanCache::instance()->invalidate(this); arangodb::aql::PlanCache::instance()->invalidate(this);
arangodb::aql::QueryCache::instance()->invalidate(this); arangodb::aql::QueryCache::instance()->invalidate(this);
auto res = view.drop(); auto res = view->drop();
if (!res.ok()) { if (!res.ok()) {
return res; return res;
} }
unregisterView(view); unregisterView(*view);
locker.unlock(); locker.unlock();
writeLocker.unlock(); writeLocker.unlock();
events::DropView(view.name(), TRI_ERROR_NO_ERROR); events::DropView(view->name(), TRI_ERROR_NO_ERROR);
if (DatabaseFeature::DATABASE != nullptr && if (DatabaseFeature::DATABASE != nullptr &&
DatabaseFeature::DATABASE->versionTracker() != nullptr) { DatabaseFeature::DATABASE->versionTracker() != nullptr) {

View File

@ -280,7 +280,7 @@ struct TRI_vocbase_t {
); );
/// @brief drops a view /// @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 /// @brief returns all known collections with their parameters
/// and optionally indexes /// and optionally indexes
@ -348,8 +348,11 @@ struct TRI_vocbase_t {
/// @brief drops a collection, no timeout if timeout is < 0.0, otherwise /// @brief drops a collection, no timeout if timeout is < 0.0, otherwise
/// timeout is in seconds. Essentially, the timeout counts to acquire the /// timeout is in seconds. Essentially, the timeout counts to acquire the
/// write lock for using the collection. /// write lock for using the collection.
int dropCollection(arangodb::LogicalCollection* collection, arangodb::Result dropCollection(
bool allowDropSystem, double timeout); TRI_voc_cid_t cid,
bool allowDropSystem,
double timeout
);
/// @brief callback for collection dropping /// @brief callback for collection dropping
static bool DropCollectionCallback(arangodb::LogicalCollection* collection); static bool DropCollectionCallback(arangodb::LogicalCollection* collection);

View File

@ -535,7 +535,7 @@ SECTION("test_persistence") {
auto collection = vocbase->lookupCollection("_iresearch_analyzers"); auto collection = vocbase->lookupCollection("_iresearch_analyzers");
if (collection) { if (collection) {
vocbase->dropCollection(collection.get(), true, -1); vocbase->dropCollection(collection->id(), true, -1);
} }
collection = vocbase->lookupCollection("_iresearch_analyzers"); collection = vocbase->lookupCollection("_iresearch_analyzers");
@ -836,7 +836,7 @@ SECTION("test_start") {
auto collection = vocbase->lookupCollection("_iresearch_analyzers"); auto collection = vocbase->lookupCollection("_iresearch_analyzers");
if (collection) { if (collection) {
vocbase->dropCollection(collection.get(), true, -1); vocbase->dropCollection(collection->id(), true, -1);
} }
collection = vocbase->lookupCollection("_iresearch_analyzers"); collection = vocbase->lookupCollection("_iresearch_analyzers");
@ -871,7 +871,7 @@ SECTION("test_start") {
auto collection = vocbase->lookupCollection("_iresearch_analyzers"); auto collection = vocbase->lookupCollection("_iresearch_analyzers");
if (collection) { if (collection) {
vocbase->dropCollection(collection.get(), true, -1); vocbase->dropCollection(collection->id(), true, -1);
} }
collection = vocbase->lookupCollection("_iresearch_analyzers"); collection = vocbase->lookupCollection("_iresearch_analyzers");
@ -909,7 +909,7 @@ SECTION("test_start") {
auto collection = vocbase->lookupCollection("_iresearch_analyzers"); auto collection = vocbase->lookupCollection("_iresearch_analyzers");
if (collection) { if (collection) {
vocbase->dropCollection(collection.get(), true, -1); vocbase->dropCollection(collection->id(), true, -1);
} }
collection = vocbase->lookupCollection("_iresearch_analyzers"); collection = vocbase->lookupCollection("_iresearch_analyzers");
@ -950,7 +950,7 @@ SECTION("test_start") {
auto collection = vocbase->lookupCollection("_iresearch_analyzers"); auto collection = vocbase->lookupCollection("_iresearch_analyzers");
if (collection) { if (collection) {
vocbase->dropCollection(collection.get(), true, -1); vocbase->dropCollection(collection->id(), true, -1);
} }
collection = vocbase->lookupCollection("_iresearch_analyzers"); collection = vocbase->lookupCollection("_iresearch_analyzers");
@ -993,7 +993,7 @@ SECTION("test_start") {
auto collection = vocbase->lookupCollection("_iresearch_analyzers"); auto collection = vocbase->lookupCollection("_iresearch_analyzers");
if (collection) { if (collection) {
vocbase->dropCollection(collection.get(), true, -1); vocbase->dropCollection(collection->id(), true, -1);
} }
collection = vocbase->lookupCollection("_iresearch_analyzers"); collection = vocbase->lookupCollection("_iresearch_analyzers");
@ -1025,7 +1025,7 @@ SECTION("test_start") {
auto collection = vocbase->lookupCollection("_iresearch_analyzers"); auto collection = vocbase->lookupCollection("_iresearch_analyzers");
if (collection) { if (collection) {
vocbase->dropCollection(collection.get(), true, -1); vocbase->dropCollection(collection->id(), true, -1);
} }
collection = vocbase->lookupCollection("_iresearch_analyzers"); collection = vocbase->lookupCollection("_iresearch_analyzers");
@ -1059,7 +1059,7 @@ SECTION("test_start") {
auto collection = vocbase->lookupCollection("_iresearch_analyzers"); auto collection = vocbase->lookupCollection("_iresearch_analyzers");
if (collection) { if (collection) {
vocbase->dropCollection(collection.get(), true, -1); vocbase->dropCollection(collection->id(), true, -1);
} }
collection = vocbase->lookupCollection("_iresearch_analyzers"); collection = vocbase->lookupCollection("_iresearch_analyzers");
@ -1097,7 +1097,7 @@ SECTION("test_start") {
auto collection = vocbase->lookupCollection("_iresearch_analyzers"); auto collection = vocbase->lookupCollection("_iresearch_analyzers");
if (collection) { if (collection) {
vocbase->dropCollection(collection.get(), true, -1); vocbase->dropCollection(collection->id(), true, -1);
} }
collection = vocbase->lookupCollection("_iresearch_analyzers"); collection = vocbase->lookupCollection("_iresearch_analyzers");
@ -1158,7 +1158,7 @@ SECTION("test_tokens") {
auto collection = vocbase->lookupCollection("_iresearch_analyzers"); auto collection = vocbase->lookupCollection("_iresearch_analyzers");
if (collection) { if (collection) {
vocbase->dropCollection(collection.get(), true, -1); vocbase->dropCollection(collection->id(), true, -1);
} }
collection = vocbase->lookupCollection("_iresearch_analyzers"); collection = vocbase->lookupCollection("_iresearch_analyzers");

View File

@ -252,10 +252,11 @@ SECTION("test_defaults") {
arangodb::iresearch::IResearchViewMeta meta; arangodb::iresearch::IResearchViewMeta meta;
std::string error; std::string error;
CHECK(6 == slice.length()); CHECK(7 == slice.length());
CHECK(slice.get("name").copyString() == "testView"); CHECK(slice.get("name").copyString() == "testView");
CHECK(slice.get("type").copyString() == arangodb::iresearch::DATA_SOURCE_TYPE.name()); CHECK(slice.get("type").copyString() == arangodb::iresearch::DATA_SOURCE_TYPE.name());
CHECK(false == slice.get("deleted").getBool()); CHECK(false == slice.get("deleted").getBool());
CHECK(false == slice.get("isSystem").getBool());
slice = slice.get("properties"); slice = slice.get("properties");
CHECK(slice.isObject()); CHECK(slice.isObject());
CHECK((5U == slice.length())); CHECK((5U == slice.length()));
@ -335,7 +336,7 @@ SECTION("test_drop") {
CHECK((true == logicalCollection->getIndexes().empty())); CHECK((true == logicalCollection->getIndexes().empty()));
CHECK((false == !vocbase.lookupView("testView"))); CHECK((false == !vocbase.lookupView("testView")));
CHECK((true == TRI_IsDirectory(dataPath.c_str()))); 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 == logicalCollection->getIndexes().empty()));
CHECK((true == !vocbase.lookupView("testView"))); CHECK((true == !vocbase.lookupView("testView")));
CHECK((false == TRI_IsDirectory(dataPath.c_str()))); CHECK((false == TRI_IsDirectory(dataPath.c_str())));
@ -373,7 +374,7 @@ SECTION("test_drop_with_link") {
CHECK(true == res.ok()); CHECK(true == res.ok());
CHECK((false == logicalCollection->getIndexes().empty())); 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 == logicalCollection->getIndexes().empty()));
CHECK((true == !vocbase.lookupView("testView"))); CHECK((true == !vocbase.lookupView("testView")));
CHECK((false == TRI_IsDirectory(dataPath.c_str()))); CHECK((false == TRI_IsDirectory(dataPath.c_str())));
@ -1686,7 +1687,7 @@ SECTION("test_unregister_link") {
StorageEngineMock::inRecoveryResult = true; StorageEngineMock::inRecoveryResult = true;
auto restore = irs::make_finally([&before]()->void { StorageEngineMock::inRecoveryResult = before; }); auto restore = irs::make_finally([&before]()->void { StorageEngineMock::inRecoveryResult = before; });
persisted = false; 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((false == persisted)); // link removal does not persist view meta
CHECK((nullptr == vocbase.lookupCollection("testCollection"))); CHECK((nullptr == vocbase.lookupCollection("testCollection")));
@ -1706,7 +1707,7 @@ SECTION("test_unregister_link") {
} }
CHECK((false == !vocbase.lookupView("testView"))); 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((true == !vocbase.lookupView("testView")));
} }
@ -1766,7 +1767,7 @@ SECTION("test_unregister_link") {
CHECK((nullptr != vocbase.lookupCollection("testCollection"))); CHECK((nullptr != vocbase.lookupCollection("testCollection")));
persisted = false; 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((true == persisted)); // collection removal persists view meta
CHECK((nullptr == vocbase.lookupCollection("testCollection"))); CHECK((nullptr == vocbase.lookupCollection("testCollection")));
@ -1786,7 +1787,7 @@ SECTION("test_unregister_link") {
} }
CHECK((false == !vocbase.lookupView("testView"))); 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((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; }); view->visitCollections([&cids](TRI_voc_cid_t cid)->bool { cids.emplace(cid); return true; });
CHECK((1 == cids.size())); CHECK((1 == cids.size()));
CHECK((false == !vocbase.lookupView("testView"))); 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((true == !vocbase.lookupView("testView")));
CHECK((nullptr != vocbase.lookupCollection("testCollection"))); 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"))); 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; }); viewImpl->visitCollections([&cids](TRI_voc_cid_t cid)->bool { cids.emplace(cid); return true; });
CHECK((1 == cids.size())); CHECK((1 == cids.size()));
logicalCollection->getIndexes()[0]->unload(); // release view reference to prevent deadlock due to ~IResearchView() waiting for IResearchLink::unload() 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((1 == logicalView.use_count())); // ensure destructor for ViewImplementation is called
CHECK((false == logicalCollection->getIndexes().empty())); CHECK((false == logicalCollection->getIndexes().empty()));
} }
@ -2233,7 +2234,7 @@ SECTION("test_transaction_registration") {
} }
// drop collection from vocbase // 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) // read transaction (by id) (one collection dropped)
{ {

View File

@ -457,9 +457,9 @@ SECTION("test_toVelocyPack") {
builder.close(); builder.close();
auto slice = builder.slice(); auto slice = builder.slice();
CHECK((3 == slice.length())); 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("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("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 // includeProperties
@ -481,9 +481,9 @@ SECTION("test_toVelocyPack") {
builder.close(); builder.close();
auto slice = builder.slice(); auto slice = builder.slice();
CHECK((4 == slice.length())); 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("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("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"))); CHECK((slice.hasKey("properties")));
auto props = slice.get("properties"); auto props = slice.get("properties");
CHECK((props.isObject())); CHECK((props.isObject()));
@ -491,7 +491,7 @@ SECTION("test_toVelocyPack") {
CHECK((props.hasKey("collections") && props.get("collections").isArray() && 0 == props.get("collections").length())); 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.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/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); wiew->toVelocyPack(builder, false, true);
builder.close(); builder.close();
auto slice = builder.slice(); 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("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("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") { 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<arangodb::iresearch::IResearchViewDBServer*>(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<arangodb::iresearch::IResearchViewDBServer*>(wiew.get());
CHECK((nullptr != impl));
auto view = impl->ensure(123);
CHECK((false == !view));
std::set<TRI_voc_cid_t> 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
}
} }
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////

View File

@ -233,8 +233,8 @@ SECTION("test_getDataSource") {
CHECK((true == !resolver.getView("testViewGUID"))); CHECK((true == !resolver.getView("testViewGUID")));
} }
CHECK((TRI_ERROR_NO_ERROR == vocbase.dropCollection(collection, true, 0))); CHECK((true == vocbase.dropCollection(collection->id(), true, 0).ok()));
CHECK((true == vocbase.dropView(*view).ok())); CHECK((true == vocbase.dropView(view->id(), true).ok()));
CHECK((true == collection->deleted())); CHECK((true == collection->deleted()));
CHECK((true == view->deleted())); CHECK((true == view->deleted()));

View File

@ -338,8 +338,8 @@ SECTION("test_lookupDataSource") {
CHECK((true == !vocbase.lookupView("testViewGUID"))); CHECK((true == !vocbase.lookupView("testViewGUID")));
} }
CHECK((TRI_ERROR_NO_ERROR == vocbase.dropCollection(collection, true, 0))); CHECK((true == vocbase.dropCollection(collection->id(), true, 0).ok()));
CHECK((true == vocbase.dropView(*view).ok())); CHECK((true == vocbase.dropView(view->id(), true).ok()));
CHECK((true == collection->deleted())); CHECK((true == collection->deleted()));
CHECK((true == view->deleted())); CHECK((true == view->deleted()));