1
0
Fork 0

forward ported node corrections from 3.4 (#9700)

* forward ported node corrections from 3.4
* tests fixed
This commit is contained in:
Kaveh Vahedipour 2019-08-15 15:48:49 +02:00 committed by Max Neunhöffer
parent 563deebbee
commit e91cc66b9e
11 changed files with 339 additions and 256 deletions

View File

@ -18,13 +18,13 @@ devel
* Updated TOKENS function to deal with primitive types and arrays.
* Fixed agency nodes to not create bogus keys on delete / observe / unobserve
v3.5.0-rc.7 (2019-08-01)
------------------------
* Upgraded arangodb starter version to 0.14.12.
v3.5.0-rc.6 (2019-07-29)
------------------------

View File

@ -1,24 +1 @@
1s/^\(.*\)$/\.TH \1/
s/^ //
/NAME/s/^\(.*\)$/\.SH \1/
/SYNOPSIS/s/^\(.*\)$/\.SH \1/
/DESCRIPTION/s/^\(.*\)$/\.SH \1/
/OPTIONS/s/^\(.*\)$/\.SH \1/
/EXAMPLES/s/^\(.*\)$/\.SH \1/
/FILES/s/^\(.*\)$/\.SH \1/
/AUTHOR/s/^\(.*\)$/\.SH AUTHOR\
Copyright ArangoDB GmbH, Cologne, Germany\
/
/SEE ALSO/s/^\(.*\)$/\.SH \1/
s/\<OPTION\>/\.IP/g
s/\<ENDOPTION\>//g
s/\<EXAMPLE\> \(.*\)/\.nf\
shell> \1\
\.fi\
/g
s/\<ENDEXAMPLE\>/\
/g
/SEE ALSO/,/AUTHOR/{
/^[a-z]/s/^\(.*\)$/\.BR \1/
s/(\([1-9]\))/ "(\1), "/g
}

View File

@ -43,13 +43,38 @@ using namespace arangodb::basics;
const Node::Children Node::dummyChildren = Node::Children();
const Node Node::_dummyNode = Node("dumm-di-dumm");
static std::string const SLASH("/");
static std::regex const reg("/+");
std::string Node::normalize(std::string const& path) {
if (path.empty()) {
return SLASH;
}
std::string key = std::regex_replace(path, reg, SLASH);
// Must specify absolute path
if (key.front() != SLASH.front()) {
key = SLASH + key;
}
// Remove trailing slash
if (key.size() > 2 && key.back() == SLASH.front()) {
key.pop_back();
}
return key;
}
/// @brief Split strings by separator
inline static std::vector<std::string> split(const std::string& str, char separator) {
std::vector<std::string> result;
if (str.empty()) {
return result;
}
std::regex reg("/+");
std::string key = std::regex_replace(str, reg, "/");
if (!key.empty() && key.front() == '/') {
@ -180,7 +205,7 @@ Node::Node(Node const& other)
/// 1. remove any existing time to live entry
/// 2. clear children map
/// 3. copy from rhs buffer to my buffer
/// @brief Must not copy _parent, _ttl, _observers
/// @brief Must not copy _parent, _store, _ttl
Node& Node::operator=(VPackSlice const& slice) {
removeTimeToLive();
_children.clear();
@ -207,7 +232,7 @@ Node& Node::operator=(Node&& rhs) {
// 1. remove any existing time to live entry
// 2. move children map over
// 3. move value over
// Must not move over rhs's _parent, _store, _observers
// Must not move over rhs's _parent, _store
_nodeName = std::move(rhs._nodeName);
_children = std::move(rhs._children);
// The _children map has been moved here, therefore we must
@ -229,7 +254,7 @@ Node& Node::operator=(Node const& rhs) {
// 1. remove any existing time to live entry
// 2. clear children map
// 3. move from rhs to buffer pointer
// Must not move rhs's _parent, _store, _observers
// Must not move rhs's _parent, _store
removeTimeToLive();
_nodeName = rhs._nodeName;
_children.clear();
@ -424,22 +449,18 @@ bool Node::removeTimeToLive() {
return true;
}
inline bool Node::observedBy(std::string const& url) const {
auto ret = store().observerTable().equal_range(url);
for (auto it = ret.first; it != ret.second; ++it) {
if (it->second == uri()) {
return true;
}
}
return false;
}
namespace arangodb {
namespace consensus {
/// Set value
template <>
bool Node::handle<SET>(VPackSlice const& slice) {
if (!slice.hasKey("new")) {
LOG_TOPIC("ad662", WARN, Logger::AGENCY)
<< "Operator set without new value: " << slice.toJson();
return false;
}
Slice val = slice.get("new");
if (val.isObject()) {
@ -676,50 +697,6 @@ bool Node::handle<SHIFT>(VPackSlice const& slice) {
return true;
}
/// Add observer for this node
template <>
bool Node::handle<OBSERVE>(VPackSlice const& slice) {
if (!slice.hasKey("url")) return false;
if (!slice.get("url").isString()) return false;
std::string url(slice.get("url").copyString()), uri(this->uri());
// check if such entry exists
if (!observedBy(url)) {
store().observerTable().emplace(std::pair<std::string, std::string>(url, uri));
store().observedTable().emplace(std::pair<std::string, std::string>(uri, url));
return true;
}
return false;
}
/// Remove observer for this node
template <>
bool Node::handle<UNOBSERVE>(VPackSlice const& slice) {
if (!slice.hasKey("url")) return false;
if (!slice.get("url").isString()) return false;
std::string url(slice.get("url").copyString()), uri(this->uri());
// delete in both cases a single entry (ensured above)
// breaking the iterators is fine then
auto ret = store().observerTable().equal_range(url);
for (auto it = ret.first; it != ret.second; ++it) {
if (it->second == uri) {
store().observerTable().erase(it);
break;
}
}
ret = store().observedTable().equal_range(uri);
for (auto it = ret.first; it != ret.second; ++it) {
if (it->second == url) {
store().observedTable().erase(it);
return true;
}
}
return false;
}
} // namespace consensus
} // namespace arangodb
@ -749,20 +726,6 @@ bool Node::applieOp(VPackSlice const& slice) {
return handle<PREPEND>(slice);
} else if (oper == "shift") { // "op":"shift"
return handle<SHIFT>(slice);
} else if (oper == "observe") { // "op":"observe"
return handle<OBSERVE>(slice);
} else if (oper == "unobserve") { // "op":"unobserve"
handle<UNOBSERVE>(slice);
if (_children.empty() && _value.empty()) {
if (_parent == nullptr) { // root node
_children.clear();
_value.clear();
return true;
} else {
return _parent->removeChild(_nodeName);
}
}
return true;
} else if (oper == "erase") { // "op":"erase"
return handle<ERASE>(slice);
} else if (oper == "replace") { // "op":"replace"

View File

@ -180,21 +180,15 @@ class Node {
/// @brief Get value type
ValueType valueType() const;
/// @brief Add observer for this node
bool addObserver(std::string const&);
/// @brief Add observer for this node
void notifyObservers(std::string const& origin) const;
/// @brief Is this node being observed by url
bool observedBy(std::string const& url) const;
/// @brief Get our container
Store& store();
/// @brief Get our container
Store const& store() const;
/// brief Normalize node URIs
static std::string normalize(std::string const& key);
private:
/// @brief Get store if it exists:

View File

@ -1,4 +1,3 @@
////////////////////////////////////////////////////////////////////////////////
/// DISCLAIMER
///
@ -690,7 +689,51 @@ bool Store::applies(arangodb::velocypack::Slice const& transaction) {
Slice value = transaction.get(key);
if (value.isObject() && value.hasKey("op")) {
_node.hasAsWritableNode(abskeys.at(i)).first.applieOp(value);
if (value.get("op").isEqualString("delete") ||
value.get("op").isEqualString("replace") ||
value.get("op").isEqualString("erase")) {
if (!_node.has(abskeys.at(i))) {
continue;
}
}
auto uri = Node::normalize(abskeys.at(i));
if (value.get("op").isEqualString("observe")) {
bool found = false;
if (value.hasKey("url") && value.get("url").isString()) {
auto url = value.get("url").copyString();
auto ret = _observerTable.equal_range(url);
for (auto it = ret.first; it != ret.second; ++it) {
if (it->second == uri) {
found = true;
break;
}
}
if (!found) {
_observerTable.emplace(std::pair<std::string, std::string>(url, uri));
_observedTable.emplace(std::pair<std::string, std::string>(uri, url));
}
}
} else if (value.get("op").isEqualString("unobserve")) {
if (value.hasKey("url") && value.get("url").isString()) {
auto url = value.get("url").copyString();
auto ret = _observerTable.equal_range(url);
for (auto it = ret.first; it != ret.second; ++it) {
if (it->second == uri) {
_observerTable.erase(it);
break;
}
}
ret = _observedTable.equal_range(uri);
for (auto it = ret.first; it != ret.second; ++it) {
if (it->second == url) {
_observedTable.erase(it);
break;
}
}
}
} else {
_node.hasAsWritableNode(abskeys.at(i)).first.applieOp(value);
}
} else {
_node.hasAsWritableNode(abskeys.at(i)).first.applies(value);
}

View File

@ -248,12 +248,16 @@ TEST_F(ClusterInfoTest, test_drop_database) {
auto viewCreateJson = arangodb::velocypack::Parser::fromJson(
"{ \"name\": \"testView\", \"type\": \"testViewType\" }");
TRI_vocbase_t* vocbase; // will be owned by DatabaseFeature
// create database
ASSERT_TRUE((TRI_ERROR_NO_ERROR ==
database->createDatabase(1, "testDatabase", vocbase)));
ASSERT_TRUE((nullptr != vocbase));
ASSERT_TRUE((ci->createDatabaseCoordinator(vocbase->name(),
arangodb::velocypack::Slice::emptyObjectSlice(), 0.0)
.ok()));
// simulate heartbeat thread
ASSERT_TRUE(arangodb::AgencyComm().setValue("Current/Databases/testDatabase", arangodb::velocypack::Slice::emptyObjectSlice(), 0.0).successful());
ASSERT_TRUE(ci->createDatabaseCoordinator(
vocbase->name(),
arangodb::velocypack::Slice::emptyObjectSlice(), 0.0).ok());
// initial view creation
{
@ -262,12 +266,11 @@ TEST_F(ClusterInfoTest, test_drop_database) {
(viewFactory.create(logicalView, *vocbase, viewCreateJson->slice()).ok()));
ASSERT_TRUE((false == !logicalView));
}
EXPECT_TRUE((ci->dropDatabaseCoordinator(vocbase->name(), 0.0).ok()));
EXPECT_TRUE((ci->createDatabaseCoordinator(vocbase->name(),
arangodb::velocypack::Slice::emptyObjectSlice(), 0.0)
.ok()));
ASSERT_TRUE(arangodb::AgencyComm().setValue("Current/Databases/testDatabase", arangodb::velocypack::Slice::emptyObjectSlice(), 0.0).successful());
EXPECT_TRUE((ci->createDatabaseCoordinator(
vocbase->name(),
arangodb::velocypack::Slice::emptyObjectSlice(), 0.0).ok()));
arangodb::LogicalView::ptr logicalView;
EXPECT_TRUE(
(viewFactory.create(logicalView, *vocbase, viewCreateJson->slice()).ok()));

View File

@ -458,6 +458,7 @@ TEST_F(IResearchFeatureTest, test_upgrade0_1) {
TRI_vocbase_t* vocbase; // will be owned by DatabaseFeature
ASSERT_TRUE((TRI_ERROR_NO_ERROR == database->createDatabase(1, "testDatabase", vocbase)));
ASSERT_TRUE(arangodb::AgencyComm().setValue(std::string("Current/Databases/") + vocbase->name(), arangodb::velocypack::Slice::emptyObjectSlice(), 0.0).successful());
ASSERT_TRUE((ci->createDatabaseCoordinator(vocbase->name(), arangodb::velocypack::Slice::emptyObjectSlice(), 0.0).ok()));
ASSERT_TRUE((ci->createCollectionCoordinator(vocbase->name(), collectionId, 0, 1, 1, false, collectionJson->slice(), 0.0).ok()));
auto logicalCollection = ci->getCollection(vocbase->name(), collectionId);

View File

@ -280,6 +280,7 @@ TEST_F(IResearchLinkCoordinatorTest, test_create_drop) {
EXPECT_TRUE(TRI_vocbase_type_e::TRI_VOCBASE_TYPE_COORDINATOR == vocbase->type());
EXPECT_TRUE(1 == vocbase->id());
EXPECT_TRUE(arangodb::AgencyComm().setValue(std::string("Current/Databases/") + vocbase->name(), arangodb::velocypack::Slice::emptyObjectSlice(), 0.0).successful());
EXPECT_TRUE((ci->createDatabaseCoordinator(vocbase->name(), VPackSlice::emptyObjectSlice(), 0.0)
.ok()));
}

View File

@ -316,6 +316,7 @@ TEST_F(IResearchViewCoordinatorTest, visit_collections) {
ASSERT_TRUE((nullptr != database));
ASSERT_TRUE((TRI_ERROR_NO_ERROR == database->createDatabase(1, "testVocbase", vocbase)));
ASSERT_TRUE((nullptr != vocbase));
ASSERT_TRUE(arangodb::AgencyComm().setValue(std::string("Current/Databases/") + vocbase->name(), arangodb::velocypack::Slice::emptyObjectSlice(), 0.0).successful());
ASSERT_TRUE((ci->createDatabaseCoordinator(vocbase->name(),
arangodb::velocypack::Slice::emptyObjectSlice(), 0.0)
.ok()));
@ -400,6 +401,7 @@ TEST_F(IResearchViewCoordinatorTest, test_defaults) {
EXPECT_TRUE((TRI_vocbase_type_e::TRI_VOCBASE_TYPE_COORDINATOR == vocbase->type()));
EXPECT_TRUE((1 == vocbase->id()));
EXPECT_TRUE(arangodb::AgencyComm().setValue(std::string("Current/Databases/") + vocbase->name(), arangodb::velocypack::Slice::emptyObjectSlice(), 0.0).successful());
EXPECT_TRUE((ci->createDatabaseCoordinator(vocbase->name(), VPackSlice::emptyObjectSlice(), 0.0)
.ok()));
}
@ -692,7 +694,7 @@ TEST_F(IResearchViewCoordinatorTest, test_create_drop_view) {
EXPECT_TRUE("testDatabase" == vocbase->name());
EXPECT_TRUE(TRI_vocbase_type_e::TRI_VOCBASE_TYPE_COORDINATOR == vocbase->type());
EXPECT_TRUE(1 == vocbase->id());
EXPECT_TRUE(arangodb::AgencyComm().setValue(std::string("Current/Databases/") + vocbase->name(), arangodb::velocypack::Slice::emptyObjectSlice(), 0.0).successful());
EXPECT_TRUE((ci->createDatabaseCoordinator(vocbase->name(), VPackSlice::emptyObjectSlice(), 0.0)
.ok()));
}
@ -841,6 +843,7 @@ TEST_F(IResearchViewCoordinatorTest, test_create_link_in_background) {
ASSERT_EQ(TRI_vocbase_type_e::TRI_VOCBASE_TYPE_COORDINATOR, vocbase->type());
ASSERT_EQ(1, vocbase->id());
ASSERT_TRUE(arangodb::AgencyComm().setValue(std::string("Current/Databases/") + vocbase->name(), arangodb::velocypack::Slice::emptyObjectSlice(), 0.0).successful());
ASSERT_TRUE((ci->createDatabaseCoordinator(vocbase->name(), VPackSlice::emptyObjectSlice(), 0.0)
.ok()));
}
@ -958,6 +961,7 @@ TEST_F(IResearchViewCoordinatorTest, test_drop_with_link) {
EXPECT_TRUE((TRI_vocbase_type_e::TRI_VOCBASE_TYPE_COORDINATOR == vocbase->type()));
EXPECT_TRUE((1 == vocbase->id()));
EXPECT_TRUE(arangodb::AgencyComm().setValue(std::string("Current/Databases/") + vocbase->name(), arangodb::velocypack::Slice::emptyObjectSlice(), 0.0).successful());
EXPECT_TRUE((ci->createDatabaseCoordinator(vocbase->name(), VPackSlice::emptyObjectSlice(), 0.0)
.ok()));
}
@ -1086,7 +1090,7 @@ TEST_F(IResearchViewCoordinatorTest, test_update_properties) {
EXPECT_TRUE("testDatabase" == vocbase->name());
EXPECT_TRUE(TRI_vocbase_type_e::TRI_VOCBASE_TYPE_COORDINATOR == vocbase->type());
EXPECT_TRUE(1 == vocbase->id());
EXPECT_TRUE(arangodb::AgencyComm().setValue(std::string("Current/Databases/") + vocbase->name(), arangodb::velocypack::Slice::emptyObjectSlice(), 0.0).successful());
EXPECT_TRUE((ci->createDatabaseCoordinator(vocbase->name(), VPackSlice::emptyObjectSlice(), 0.0)
.ok()));
}
@ -1257,7 +1261,7 @@ TEST_F(IResearchViewCoordinatorTest, test_overwrite_immutable_properties) {
EXPECT_EQ("testDatabase", vocbase->name());
EXPECT_EQ(TRI_vocbase_type_e::TRI_VOCBASE_TYPE_COORDINATOR, vocbase->type());
EXPECT_EQ(1, vocbase->id());
EXPECT_TRUE(arangodb::AgencyComm().setValue(std::string("Current/Databases/") + vocbase->name(), arangodb::velocypack::Slice::emptyObjectSlice(), 0.0).successful());
EXPECT_TRUE(ci->createDatabaseCoordinator(vocbase->name(),
VPackSlice::emptyObjectSlice(), 0.0)
.ok());
@ -1457,7 +1461,7 @@ TEST_F(IResearchViewCoordinatorTest, test_update_links_partial_remove) {
EXPECT_TRUE("testDatabase" == vocbase->name());
EXPECT_TRUE(TRI_vocbase_type_e::TRI_VOCBASE_TYPE_COORDINATOR == vocbase->type());
EXPECT_TRUE(1 == vocbase->id());
EXPECT_TRUE(arangodb::AgencyComm().setValue(std::string("Current/Databases/") + vocbase->name(), arangodb::velocypack::Slice::emptyObjectSlice(), 0.0).successful());
EXPECT_TRUE((ci->createDatabaseCoordinator(vocbase->name(), VPackSlice::emptyObjectSlice(), 0.0)
.ok()));
}
@ -2049,7 +2053,7 @@ TEST_F(IResearchViewCoordinatorTest, test_update_links_partial_add) {
EXPECT_TRUE("testDatabase" == vocbase->name());
EXPECT_TRUE(TRI_vocbase_type_e::TRI_VOCBASE_TYPE_COORDINATOR == vocbase->type());
EXPECT_TRUE(1 == vocbase->id());
EXPECT_TRUE(arangodb::AgencyComm().setValue(std::string("Current/Databases/") + vocbase->name(), arangodb::velocypack::Slice::emptyObjectSlice(), 0.0).successful());
EXPECT_TRUE((ci->createDatabaseCoordinator(vocbase->name(), VPackSlice::emptyObjectSlice(), 0.0)
.ok()));
}
@ -2692,7 +2696,7 @@ TEST_F(IResearchViewCoordinatorTest, test_update_links_replace) {
EXPECT_TRUE("testDatabase" == vocbase->name());
EXPECT_TRUE(TRI_vocbase_type_e::TRI_VOCBASE_TYPE_COORDINATOR == vocbase->type());
EXPECT_TRUE(1 == vocbase->id());
EXPECT_TRUE(arangodb::AgencyComm().setValue(std::string("Current/Databases/") + vocbase->name(), arangodb::velocypack::Slice::emptyObjectSlice(), 0.0).successful());
EXPECT_TRUE((ci->createDatabaseCoordinator(vocbase->name(), VPackSlice::emptyObjectSlice(), 0.0)
.ok()));
}
@ -3293,7 +3297,7 @@ TEST_F(IResearchViewCoordinatorTest, test_update_links_clear) {
EXPECT_TRUE("testDatabase" == vocbase->name());
EXPECT_TRUE(TRI_vocbase_type_e::TRI_VOCBASE_TYPE_COORDINATOR == vocbase->type());
EXPECT_TRUE(1 == vocbase->id());
EXPECT_TRUE(arangodb::AgencyComm().setValue(std::string("Current/Databases/") + vocbase->name(), arangodb::velocypack::Slice::emptyObjectSlice(), 0.0).successful());
EXPECT_TRUE((ci->createDatabaseCoordinator(vocbase->name(), VPackSlice::emptyObjectSlice(), 0.0)
.ok()));
}
@ -3758,7 +3762,7 @@ TEST_F(IResearchViewCoordinatorTest, test_drop_link) {
EXPECT_TRUE("testDatabase" == vocbase->name());
EXPECT_TRUE(TRI_vocbase_type_e::TRI_VOCBASE_TYPE_COORDINATOR == vocbase->type());
EXPECT_TRUE(1 == vocbase->id());
EXPECT_TRUE(arangodb::AgencyComm().setValue(std::string("Current/Databases/") + vocbase->name(), arangodb::velocypack::Slice::emptyObjectSlice(), 0.0).successful());
EXPECT_TRUE((ci->createDatabaseCoordinator(vocbase->name(), VPackSlice::emptyObjectSlice(), 0.0)
.ok()));
}
@ -4067,7 +4071,7 @@ TEST_F(IResearchViewCoordinatorTest, test_update_overwrite) {
EXPECT_TRUE(("testDatabase" == vocbase->name()));
EXPECT_TRUE((TRI_vocbase_type_e::TRI_VOCBASE_TYPE_COORDINATOR == vocbase->type()));
EXPECT_TRUE((1 == vocbase->id()));
EXPECT_TRUE(arangodb::AgencyComm().setValue(std::string("Current/Databases/") + vocbase->name(), arangodb::velocypack::Slice::emptyObjectSlice(), 0.0).successful());
EXPECT_TRUE((ci->createDatabaseCoordinator(vocbase->name(), VPackSlice::emptyObjectSlice(), 0.0)
.ok()));
}
@ -4832,7 +4836,7 @@ TEST_F(IResearchViewCoordinatorTest, test_update_partial) {
EXPECT_TRUE(("testDatabase" == vocbase->name()));
EXPECT_TRUE((TRI_vocbase_type_e::TRI_VOCBASE_TYPE_COORDINATOR == vocbase->type()));
EXPECT_TRUE((1 == vocbase->id()));
EXPECT_TRUE(arangodb::AgencyComm().setValue(std::string("Current/Databases/") + vocbase->name(), arangodb::velocypack::Slice::emptyObjectSlice(), 0.0).successful());
EXPECT_TRUE((ci->createDatabaseCoordinator(vocbase->name(), VPackSlice::emptyObjectSlice(), 0.0)
.ok()));
}
@ -5603,7 +5607,7 @@ TEST_F(IResearchViewCoordinatorTest, IResearchViewNode_createBlock) {
EXPECT_TRUE("testDatabase" == vocbase->name());
EXPECT_TRUE(TRI_vocbase_type_e::TRI_VOCBASE_TYPE_COORDINATOR == vocbase->type());
EXPECT_TRUE(1 == vocbase->id());
EXPECT_TRUE(arangodb::AgencyComm().setValue(std::string("Current/Databases/") + vocbase->name(), arangodb::velocypack::Slice::emptyObjectSlice(), 0.0).successful());
EXPECT_TRUE((ci->createDatabaseCoordinator(vocbase->name(), VPackSlice::emptyObjectSlice(), 0.0)
.ok()));
}

View File

@ -243,7 +243,7 @@ TEST_F(IResearchViewDBServerTest, test_drop) {
EXPECT_TRUE("testDatabase" == vocbase->name());
EXPECT_TRUE(TRI_vocbase_type_e::TRI_VOCBASE_TYPE_NORMAL == vocbase->type());
EXPECT_TRUE(1 == vocbase->id());
EXPECT_TRUE(arangodb::AgencyComm().setValue(std::string("Current/Databases/") + vocbase->name(), arangodb::velocypack::Slice::emptyObjectSlice(), 0.0).successful());
EXPECT_TRUE((ci->createDatabaseCoordinator(vocbase->name(), VPackSlice::emptyObjectSlice(), 0.0)
.ok()));
}
@ -360,7 +360,7 @@ TEST_F(IResearchViewDBServerTest, test_drop_cid) {
EXPECT_TRUE("testDatabase" == vocbase->name());
EXPECT_TRUE(TRI_vocbase_type_e::TRI_VOCBASE_TYPE_NORMAL == vocbase->type());
EXPECT_TRUE(1 == vocbase->id());
EXPECT_TRUE(arangodb::AgencyComm().setValue(std::string("Current/Databases/") + vocbase->name(), arangodb::velocypack::Slice::emptyObjectSlice(), 0.0).successful());
EXPECT_TRUE((ci->createDatabaseCoordinator(vocbase->name(), VPackSlice::emptyObjectSlice(), 0.0)
.ok()));
}
@ -425,6 +425,7 @@ TEST_F(IResearchViewDBServerTest, test_drop_database) {
ASSERT_TRUE((TRI_ERROR_NO_ERROR ==
databaseFeature->createDatabase(0, "testDatabase" TOSTRING(__LINE__), vocbase)));
ASSERT_TRUE((nullptr != vocbase));
ASSERT_TRUE(arangodb::AgencyComm().setValue(std::string("Current/Databases/") + vocbase->name(), arangodb::velocypack::Slice::emptyObjectSlice(), 0.0).successful());
ASSERT_TRUE((ci->createDatabaseCoordinator(vocbase->name(),
arangodb::velocypack::Slice::emptyObjectSlice(), 0.)
.ok()));
@ -463,7 +464,7 @@ TEST_F(IResearchViewDBServerTest, test_ensure) {
EXPECT_TRUE("testDatabase" == vocbase->name());
EXPECT_TRUE(TRI_vocbase_type_e::TRI_VOCBASE_TYPE_NORMAL == vocbase->type());
EXPECT_TRUE(1 == vocbase->id());
EXPECT_TRUE(arangodb::AgencyComm().setValue(std::string("Current/Databases/") + vocbase->name(), arangodb::velocypack::Slice::emptyObjectSlice(), 0.0).successful());
EXPECT_TRUE((ci->createDatabaseCoordinator(vocbase->name(), VPackSlice::emptyObjectSlice(), 0.0)
.ok()));
}
@ -621,6 +622,7 @@ TEST_F(IResearchViewDBServerTest, test_query) {
TRI_vocbase_t* vocbase; // will be owned by DatabaseFeature
ASSERT_TRUE((TRI_ERROR_NO_ERROR ==
database->createDatabase(1, "testDatabase0", vocbase)));
EXPECT_TRUE(arangodb::AgencyComm().setValue(std::string("Current/Databases/") + vocbase->name(), arangodb::velocypack::Slice::emptyObjectSlice(), 0.0).successful());
EXPECT_TRUE((ci->createDatabaseCoordinator(vocbase->name(), VPackSlice::emptyObjectSlice(), 0.0)
.ok()));
auto logicalCollection = vocbase->createCollection(collectionJson->slice());
@ -664,6 +666,7 @@ TEST_F(IResearchViewDBServerTest, test_query) {
TRI_vocbase_t* vocbase; // will be owned by DatabaseFeature
ASSERT_TRUE((TRI_ERROR_NO_ERROR ==
database->createDatabase(1, "testDatabase1", vocbase)));
EXPECT_TRUE(arangodb::AgencyComm().setValue(std::string("Current/Databases/") + vocbase->name(), arangodb::velocypack::Slice::emptyObjectSlice(), 0.0).successful());
EXPECT_TRUE((ci->createDatabaseCoordinator(vocbase->name(), VPackSlice::emptyObjectSlice(), 0.0)
.ok()));
auto logicalCollection = vocbase->createCollection(collectionJson->slice());
@ -731,6 +734,7 @@ TEST_F(IResearchViewDBServerTest, test_query) {
ASSERT_TRUE((TRI_ERROR_NO_ERROR ==
databaseFeature->createDatabase(0, "testDatabase" TOSTRING(__LINE__), vocbase)));
ASSERT_TRUE((nullptr != vocbase));
ASSERT_TRUE(arangodb::AgencyComm().setValue(std::string("Current/Databases/") + vocbase->name(), arangodb::velocypack::Slice::emptyObjectSlice(), 0.0).successful());
ASSERT_TRUE((ci->createDatabaseCoordinator(vocbase->name(),
arangodb::velocypack::Slice::emptyObjectSlice(), 0.)
.ok()));
@ -831,9 +835,10 @@ TEST_F(IResearchViewDBServerTest, test_query) {
ASSERT_TRUE((TRI_ERROR_NO_ERROR ==
databaseFeature->createDatabase(0, "testDatabase" TOSTRING(__LINE__), vocbase)));
ASSERT_TRUE((nullptr != vocbase));
ASSERT_TRUE((ci->createDatabaseCoordinator(vocbase->name(),
arangodb::velocypack::Slice::emptyObjectSlice(), 0.)
.ok()));
ASSERT_TRUE(arangodb::AgencyComm().setValue(std::string("Current/Databases/") + vocbase->name(), arangodb::velocypack::Slice::emptyObjectSlice(), 0.0).successful());
EXPECT_TRUE((ci->createDatabaseCoordinator(
vocbase->name(),
arangodb::velocypack::Slice::emptyObjectSlice(), 0.).ok()));
auto logicalCollection = vocbase->createCollection(collectionJson->slice());
EXPECT_TRUE(
(ci->createViewCoordinator(vocbase->name(), "42", createJson->slice()).ok()));
@ -1122,7 +1127,7 @@ TEST_F(IResearchViewDBServerTest, test_transaction_snapshot) {
EXPECT_TRUE("testDatabase" == vocbase->name());
EXPECT_TRUE(TRI_vocbase_type_e::TRI_VOCBASE_TYPE_NORMAL == vocbase->type());
EXPECT_TRUE(1 == vocbase->id());
EXPECT_TRUE(arangodb::AgencyComm().setValue(std::string("Current/Databases/") + vocbase->name(), arangodb::velocypack::Slice::emptyObjectSlice(), 0.0).successful());
EXPECT_TRUE((ci->createDatabaseCoordinator(vocbase->name(), VPackSlice::emptyObjectSlice(), 0.0)
.ok()));
}
@ -1265,6 +1270,7 @@ TEST_F(IResearchViewDBServerTest, test_updateProperties) {
ASSERT_TRUE((TRI_ERROR_NO_ERROR ==
databaseFeature->createDatabase(0, "testDatabase" TOSTRING(__LINE__), vocbase)));
ASSERT_TRUE((nullptr != vocbase));
ASSERT_TRUE(arangodb::AgencyComm().setValue(std::string("Current/Databases/") + vocbase->name(), arangodb::velocypack::Slice::emptyObjectSlice(), 0.0).successful());
ASSERT_TRUE((ci->createDatabaseCoordinator(vocbase->name(),
arangodb::velocypack::Slice::emptyObjectSlice(), 0.)
.ok()));
@ -1390,6 +1396,7 @@ TEST_F(IResearchViewDBServerTest, test_updateProperties) {
ASSERT_TRUE((TRI_ERROR_NO_ERROR ==
databaseFeature->createDatabase(0, "testDatabase" TOSTRING(__LINE__), vocbase)));
ASSERT_TRUE((nullptr != vocbase));
ASSERT_TRUE(arangodb::AgencyComm().setValue(std::string("Current/Databases/") + vocbase->name(), arangodb::velocypack::Slice::emptyObjectSlice(), 0.0).successful());
ASSERT_TRUE((ci->createDatabaseCoordinator(vocbase->name(),
arangodb::velocypack::Slice::emptyObjectSlice(), 0.)
.ok()));
@ -1518,6 +1525,7 @@ TEST_F(IResearchViewDBServerTest, test_updateProperties) {
ASSERT_TRUE((TRI_ERROR_NO_ERROR ==
databaseFeature->createDatabase(0, "testDatabase" TOSTRING(__LINE__), vocbase)));
ASSERT_TRUE((nullptr != vocbase));
ASSERT_TRUE(arangodb::AgencyComm().setValue(std::string("Current/Databases/") + vocbase->name(), arangodb::velocypack::Slice::emptyObjectSlice(), 0.0).successful());
ASSERT_TRUE((ci->createDatabaseCoordinator(vocbase->name(),
arangodb::velocypack::Slice::emptyObjectSlice(), 0.)
.ok()));
@ -1651,6 +1659,7 @@ TEST_F(IResearchViewDBServerTest, test_updateProperties) {
ASSERT_TRUE((TRI_ERROR_NO_ERROR ==
databaseFeature->createDatabase(0, "testDatabase" TOSTRING(__LINE__), vocbase)));
ASSERT_TRUE((nullptr != vocbase));
ASSERT_TRUE(arangodb::AgencyComm().setValue(std::string("Current/Databases/") + vocbase->name(), arangodb::velocypack::Slice::emptyObjectSlice(), 0.0).successful());
ASSERT_TRUE((ci->createDatabaseCoordinator(vocbase->name(),
arangodb::velocypack::Slice::emptyObjectSlice(), 0.)
.ok()));

View File

@ -72,35 +72,40 @@ function agencyTestSuite () {
var agencyServers = instanceInfo.arangods.map(arangod => {
return arangod.url;
});
var agencyLeader = agencyServers[0];
var request = require("@arangodb/request");
function findAgencyCompactionIntervals() {
function agencyConfig() {
for (let count = 0; count < 60; ++count) {
let res = request({url: agencyLeader + "/_api/agency/config",
method: "GET", followRedirect: true});
if (res.statusCode === 200) {
try {
res.bodyParsed = JSON.parse(res.body);
} catch(e) {
require("console").error("Exception in body parse of '" + agencyLeader + "/_api/agency/config' : ", res.body, JSON.stringify(e), JSON.stringify(res));
throw e;
res.bodyParsed = JSON.parse(res.body);
if (res.bodyParsed.leaderId !== "") {
return res.bodyParsed;
}
return {
compactionStepSize: res.bodyParsed.configuration["compaction step size"],
compactionKeepSize: res.bodyParsed.configuration["compaction keep size"]
};
require('console').topic("agency=warn", "No leadership ...");
} else {
require('console').topic("agency=warn", "Got status " + res.statusCode +
" from agency.");
}
require('console').topic("agency=warn", "Got status " + res.statusCode +
" from agency.");
require("internal").wait(1.0); // give the server another second
}
require('console').topic("agency=error",
"Giving up, agency did not boot successfully.");
"Giving up, agency did not boot successfully.");
assertEqual("apple", "orange");
// all is lost because agency did not get up and running in time
}
function findAgencyCompactionIntervals() {
var c = agencyConfig();
return {
compactionStepSize: c.configuration["compaction step size"],
compactionKeepSize: c.configuration["compaction keep size"]
};
}
var compactionConfig = findAgencyCompactionIntervals();
require("console").topic("agency=info", "Agency compaction configuration: ", compactionConfig);
@ -118,29 +123,8 @@ function agencyTestSuite () {
timeout: 240
};
let compactionReply = request(compaction);
let stateReply = request(state);
let compactionParsed;
let stateParsed;
try {
compactionParsed = JSON.parse(compactionReply.body);
}
catch (e) {
require("console").error("Exception in body parse of '" + url + "/_api/cursor' : ", compactionReply.body, JSON.stringify(e), JSON.stringify(compactionReply));
throw e;
}
try {
stateParsed = JSON.parse(stateReply.body);
}
catch (e) {
require("console").error("Exception in body parse of '" + url + "/_api/agency/state' : ", stateReply.body, JSON.stringify(e), JSON.stringify(stateReply));
throw e;
}
ret.push({
compactions: compactionParsed,
state: stateParsed,
url: url
});
ret.push({compactions: JSON.parse(request(compaction).body),
state: JSON.parse(request(state).body), url: url});
});
return ret;
}
@ -149,7 +133,6 @@ function agencyTestSuite () {
// We simply try all agency servers in turn until one gives us an HTTP
// response:
var res;
let requestUrl;
var inquire = false;
var clientIds = [];
@ -163,16 +146,14 @@ function agencyTestSuite () {
while (true) {
if (!inquire) {
requestUrl = agencyLeader + "/_api/agency/" + api;
res = request({url: requestUrl,
res = request({url: agencyLeader + "/_api/agency/" + api,
method: "POST", followRedirect: false,
body: JSON.stringify(list),
headers: {"Content-Type": "application/json"},
timeout: timeout /* essentially for the huge trx package
running under ASAN in the CI */ });
} else { // inquire. Remove successful commits. For later retries
requestUrl = agencyLeader + "/_api/agency/inquire";
res = request({url: requestUrl,
res = request({url: agencyLeader + "/_api/agency/inquire",
method: "POST", followRedirect: false,
body: JSON.stringify(clientIds),
headers: {"Content-Type": "application/json"},
@ -184,7 +165,7 @@ function agencyTestSuite () {
agencyLeader = res.headers.location;
var l = 0;
for (var i = 0; i < 3; ++i) {
l = agencyLeader.indexOf('/', l + 1);
l = agencyLeader.indexOf('/', l+1);
}
agencyLeader = agencyLeader.substring(0,l);
if (clientIds.length > 0 && api === 'write') {
@ -205,12 +186,7 @@ function agencyTestSuite () {
}
// In case of inquiry, we probably have done some of the transactions:
var done = 0;
try {
res.bodyParsed = JSON.parse(res.body);
} catch(e) {
require("console").error("Exception in body parse of '" + requestUrl + "' : ", res.body, JSON.stringify(e), api, list, JSON.stringify(res));
throw e;
}
res.bodyParsed = JSON.parse(res.body);
res.bodyParsed.results.forEach(function (index) {
if (index > 0) {
done++;
@ -226,7 +202,7 @@ function agencyTestSuite () {
try {
res.bodyParsed = JSON.parse(res.body);
} catch(e) {
require("console").error("Exception in body parse of '" + requestUrl + "' : ", res.body, JSON.stringify(e), api, list, JSON.stringify(res));
require("console").error("Exception in body parse:", res.body, JSON.stringify(e), api, list, JSON.stringify(res));
}
return res;
}
@ -271,10 +247,10 @@ function agencyTestSuite () {
res = accessAgency("read", trxs);
assertEqual(200, res.statusCode);
for (i = 0; i < start + count; ++i) {
let key = "key" + i;
let key = "key"+i;
let correct = {};
correct[key] = "value" + i;
assertEqual(correct, res.bodyParsed[i], JSON.stringify(res.bodyParsed));
assertEqual(correct, res.bodyParsed[i]);
}
}
@ -287,8 +263,8 @@ function agencyTestSuite () {
var agents = getCompactions(servers), i, old;
var ready = true;
for (i = 1; i < agents.length; ++i) {
if (agents[0].state.log[agents[0].state.log.length - 1].index !==
agents[i].state.log[agents[i].state.log.length - 1].index) {
if (agents[0].state.log[agents[0].state.log.length-1].index !==
agents[i].state.log[agents[i].state.log.length-1].index) {
ready = false;
break;
}
@ -299,9 +275,9 @@ function agencyTestSuite () {
agents.forEach( function (agent) {
var results = agent.compactions.result; // All compactions
var llog = agent.state.log[agent.state.log.length - 1]; // Last log entry
var llog = agent.state.log[agent.state.log.length-1]; // Last log entry
llogi = llog.index; // Last log index
var lcomp = results[results.length - 1]; // Last compaction entry
var lcomp = results[results.length-1]; // Last compaction entry
var lcompi = parseInt(lcomp._key); // Last compaction index
var stepsize = compactionConfig.compactionStepSize;
@ -780,12 +756,7 @@ function agencyTestSuite () {
let res = request({url: agencyLeader + "/_api/agency/stores",
method: "GET", followRedirect: true});
if (res.statusCode === 200) {
try {
res.bodyParsed = JSON.parse(res.body);
} catch(e) {
require("console").error("Exception in body parse of " + agencyLeader + "/_api/agency/stores' : ", res.body, JSON.stringify(e), JSON.stringify(res));
throw e;
}
res.bodyParsed = JSON.parse(res.body);
if (res.bodyParsed.read_db[0].a !== undefined) {
assertTrue(res.bodyParsed.read_db[1]["/a/u"] >= 0);
} else {
@ -807,12 +778,7 @@ function agencyTestSuite () {
// only, if agency is still led by same guy/girl
if (agencyLeader === tmp) {
if (res.statusCode === 200) {
try {
res.bodyParsed = JSON.parse(res.body);
} catch(e) {
require("console").error("Exception in body parse of '" + agencyLeader + "/_api/agency/stores' : ", res.body, JSON.stringify(e), JSON.stringify(res));
throw e;
}
res.bodyParsed = JSON.parse(res.body);
console.warn(res.bodyParsed.read_db[0]);
if (res.bodyParsed.read_db[0].a !== undefined) {
assertTrue(res.bodyParsed.read_db[1]["/a/u"] === undefined);
@ -1100,6 +1066,129 @@ function agencyTestSuite () {
assertEqual(readAndCheck([["/"]]), [{}]);
},
////////////////////////////////////////////////////////////////////////////////
/// @brief Test observe / unobserve
////////////////////////////////////////////////////////////////////////////////
testObserve : function () {
var res, before, after, clean;
var trx = [{"/a":"a"}, {"a":{"oldEmpty":true}}];
// In the beginning
res = request({url:agencyLeader+"/_api/agency/stores", method:"GET"});
assertEqual(200, res.statusCode);
clean = JSON.parse(res.body);
// Don't create empty object for observation
writeAndCheck([[{"/a":{"op":"observe", "url":"https://google.com"}}]]);
assertEqual(readAndCheck([["/"]]), [{}]);
res = accessAgency("write",[trx]);
assertEqual(res.statusCode, 200);
res = accessAgency("write",[trx]);
assertEqual(res.statusCode, 412);
writeAndCheck([[{"/":{"op":"delete"}}]]);
var c = agencyConfig().term;
// No duplicate entries in
res = request({url:agencyLeader+"/_api/agency/stores", method:"GET"});
assertEqual(200, res.statusCode);
before = JSON.parse(res.body);
writeAndCheck([[{"/a":{"op":"observe", "url":"https://google.com"}}]]);
res = request({url:agencyLeader+"/_api/agency/stores", method:"GET"});
assertEqual(200, res.statusCode);
after = JSON.parse(res.body);
if (!_.isEqual(before, after)) {
if (agencyConfig().term === c) {
assertEqual(before, after); //peng
} else {
require("console").warn("skipping remaining callback tests this time around");
return; //
}
}
// Normalization
res = request({url:agencyLeader+"/_api/agency/stores", method:"GET"});
assertEqual(200, res.statusCode);
before = JSON.parse(res.body);
writeAndCheck([[{"//////a////":{"op":"observe", "url":"https://google.com"}}]]);
writeAndCheck([[{"a":{"op":"observe", "url":"https://google.com"}}]]);
writeAndCheck([[{"a/":{"op":"observe", "url":"https://google.com"}}]]);
writeAndCheck([[{"/a/":{"op":"observe", "url":"https://google.com"}}]]);
res = request({url:agencyLeader+"/_api/agency/stores", method:"GET"});
assertEqual(200, res.statusCode);
after = JSON.parse(res.body);
if (!_.isEqual(before, after)) {
if (agencyConfig().term === c) {
assertEqual(before, after); //peng
} else {
require("console").warn("skipping remaining callback tests this time around");
return; //
}
}
// Unobserve
res = request({url:agencyLeader+"/_api/agency/stores", method:"GET"});
assertEqual(200, res.statusCode);
before = JSON.parse(res.body);
writeAndCheck([[{"//////a":{"op":"unobserve", "url":"https://google.com"}}]]);
res = request({url:agencyLeader+"/_api/agency/stores", method:"GET"});
assertEqual(200, res.statusCode);
after = JSON.parse(res.body);
assertEqual(clean, after);
if (!_.isEqual(clean, after)) {
if (agencyConfig().term === c) {
assertEqual(clean, after); //peng
} else {
require("console").warn("skipping remaining callback tests this time around");
return; //
}
}
writeAndCheck([[{"/":{"op":"delete"}}]]);
assertEqual(readAndCheck([["/"]]), [{}]);
},
////////////////////////////////////////////////////////////////////////////////
/// @brief Test delete / replace / erase should not create new stuff in agency
////////////////////////////////////////////////////////////////////////////////
testNotCreate : function () {
var trx = [{"/a":"a"}, {"a":{"oldEmpty":true}}], res;
// Don't create empty object for observation
writeAndCheck([[{"a":{"op":"delete"}}]]);
assertEqual(readAndCheck([["/"]]), [{}]);
res = accessAgency("write",[trx]);
assertEqual(res.statusCode, 200);
res = accessAgency("write",[trx]);
assertEqual(res.statusCode, 412);
writeAndCheck([[{"/":{"op":"delete"}}]]);
assertEqual(readAndCheck([["/"]]), [{}]);
// Don't create empty object for observation
writeAndCheck([[{"a":{"op":"replace", "val":1, "new":2}}]]);
assertEqual(readAndCheck([["/"]]), [{}]);
res = accessAgency("write",[trx]);
assertEqual(res.statusCode, 200);
res = accessAgency("write",[trx]);
assertEqual(res.statusCode, 412);
writeAndCheck([[{"/":{"op":"delete"}}]]);
assertEqual(readAndCheck([["/"]]), [{}]);
// Don't create empty object for observation
writeAndCheck([[{"a":{"op":"erase", "val":1}}]]);
assertEqual(readAndCheck([["/"]]), [{}]);
res = accessAgency("write",[trx]);
assertEqual(res.statusCode, 200);
res = accessAgency("write",[trx]);
assertEqual(res.statusCode, 412);
writeAndCheck([[{"/":{"op":"delete"}}]]);
assertEqual(readAndCheck([["/"]]), [{}]);
},
////////////////////////////////////////////////////////////////////////////////
/// @brief Test that order should not matter
////////////////////////////////////////////////////////////////////////////////
@ -1341,4 +1430,3 @@ function agencyTestSuite () {
jsunity.run(agencyTestSuite);
return jsunity.done();