mirror of https://gitee.com/bigwinds/arangodb
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:
parent
da4519df43
commit
9062c41592
|
@ -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_;
|
||||
|
|
|
@ -2647,7 +2647,7 @@ std::shared_ptr<LogicalCollection> 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<LogicalCollection> 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()) {
|
||||
|
|
|
@ -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<arangodb::LogicalView> IResearchViewDBServer::ensure(
|
|||
static const std::function<bool(irs::string_ref const& key)> 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<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)) {
|
||||
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<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));
|
||||
|
||||
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<bool(irs::string_ref const& key)> 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<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(
|
||||
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<bool(irs::string_ref const& key)> 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();
|
||||
|
||||
// ...........................................................................
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -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());
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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";
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -1920,10 +1920,12 @@ static void JS_PregelStart(v8::FunctionCallbackInfo<v8::Value> 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<v8::Value> const& args) {
|
|||
}
|
||||
|
||||
std::vector<CollectionID> 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<std::string> eKeys = coll->shardKeys();
|
||||
if ( eKeys.size() != 1 || eKeys[0] != "vertex") {
|
||||
|
@ -1961,11 +1966,14 @@ static void JS_PregelStart(v8::FunctionCallbackInfo<v8::Value> 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<std::string> 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);
|
||||
|
|
|
@ -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(<name>)");
|
||||
// we require exactly 1 string argument and an optional boolean argument
|
||||
if (args.Length() < 1 || args.Length() > 2) {
|
||||
TRI_V8_THROW_EXCEPTION_USAGE("_dropView(<name> [, allowDropSystem])");
|
||||
}
|
||||
|
||||
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
|
||||
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<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) {
|
||||
TRI_V8_THROW_EXCEPTION_MESSAGE(res, "cannot drop view");
|
||||
|
|
|
@ -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<uint32_t>(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());
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -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<arangodb::LogicalView> 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) {
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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<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
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
@ -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()));
|
||||
|
||||
|
|
|
@ -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()));
|
||||
|
||||
|
|
Loading…
Reference in New Issue