1
0
Fork 0

issue 399.1: store only transient link information by IResearchViewCoordinator (#5834)

* issue 399.1: store only transient link information by IResearchViewCoordinator

* some fixes
This commit is contained in:
Vasiliy 2018-07-11 21:21:51 +03:00 committed by Andrey Abramov
parent ef6e5dd8df
commit 57d2517bd6
11 changed files with 272 additions and 223 deletions

View File

@ -33,7 +33,7 @@
using namespace arangodb;
using namespace arangodb::aql;
namespace {
std::string const doneString = "DONE";
@ -54,6 +54,13 @@ static std::string const& stateToString(ExecutionState state) {
return unknownString;
}
struct ExecutionBlockTypeHash {
size_t operator()(ExecutionBlock::Type value) const noexcept {
typedef std::underlying_type<decltype(value)>::type UnderlyingType;
return std::hash<UnderlyingType>()(UnderlyingType(value));
}
};
std::unordered_map<std::string, arangodb::aql::ExecutionBlock::Type> const NamesToBlockTypeMap = {
{ "-undefined-", arangodb::aql::ExecutionBlock::Type::_UNDEFINED},
{ "CalculationBlock", arangodb::aql::ExecutionBlock::Type::CALCULATION},
@ -83,23 +90,34 @@ std::unordered_map<std::string, arangodb::aql::ExecutionBlock::Type> const Names
{ "UpsertBlock", arangodb::aql::ExecutionBlock::Type::UPSERT},
{ "ScatterBlock", arangodb::aql::ExecutionBlock::Type::SCATTER},
{ "DistributeBlock", arangodb::aql::ExecutionBlock::Type::DISTRIBUTE},
#ifdef USE_IRESEARCH
{ "IResearchViewBlock", arangodb::aql::ExecutionBlock::Type::IRESEARCH_VIEW},
{ "IResearchViewOrderedBlock", arangodb::aql::ExecutionBlock::Type::IRESEARCH_VIEW_ORDERED},
{ "IResearchViewUnorderedBlock", arangodb::aql::ExecutionBlock::Type::IRESEARCH_VIEW_UNORDERED}
#endif
};
std::unordered_map<arangodb::aql::ExecutionBlock::Type, std::string> blockTypeToNamesMap;
std::unordered_map<
arangodb::aql::ExecutionBlock::Type,
std::reference_wrapper<const std::string>,
ExecutionBlockTypeHash
> blockTypeToNamesMap;
struct BlockTypeToNameMapInitializer {
BlockTypeToNameMapInitializer() {
blockTypeToNamesMap.reserve(NamesToBlockTypeMap.size());
std::for_each(NamesToBlockTypeMap.begin(),
NamesToBlockTypeMap.end(),
[](std::pair<std::string const&, arangodb::aql::ExecutionBlock::Type> const& p) {
blockTypeToNamesMap.emplace(p.second, p.first);
});
}
} initializeBlockTypeToNameMap;
} // namespace
void ExecutionBlock::init() {
blockTypeToNamesMap.reserve(NamesToBlockTypeMap.size());
std::for_each(NamesToBlockTypeMap.begin(),
NamesToBlockTypeMap.end(),
[](std::pair<std::string const&, arangodb::aql::ExecutionBlock::Type> const& p) {
blockTypeToNamesMap.insert(std::make_pair(p.second, p.first));
});
}
ExecutionBlock::ExecutionBlock(ExecutionEngine* engine, ExecutionNode const* ep)
: _engine(engine),
_trx(engine->getQuery()->trx()),

View File

@ -111,9 +111,11 @@ class ExecutionBlock {
UPSERT,
SCATTER,
DISTRIBUTE,
#ifdef USE_IRESEARCH
IRESEARCH_VIEW,
IRESEARCH_VIEW_ORDERED,
IRESEARCH_VIEW_UNORDERED,
#endif
};
// omitted in this list are (because):
// WaitingExecutionBlockMock (mock)
@ -124,7 +126,6 @@ class ExecutionBlock {
static std::string typeToString(Type type);
static Type typeFromString(std::string const& type);
static void init();
public:
/// @brief batch size value

View File

@ -69,47 +69,6 @@ IResearchLinkCoordinator::IResearchLinkCoordinator(
_sparse = true; // always sparse
}
IResearchLinkCoordinator::~IResearchLinkCoordinator() {
if (!_collection || !_view) {
return; // nothing else can be done
}
if (_collection->deleted()
|| TRI_vocbase_col_status_e::TRI_VOC_COL_STATUS_DELETED == _collection->status()) {
_view->drop(_collection->id());
}
}
int IResearchLinkCoordinator::drop() {
if (!_collection) {
return TRI_ERROR_ARANGO_COLLECTION_NOT_LOADED; // '_collection' required
}
if (!_view) {
return TRI_ERROR_ARANGO_COLLECTION_NOT_LOADED; // IResearchView required
}
// if the collection is in the process of being removed then drop it from the view
if (_collection->deleted()
|| TRI_vocbase_col_status_e::TRI_VOC_COL_STATUS_DELETED == _collection->status()) {
// revalidate all links
auto const result = _view->updateProperties(
emptyObjectSlice(), true, false
);
if (!result.ok()) {
LOG_TOPIC(WARN, arangodb::iresearch::TOPIC)
<< "failed to force view link revalidation while unloading dropped IResearch link '" << id()
<< "' for IResearch view '" << _view->id() << "'";
return result.errorNumber();
}
}
// drop it from view
return _view->drop(_collection->id()).errorNumber();
}
bool IResearchLinkCoordinator::operator==(LogicalView const& view) const noexcept {
return _view && _view->id() == view.id();
}
@ -159,7 +118,14 @@ bool IResearchLinkCoordinator::init(VPackSlice definition) {
if (!view) {
LOG_TOPIC(WARN, arangodb::iresearch::TOPIC)
<< "error finding view: '" << viewId << "' for link '" << id() << "'";
<< "error finding view '" << viewId << "' for link '" << id() << "'";
return false;
}
if (!view->emplace(_collection->id(), _collection->name(), definition)) {
LOG_TOPIC(WARN, arangodb::iresearch::TOPIC)
<< "error emplacing link to collection '" << _collection->name() << "' into IResearch view '" << viewId << "' link '" << id() << "'";
return false;
}

View File

@ -43,7 +43,7 @@ class IResearchLinkCoordinator final: public arangodb::Index {
////////////////////////////////////////////////////////////////////////////////
/// @brief destructor
////////////////////////////////////////////////////////////////////////////////
virtual ~IResearchLinkCoordinator();
virtual ~IResearchLinkCoordinator() = default;
////////////////////////////////////////////////////////////////////////////////
/// @brief does this IResearch Link reference the supplied view
@ -74,7 +74,7 @@ class IResearchLinkCoordinator final: public arangodb::Index {
virtual bool canBeDropped() const override { return true; }
virtual int drop() override;
virtual int drop() override { return TRI_ERROR_NO_ERROR; }
////////////////////////////////////////////////////////////////////////////////
/// @brief finds first link between specified collection and view

View File

@ -733,12 +733,13 @@ IResearchView::IResearchView(
it->_next = _memoryNodes;
auto* viewPtr = this;
auto* iresearchFeature = arangodb::application_features::ApplicationServer::lookupFeature<
_asyncFeature = arangodb::application_features::ApplicationServer::lookupFeature<
arangodb::iresearch::IResearchFeature
>();
// add asynchronous commit tasks
if (iresearchFeature) {
if (_asyncFeature) {
struct State: public IResearchViewMeta::CommitMeta {
size_t _cleanupIntervalCount;
std::chrono::system_clock::time_point _last;
@ -817,8 +818,7 @@ IResearchView::IResearchView(
state
);
iresearchFeature->async(self(), 0, std::move(task));
_asyncFeature = iresearchFeature;
_asyncFeature->async(self(), 0, std::move(task));
}
}

View File

@ -40,7 +40,9 @@
namespace {
using namespace arangodb::basics;
typedef irs::async_utils::read_write_mutex::read_mutex ReadMutex;
typedef irs::async_utils::read_write_mutex::write_mutex WriteMutex;
using namespace arangodb::iresearch;
arangodb::Result dropLink(
@ -127,9 +129,10 @@ arangodb::Result updateLinks(
return {
TRI_ERROR_BAD_PARAMETER,
std::string("error parsing link parameters from json for IResearch view '")
+ StringUtils::itoa(view.id())
+ view.name()
+ "' offset '"
+ StringUtils::itoa(linksItr.index()) + '"'
+ std::to_string(linksItr.index())
+ '"'
};
}
@ -208,8 +211,9 @@ arangodb::Result updateLinks(
return {
TRI_ERROR_ARANGO_INDEX_NOT_FOUND,
std::string("no link between view '")
+ StringUtils::itoa(view.id())
+ "' and collection '" + StringUtils::itoa(cid)
+ view.name()
+ "' and collection '"
+ std::to_string(cid)
+ "' found"
};
}
@ -221,7 +225,7 @@ arangodb::Result updateLinks(
auto link = currentLinks.get(collection->name());
if (!link.isObject()) {
auto const collectiondId = StringUtils::itoa(collection->id());
auto const collectiondId = std::to_string(collection->id());
link = currentLinks.get(collectiondId);
if (!link.isObject()) {
@ -256,7 +260,7 @@ namespace iresearch {
arangodb::Result IResearchViewCoordinator::appendVelocyPack(
arangodb::velocypack::Builder& builder,
bool detailed,
bool //forPersistence
bool forPersistence
) const {
if (!builder.isOpenObject()) {
return arangodb::Result(
@ -279,12 +283,29 @@ arangodb::Result IResearchViewCoordinator::appendVelocyPack(
arangodb::velocypack::Value(arangodb::velocypack::ValueType::Object)
);
_meta.json(builder); // regular properites
_metaState.json(builder); // regular properites
auto links = _links.slice();
arangodb::velocypack::Builder links;
IResearchViewMetaState metaState;
if (links.isObject() && links.length()) {
builder.add(StaticStrings::LinksField, links);
{
ReadMutex mutex(_mutex);
SCOPED_LOCK(mutex); // '_collections' can be asynchronously modified
links.openObject();
for (auto& entry: _collections) {
links.add(entry.second.first, entry.second.second.slice());
metaState._collections.emplace(entry.first);
}
links.close();
}
metaState.json(builder); // FIXME TODO remove and fix JavaScript tests (no longer required)
// links are not persisted, their definitions are part of the corresponding collections
if (!forPersistence) {
builder.add(StaticStrings::LinksField, links.slice());
}
builder.close(); // close PROPERTIES_FIELD
@ -292,6 +313,42 @@ arangodb::Result IResearchViewCoordinator::appendVelocyPack(
return arangodb::Result();
}
bool IResearchViewCoordinator::emplace(
TRI_voc_cid_t cid,
std::string const& key,
arangodb::velocypack::Slice const& value
) {
static const std::function<bool(irs::string_ref const& key)> acceptor = [](
irs::string_ref const& key
)->bool {
return key != arangodb::StaticStrings::IndexType
&& key != StaticStrings::ViewIdField; // ignored fields
};
arangodb::velocypack::Builder builder;
builder.openObject();
// strip internal keys (added in createLink(...)) from externally visible link definition
if (!mergeSliceSkipKeys(builder, value, acceptor)) {
LOG_TOPIC(WARN, iresearch::TOPIC)
<< "failed to generate externally visible link definition while emplacing link definition into IResearch view '"
<< name() << "' collection '" << cid << "'";
return false;
}
builder.close();
WriteMutex mutex(_mutex);
SCOPED_LOCK(mutex); // '_collections' can be asynchronously read
return _collections.emplace(
std::piecewise_construct,
std::forward_as_tuple(cid),
std::forward_as_tuple(key, std::move(builder))
).second;
}
/*static*/ std::shared_ptr<LogicalView> IResearchViewCoordinator::make(
TRI_vocbase_t& vocbase,
velocypack::Slice const& info,
@ -307,53 +364,13 @@ arangodb::Result IResearchViewCoordinator::appendVelocyPack(
auto& properties = props.isObject() ? props : emptyObjectSlice(); // if no 'props' then assume defaults
std::string error;
if (!view->_meta.init(properties, error)
|| !view->_metaState.init(properties, error)) {
if (!view->_meta.init(properties, error)) {
LOG_TOPIC(WARN, iresearch::TOPIC)
<< "failed to initialize IResearch view from definition, error: " << error;
return nullptr;
}
auto const links = properties.get(StaticStrings::LinksField);
IResearchLinkMeta linkMeta;
if (links.isObject()) {
auto& builder = view->_links;
VPackObjectBuilder guard(&builder);
size_t idx = 0;
for (auto link : velocypack::ObjectIterator(links)) {
auto const nameSlice = link.key;
if (!nameSlice.isString()) {
LOG_TOPIC(WARN, iresearch::TOPIC)
<< "failed to initialize IResearch view link from definition at index " << idx
<< ", link name is not string";
return nullptr;
}
if (!linkMeta.init(link.value, error)) {
LOG_TOPIC(WARN, iresearch::TOPIC)
<< "failed to initialize IResearch view link from definition at index " << idx
<< ", error: " << error;
return nullptr;
}
// append normalized link definition
{
VPackValueLength length;
char const* name = nameSlice.getString(length);
builder.add(name, length, VPackValue(VPackValueType::Object));
linkMeta.json(builder);
builder.close();
}
}
}
if (preCommit && !preCommit(view)) {
LOG_TOPIC(ERR, arangodb::iresearch::TOPIC)
<< "Failure during pre-commit while constructing IResearch View in database '" << vocbase.id() << "'";
@ -411,8 +428,11 @@ IResearchViewCoordinator::IResearchViewCoordinator(
bool IResearchViewCoordinator::visitCollections(
CollectionVisitor const& visitor
) const {
for (auto& cid: _metaState._collections) {
if (!visitor(cid)) {
ReadMutex mutex(_mutex);
SCOPED_LOCK(mutex); // '_collections' can be asynchronously modified
for (auto& entry: _collections) {
if (!visitor(entry.first)) {
return false;
}
}
@ -427,7 +447,6 @@ arangodb::Result IResearchViewCoordinator::updateProperties(
) {
try {
IResearchViewMeta meta;
IResearchViewMetaState metaState;
std::string error;
auto const& defaults = partialUpdate
@ -438,53 +457,85 @@ arangodb::Result IResearchViewCoordinator::updateProperties(
return { TRI_ERROR_BAD_PARAMETER, error };
}
VPackBuilder builder;
{
VPackObjectBuilder const guard(&builder);
// only trigger persisting of properties if they have changed
if (_meta != meta) {
auto* engine = arangodb::ClusterInfo::instance();
// system properties
toVelocyPack(builder, false, true);
if (!engine) {
return arangodb::Result(
TRI_ERROR_INTERNAL,
std::string("failure to get storage engine while updating IResearch View '") + name() + "'"
);
}
// properties
{
VPackObjectBuilder const guard(&builder, StaticStrings::PropertiesField);
arangodb::velocypack::Builder builder;
// links
{
VPackObjectBuilder const guard(&builder, StaticStrings::LinksField);
builder.openObject();
builder.add(
StaticStrings::PropertiesField,
arangodb::velocypack::Value(arangodb::velocypack::ValueType::Object)
);
meta.json(builder);
builder.close(); // close PROPERTIES_FIELD
bool modified = false;
auto const res = updateLinks(
properties.get(StaticStrings::LinksField),
_links.slice(),
*this,
partialUpdate,
_metaState._collections,
modified,
builder,
metaState._collections
);
auto result = toVelocyPack(builder, false, true);
if (!res.ok()) {
return res;
}
if (!modified && _meta == meta && _metaState == metaState) {
// nothing to do
return {};
}
if (!result.ok()) {
return result;
}
// meta
meta.json(builder);
metaState.json(builder);
builder.close();
result = engine->setViewPropertiesCoordinator(
vocbase().name(), std::to_string(id()), builder.slice()
);
if (!result.ok()) {
return result;
}
}
return ClusterInfo::instance()->setViewPropertiesCoordinator(
vocbase().name(), // database name,
StringUtils::itoa(id()), // cluster-wide view id
builder.slice()
if (!properties.hasKey(StaticStrings::LinksField)) {
return arangodb::Result(); // nothing more to do
}
// ...........................................................................
// update links if requested (on a best-effort basis)
// indexing of collections is done in different threads so no locks can be held and rollback is not possible
// as a result it's also possible for links to be simultaneously modified via a different callflow (e.g. from collections)
// ...........................................................................
arangodb::velocypack::Builder currentLinks;
std::unordered_set<TRI_voc_cid_t> currentCids;
{
ReadMutex mutex(_mutex);
SCOPED_LOCK(mutex); // '_collections' can be asynchronously modified
currentLinks.openObject();
for (auto& entry: _collections) {
currentCids.emplace(entry.first);
currentLinks.add(entry.second.first, entry.second.second.slice());
}
currentLinks.close();
}
arangodb::velocypack::Builder viewNewProperties;
bool modified = false;
std::unordered_set<TRI_voc_cid_t> newCids;
viewNewProperties.openObject();
return updateLinks(
properties.get(StaticStrings::LinksField),
currentLinks.slice(),
*this,
partialUpdate,
currentCids,
modified,
viewNewProperties,
newCids
);
} catch (std::exception const& e) {
LOG_TOPIC(WARN, iresearch::TOPIC)
@ -510,8 +561,22 @@ arangodb::Result IResearchViewCoordinator::updateProperties(
Result IResearchViewCoordinator::drop() {
// drop links first
{
auto const res = updateProperties(
VPackSlice::emptyObjectSlice(), false, true
std::unordered_set<TRI_voc_cid_t> currentCids;
visitCollections([&currentCids](TRI_voc_cid_t cid)->bool { currentCids.emplace(cid); return true; });
arangodb::velocypack::Builder builder;
bool modified;
std::unordered_set<TRI_voc_cid_t> newCids;
auto res = updateLinks(
arangodb::velocypack::Slice::emptyObjectSlice(),
arangodb::velocypack::Slice::emptyObjectSlice(),
*this,
false,
currentCids,
modified,
builder,
newCids
);
if (!res.ok()) {
@ -539,26 +604,6 @@ Result IResearchViewCoordinator::drop() {
return {};
}
Result IResearchViewCoordinator::drop(TRI_voc_cid_t cid) {
auto cid_itr = _metaState._collections.find(cid);
if (cid_itr == _metaState._collections.end()) {
// no such cid
return { TRI_ERROR_BAD_PARAMETER };
}
VPackBuilder builder;
{
VPackObjectBuilder const guard(&builder);
{
VPackObjectBuilder const guard(&builder, StaticStrings::LinksField);
builder.add(StringUtils::itoa(cid), VPackSlice::nullSlice());
}
}
return updateProperties(builder.slice(), true, true);
}
} // iresearch
} // arangodb

View File

@ -40,6 +40,22 @@ namespace iresearch {
///////////////////////////////////////////////////////////////////////////////
class IResearchViewCoordinator final : public arangodb::LogicalView {
public:
////////////////////////////////////////////////////////////////////////////////
/// @brief acquire locks on the specified 'cid' during read-transactions
/// allowing retrieval of documents contained in the aforementioned
/// collection
/// @note definitions are not persisted
/// @param cid the collection ID to track
/// @param key the key of the link definition for use in appendVelocyPack(...)
/// @param value the link definition to use in appendVelocyPack(...)
/// @return the 'cid' was newly added to the IResearch View
////////////////////////////////////////////////////////////////////////////////
bool emplace(
TRI_voc_cid_t cid,
std::string const& key,
arangodb::velocypack::Slice const& value
);
///////////////////////////////////////////////////////////////////////////////
/// @brief view factory
/// @returns initialized view object
@ -60,9 +76,6 @@ class IResearchViewCoordinator final : public arangodb::LogicalView {
Result drop() override;
// drops collection from a view
Result drop(TRI_voc_cid_t cid);
virtual Result rename(
std::string&& /*newName*/,
bool /*doSync*/
@ -89,10 +102,9 @@ class IResearchViewCoordinator final : public arangodb::LogicalView {
TRI_vocbase_t& vocbase, velocypack::Slice info, uint64_t planVersion
);
std::unordered_map<TRI_voc_cid_t, std::pair<std::string, arangodb::velocypack::Builder>> _collections; // transient member, not persisted
mutable irs::async_utils::read_write_mutex _mutex; // for use with '_collections'
IResearchViewMeta _meta;
IResearchViewMetaState _metaState;
velocypack::Builder _links;
}; // IResearchViewCoordinator
} // iresearch

View File

@ -73,7 +73,6 @@ void AqlFeature::start() {
MUTEX_LOCKER(locker, AqlFeature::_aqlFeatureMutex);
TRI_ASSERT(_AQL == nullptr);
_AQL = this;
aql::ExecutionBlock::init();
LOG_TOPIC(DEBUG, Logger::QUERIES) << "AQL feature started";
}

View File

@ -239,9 +239,9 @@ static void JS_DropViewVocbase(
auto view = vocbase.lookupView(name);
if (view) {
auto res = vocbase.dropView(view->id(), allowDropSystem).errorNumber();
auto res = vocbase.dropView(view->id(), allowDropSystem);
if (res != TRI_ERROR_NO_ERROR) {
if (!res.ok()) {
TRI_V8_THROW_EXCEPTION(res);
}
}
@ -285,11 +285,10 @@ static void JS_DropViewVocbaseObj(
}
}
auto res =
view->vocbase().dropView(view->id(), allowDropSystem).errorNumber();
auto res = view->vocbase().dropView(view->id(), allowDropSystem);
if (res != TRI_ERROR_NO_ERROR) {
TRI_V8_THROW_EXCEPTION_MESSAGE(res, "cannot drop view");
if (!res.ok()) {
TRI_V8_THROW_EXCEPTION(res);
}
TRI_V8_RETURN_UNDEFINED();

View File

@ -110,23 +110,22 @@ function IResearchFeatureDDLTestSuite () {
}
},
//FIXME
// testRemoveLinkViaCollection : function() {
// db._drop("TestCollection0");
// db._dropView("TestView");
//
// var view = db._createView("TestView", "arangosearch", {});
// db._create("TestCollection0");
// var addLink = { links: { "TestCollection0": {} } };
// view.properties(addLink, true); // partial update
// properties = view.properties();
// assertTrue(Array === properties.collections.constructor);
// assertEqual(1, properties.collections.length);
// db._drop("TestCollection0");
// properties = view.properties();
// assertTrue(Array === properties.collections.constructor);
// assertEqual(0, properties.collections.length);
// },
testRemoveLinkViaCollection : function() {
db._drop("TestCollection0");
db._dropView("TestView");
var view = db._createView("TestView", "arangosearch", {});
db._create("TestCollection0");
var addLink = { links: { "TestCollection0": {} } };
view.properties(addLink, true); // partial update
properties = view.properties();
assertTrue(Array === properties.collections.constructor);
assertEqual(1, properties.collections.length);
db._drop("TestCollection0");
properties = view.properties();
assertTrue(Array === properties.collections.constructor);
assertEqual(0, properties.collections.length);
},
testViewDDL: function() {
// collections

View File

@ -40,6 +40,7 @@
#include "Agency/Store.h"
#include "Basics/ArangoGlobalContext.h"
#include "Basics/files.h"
#include "VocBase/Methods/Indexes.h"
#if USE_ENTERPRISE
#include "Enterprise/Ldap/LdapFeature.h"
@ -256,15 +257,12 @@ SECTION("test_rename") {
}
SECTION("visit_collections") {
auto json = arangodb::velocypack::Parser::fromJson(
"{ \"name\": \"testView\", \"type\": \"arangosearch\", \"id\": \"1\", \"properties\": { \"collections\": [1,2,3] } }");
auto json = arangodb::velocypack::Parser::fromJson("{ \"name\": \"testView\", \"type\": \"arangosearch\", \"id\": \"1\" }");
Vocbase vocbase(TRI_vocbase_type_e::TRI_VOCBASE_TYPE_COORDINATOR, 1, "testVocbase");
auto view = arangodb::LogicalView::create(vocbase, json->slice(), false); // false == do not persist
auto logicalView = arangodb::LogicalView::create(vocbase, json->slice(), false); // false == do not persist
auto* view = dynamic_cast<arangodb::iresearch::IResearchViewCoordinator*>(logicalView.get());
CHECK(nullptr != view);
CHECK(nullptr != std::dynamic_pointer_cast<arangodb::iresearch::IResearchViewCoordinator>(view));
CHECK(0 == view->planVersion());
CHECK("testView" == view->name());
CHECK(false == view->deleted());
@ -273,6 +271,10 @@ SECTION("visit_collections") {
CHECK(arangodb::LogicalView::category() == view->category());
CHECK(&vocbase == &view->vocbase());
CHECK((true == view->emplace(1, "1", arangodb::velocypack::Slice::emptyObjectSlice())));
CHECK((true == view->emplace(2, "2", arangodb::velocypack::Slice::emptyObjectSlice())));
CHECK((true == view->emplace(3, "3", arangodb::velocypack::Slice::emptyObjectSlice())));
// visit view
TRI_voc_cid_t expectedCollections[] = {1,2,3};
auto* begin = expectedCollections;
@ -353,8 +355,8 @@ SECTION("test_defaults") {
CHECK(!slice.hasKey("deleted"));
slice = slice.get("properties");
CHECK(slice.isObject());
CHECK((3 == slice.length()));
CHECK((!slice.hasKey("links")));
CHECK((4 == slice.length()));
CHECK((slice.hasKey("links") && slice.get("links").isObject() && 0 == slice.get("links").length()));
CHECK((meta.init(slice, error) && expectedMeta == meta));
CHECK((true == metaState.init(slice, error) && expectedMetaState == metaState));
}
@ -899,7 +901,7 @@ SECTION("test_update_links_partial_remove") {
// testCollection2
{
auto const value = linksSlice.get(std::to_string(logicalCollection2->id()));
auto const value = linksSlice.get(logicalCollection2->name());
CHECK(value.isObject());
arangodb::iresearch::IResearchLinkMeta expectedMeta;
@ -1631,7 +1633,7 @@ SECTION("test_update_links_partial_add") {
// testCollection2
{
auto const value = linksSlice.get(std::to_string(logicalCollection2->id()));
auto const value = linksSlice.get(logicalCollection2->name());
CHECK(value.isObject());
arangodb::iresearch::IResearchLinkMeta expectedMeta;
@ -2192,7 +2194,7 @@ SECTION("test_update_links_replace") {
// testCollection2
{
auto const value = linksSlice.get(std::to_string(logicalCollection2->id()));
auto const value = linksSlice.get(logicalCollection2->name());
CHECK(value.isObject());
arangodb::iresearch::IResearchLinkMeta expectedMeta;
@ -2521,7 +2523,7 @@ SECTION("test_update_links_clear") {
// explicitly specify id for the sake of tests
auto linksJson = arangodb::velocypack::Parser::fromJson(
"{ \"links\" : {"
"{ \"locale\": \"en\", \"links\" : {"
" \"testCollection1\" : { \"id\": \"1\", \"includeAllFields\" : true }, "
" \"2\" : { \"id\": \"2\", \"trackListPositions\" : true }, "
" \"testCollection3\" : { \"id\": \"3\" } "
@ -2588,7 +2590,7 @@ SECTION("test_update_links_clear") {
// testCollection2
{
auto const value = linksSlice.get(std::to_string(logicalCollection2->id()));
auto const value = linksSlice.get(logicalCollection2->name());
CHECK(value.isObject());
arangodb::iresearch::IResearchLinkMeta expectedMeta;
@ -2771,7 +2773,7 @@ SECTION("test_update_links_clear") {
CHECK(arangodb::AgencyComm().setValue(currentCollection3Path, value->slice(), 0.0).successful());
}
auto const updateJson = arangodb::velocypack::Parser::fromJson("{}");
auto const updateJson = arangodb::velocypack::Parser::fromJson("{ \"links\": {}}");
CHECK(view->updateProperties(updateJson->slice(), false, true).ok());
CHECK(planVersion < arangodb::tests::getCurrentPlanVersion()); // plan version changed
planVersion = arangodb::tests::getCurrentPlanVersion();
@ -2803,7 +2805,10 @@ SECTION("test_update_links_clear") {
info.close();
auto const properties = info.slice().get("properties");
CHECK(!properties.hasKey(arangodb::iresearch::StaticStrings::LinksField));
CHECK((properties.hasKey(arangodb::iresearch::StaticStrings::LinksField)));
auto links = properties.get(arangodb::iresearch::StaticStrings::LinksField);
CHECK((links.isObject()));
CHECK((0 == links.length()));
}
// test index in testCollection1
@ -2899,7 +2904,6 @@ SECTION("test_drop_link") {
REQUIRE(view);
auto const viewId = std::to_string(view->planId());
CHECK("42" == viewId);
CHECK(TRI_ERROR_BAD_PARAMETER == view->drop(logicalCollection->id()).errorNumber()); // unable to drop nonexistent link
// simulate heartbeat thread (create index in current)
{
@ -2965,6 +2969,8 @@ SECTION("test_drop_link") {
CHECK(expectedMeta == actualMeta);
}
TRI_idx_iid_t linkId;
// check indexes
{
// get new version from plan
@ -2972,6 +2978,7 @@ SECTION("test_drop_link") {
REQUIRE(updatedCollection);
auto link = arangodb::iresearch::IResearchLinkCoordinator::find(*updatedCollection, *view);
CHECK(link);
linkId = link->id();
auto index = std::dynamic_pointer_cast<arangodb::Index>(link);
REQUIRE((false == !index));
@ -3021,7 +3028,7 @@ SECTION("test_drop_link") {
}
// drop link
CHECK(view->drop(logicalCollection->id()).ok());
CHECK((arangodb::methods::Indexes::drop(logicalCollection.get(), arangodb::velocypack::Parser::fromJson(std::to_string(linkId))->slice()).ok()));
CHECK(planVersion < arangodb::tests::getCurrentPlanVersion()); // plan version changed
planVersion = arangodb::tests::getCurrentPlanVersion();
oldView = view;
@ -3050,7 +3057,10 @@ SECTION("test_drop_link") {
info.close();
auto const properties = info.slice().get("properties");
CHECK(!properties.hasKey(arangodb::iresearch::StaticStrings::LinksField));
CHECK((properties.hasKey(arangodb::iresearch::StaticStrings::LinksField)));
auto links = properties.get(arangodb::iresearch::StaticStrings::LinksField);
CHECK((links.isObject()));
CHECK((0 == links.length()));
}
// check indexes
@ -3165,4 +3175,4 @@ SECTION("IResearchViewNode::createBlock") {
// -----------------------------------------------------------------------------
// --SECTION-- END-OF-FILE
// -----------------------------------------------------------------------------
// -----------------------------------------------------------------------------