mirror of https://gitee.com/bigwinds/arangodb
Added view retrieval via HTTP with tests and initial work on view factory.
This commit is contained in:
parent
7e7fe8bc21
commit
aa23074efd
|
@ -27,7 +27,9 @@ describe ArangoDB do
|
|||
|
||||
it "creating a view without name" do
|
||||
cmd = api
|
||||
body = "{ \"type\" : \"def\" }"
|
||||
body = <<-END
|
||||
{ "type": "def" }
|
||||
END
|
||||
doc = ArangoDB.log_post("#{prefix}-create-missing-name", cmd, :body => body)
|
||||
|
||||
doc.code.should eq(400)
|
||||
|
@ -39,7 +41,9 @@ describe ArangoDB do
|
|||
|
||||
it "creating a view without type" do
|
||||
cmd = api
|
||||
body = "{ \"name\" : \"abc\" }"
|
||||
body = <<-END
|
||||
{ "name": "abc" }
|
||||
END
|
||||
doc = ArangoDB.log_post("#{prefix}-create-missing-type", cmd, :body => body)
|
||||
|
||||
doc.code.should eq(400)
|
||||
|
@ -49,6 +53,117 @@ describe ArangoDB do
|
|||
doc.parsed_response['errorNum'].should eq(400)
|
||||
end
|
||||
|
||||
it "duplicate name" do
|
||||
cmd1 = api
|
||||
body1 = <<-END
|
||||
{ "name": "dup",
|
||||
"type": "type1" }
|
||||
END
|
||||
doc1 = ArangoDB.log_post("#{prefix}-create-duplicate", cmd1, :body => body1)
|
||||
|
||||
doc1.code.should eq(201)
|
||||
doc1.headers['content-type'].should eq("application/json; charset=utf-8")
|
||||
doc1.parsed_response['name'].should eq("dup")
|
||||
doc1.parsed_response['type'].should eq("type1")
|
||||
|
||||
cmd2 = api
|
||||
body2 = <<-END
|
||||
{ "name": "dup",
|
||||
"type": "type2" }
|
||||
END
|
||||
doc2 = ArangoDB.log_post("#{prefix}-create-duplicate", cmd1, :body => body2)
|
||||
|
||||
doc2.code.should eq(500)
|
||||
doc2.headers['content-type'].should eq("application/json; charset=utf-8")
|
||||
doc2.parsed_response['error'].should eq(true)
|
||||
doc2.parsed_response['code'].should eq(500)
|
||||
doc2.parsed_response['errorNum'].should eq(1207)
|
||||
|
||||
cmd3 = api + '/dup'
|
||||
doc3 = ArangoDB.log_delete("#{prefix}-create-duplicate", cmd3)
|
||||
|
||||
doc3.code.should eq(204)
|
||||
doc3.headers['content-type'].should eq("text/plain; charset=utf-8")
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
context "add/drop:" do
|
||||
it "creating a view" do
|
||||
cmd = api
|
||||
body = <<-END
|
||||
{ "name": "abc",
|
||||
"type": "def" }
|
||||
END
|
||||
doc = ArangoDB.log_post("#{prefix}-create-a-view", cmd, :body => body)
|
||||
|
||||
doc.code.should eq(201)
|
||||
doc.headers['content-type'].should eq("application/json; charset=utf-8")
|
||||
doc.parsed_response['name'].should eq("abc")
|
||||
doc.parsed_response['type'].should eq("def")
|
||||
end
|
||||
|
||||
it "dropping a view" do
|
||||
cmd1 = api + "/abc"
|
||||
doc1 = ArangoDB.log_delete("#{prefix}-drop-a-view", cmd1)
|
||||
|
||||
doc1.code.should eq(204)
|
||||
doc1.headers['content-type'].should eq("text/plain; charset=utf-8")
|
||||
|
||||
cmd2 = api + "/abc"
|
||||
doc2 = ArangoDB.log_get("#{prefix}-drop-a-view", cmd2)
|
||||
|
||||
doc2.code.should eq(404)
|
||||
doc2.headers['content-type'].should eq("application/json; charset=utf-8")
|
||||
doc2.parsed_response['error'].should eq(true)
|
||||
doc2.parsed_response['code'].should eq(404)
|
||||
end
|
||||
end
|
||||
|
||||
context "retrieval:" do
|
||||
it "empty list" do
|
||||
cmd = api
|
||||
doc = ArangoDB.log_get("#{prefix}-empty-list", cmd)
|
||||
|
||||
doc.code.should eq(200)
|
||||
doc.headers['content-type'].should eq("application/json; charset=utf-8")
|
||||
doc.parsed_response.should eq([])
|
||||
end
|
||||
|
||||
it "short list" do
|
||||
cmd1 = api
|
||||
body1 = <<-END
|
||||
{"name": "abc",
|
||||
"type": "type1"}
|
||||
END
|
||||
doc1 = ArangoDB.log_post("#{prefix}-short-list", cmd1, :body => body1)
|
||||
doc1.code.should eq(201)
|
||||
doc1.headers['content-type'].should eq("application/json; charset=utf-8")
|
||||
doc1.parsed_response['name'].should eq("abc")
|
||||
doc1.parsed_response['type'].should eq("type1")
|
||||
|
||||
cmd2 = api
|
||||
body2 = <<-END
|
||||
{"name": "def",
|
||||
"type": "type2"}
|
||||
END
|
||||
doc2 = ArangoDB.log_post("#{prefix}-short-list", cmd2, :body => body2)
|
||||
doc2.code.should eq(201)
|
||||
doc2.headers['content-type'].should eq("application/json; charset=utf-8")
|
||||
doc2.parsed_response['name'].should eq("def")
|
||||
doc2.parsed_response['type'].should eq("type2")
|
||||
|
||||
cmd3 = api
|
||||
doc3 = ArangoDB.log_get("#{prefix}-short-list", cmd3)
|
||||
doc3.code.should eq(200)
|
||||
puts doc3
|
||||
doc3.headers['content-type'].should eq("application/json; charset=utf-8")
|
||||
doc3.parsed_response.length.should eq(2)
|
||||
doc3.parsed_response[0]['name'].should eq("abc")
|
||||
doc3.parsed_response[1]['name'].should eq("def")
|
||||
doc3.parsed_response[0]['type'].should eq("type1")
|
||||
doc3.parsed_response[1]['type'].should eq("type2")
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
@ -24,11 +24,14 @@
|
|||
|
||||
#include "RestViewHandler.h"
|
||||
#include "Basics/Exceptions.h"
|
||||
#include "Basics/StringUtils.h"
|
||||
#include "Basics/VelocyPackHelper.h"
|
||||
#include "VocBase/LogicalView.h"
|
||||
|
||||
#include <velocypack/velocypack-aliases.h>
|
||||
|
||||
using namespace arangodb;
|
||||
using namespace arangodb::basics;
|
||||
using namespace arangodb::rest;
|
||||
|
||||
RestViewHandler::RestViewHandler(GeneralRequest* request,
|
||||
|
@ -54,6 +57,11 @@ RestStatus RestViewHandler::execute() {
|
|||
return RestStatus::DONE;
|
||||
}
|
||||
|
||||
if (type == rest::RequestType::GET) {
|
||||
getViews();
|
||||
return RestStatus::DONE;
|
||||
}
|
||||
|
||||
generateError(rest::ResponseCode::METHOD_NOT_ALLOWED,
|
||||
TRI_ERROR_HTTP_METHOD_NOT_ALLOWED);
|
||||
return RestStatus::DONE;
|
||||
|
@ -106,7 +114,11 @@ void RestViewHandler::createView() {
|
|||
TRI_voc_cid_t id = 0;
|
||||
std::shared_ptr<LogicalView> view = _vocbase->createView(body, id);
|
||||
if (view != nullptr) {
|
||||
generateOk(rest::ResponseCode::CREATED);
|
||||
VPackBuilder props;
|
||||
props.openObject();
|
||||
view->toVelocyPack(props);
|
||||
props.close();
|
||||
generateResult(rest::ResponseCode::CREATED, props.slice());
|
||||
} else {
|
||||
generateError(rest::ResponseCode::SERVER_ERROR, TRI_ERROR_INTERNAL,
|
||||
"problem creating view");
|
||||
|
@ -181,10 +193,72 @@ void RestViewHandler::deleteView() {
|
|||
if (res == TRI_ERROR_NO_ERROR) {
|
||||
generateOk();
|
||||
} else if (res == TRI_ERROR_ARANGO_COLLECTION_NOT_FOUND) {
|
||||
generateError(rest::ResponseCode::NOT_FOUND, TRI_ERROR_ARANGO_COLLECTION_NOT_FOUND,
|
||||
generateError(rest::ResponseCode::NOT_FOUND,
|
||||
TRI_ERROR_ARANGO_COLLECTION_NOT_FOUND,
|
||||
"could not find view by that name");
|
||||
} else {
|
||||
generateError(rest::ResponseCode::SERVER_ERROR, TRI_ERROR_INTERNAL,
|
||||
"problem dropping view");
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief was docuBlock JSF_post_api_cursor_delete
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void RestViewHandler::getViews() {
|
||||
std::vector<std::string> const& suffixes = _request->suffixes();
|
||||
|
||||
if (suffixes.size() > 1) {
|
||||
generateError(rest::ResponseCode::BAD, TRI_ERROR_HTTP_BAD_PARAMETER,
|
||||
"expecting GET [/_api/view | /_api/view/<view-name>]");
|
||||
return;
|
||||
}
|
||||
|
||||
if (suffixes.size() == 0) {
|
||||
getListOfViews();
|
||||
return;
|
||||
} else {
|
||||
std::string const& name = suffixes[0];
|
||||
getSingleView(name);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void RestViewHandler::getListOfViews() {
|
||||
std::vector<std::shared_ptr<LogicalView>> views = _vocbase->views();
|
||||
std::sort(views.begin(), views.end(),
|
||||
[](std::shared_ptr<LogicalView> const& lhs,
|
||||
std::shared_ptr<LogicalView> const& rhs) -> bool {
|
||||
return StringUtils::tolower(lhs->name()) <
|
||||
StringUtils::tolower(rhs->name());
|
||||
});
|
||||
|
||||
VPackBuilder props;
|
||||
props.openArray();
|
||||
for (std::shared_ptr<LogicalView> view : views) {
|
||||
if (view.get() != nullptr) {
|
||||
props.openObject();
|
||||
view->toVelocyPack(props);
|
||||
props.close();
|
||||
}
|
||||
}
|
||||
props.close();
|
||||
generateResult(rest::ResponseCode::OK, props.slice());
|
||||
}
|
||||
|
||||
void RestViewHandler::getSingleView(std::string const& name) {
|
||||
std::shared_ptr<LogicalView> view = _vocbase->lookupView(name);
|
||||
|
||||
if (view.get() != nullptr) {
|
||||
VPackBuilder props;
|
||||
props.openObject();
|
||||
view->toVelocyPack(props);
|
||||
props.close();
|
||||
generateResult(rest::ResponseCode::OK, props.slice());
|
||||
} else {
|
||||
generateError(rest::ResponseCode::NOT_FOUND,
|
||||
TRI_ERROR_ARANGO_COLLECTION_NOT_FOUND,
|
||||
"could not find view by that name");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -46,6 +46,10 @@ class RestViewHandler : public RestVocbaseBaseHandler {
|
|||
void createView();
|
||||
void modifyView();
|
||||
void deleteView();
|
||||
void getViews();
|
||||
|
||||
void getSingleView(std::string const&);
|
||||
void getListOfViews();
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -89,7 +89,6 @@ static std::string const ReadStringValue(VPackSlice info,
|
|||
}
|
||||
return Helper::getStringValue(info, name, def);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/// @brief This the "copy" constructor used in the cluster
|
||||
|
@ -110,16 +109,14 @@ LogicalView::LogicalView(LogicalView const& other)
|
|||
// @brief Constructor used in coordinator case.
|
||||
// The Slice contains the part of the plan that
|
||||
// is relevant for this view
|
||||
LogicalView::LogicalView(TRI_vocbase_t* vocbase,
|
||||
VPackSlice const& info)
|
||||
LogicalView::LogicalView(TRI_vocbase_t* vocbase, VPackSlice const& info)
|
||||
: _id(ReadId(info)),
|
||||
_planId(ReadPlanId(info, _id)),
|
||||
_type(ReadStringValue(info, "type", "")),
|
||||
_name(ReadStringValue(info, "name", "")),
|
||||
_isDeleted(Helper::readBooleanValue(info, "deleted", false)),
|
||||
_vocbase(vocbase),
|
||||
_physical(
|
||||
EngineSelectorFeature::ENGINE->createPhysicalView(this, info)) {
|
||||
_physical(EngineSelectorFeature::ENGINE->createPhysicalView(this, info)) {
|
||||
TRI_ASSERT(_physical != nullptr);
|
||||
if (!IsAllowedName(info)) {
|
||||
THROW_ARANGO_EXCEPTION(TRI_ERROR_ARANGO_ILLEGAL_NAME);
|
||||
|
@ -208,7 +205,7 @@ void LogicalView::toVelocyPack(VPackBuilder& result) const {
|
|||
|
||||
// Cluster Specific
|
||||
result.add("planId", VPackValue(std::to_string(_planId)));
|
||||
|
||||
|
||||
TRI_ASSERT(result.isOpenObject());
|
||||
// We leave the object open
|
||||
}
|
||||
|
@ -217,7 +214,7 @@ arangodb::Result LogicalView::updateProperties(VPackSlice const& slice,
|
|||
bool doSync) {
|
||||
WRITE_LOCKER(writeLocker, _infoLock);
|
||||
|
||||
// The physical may first reject illegal properties.
|
||||
// The physical may first reject illegal properties.
|
||||
// After this call it either has thrown or the properties are stored
|
||||
getPhysical()->updateProperties(slice, doSync);
|
||||
|
||||
|
@ -240,3 +237,10 @@ void LogicalView::persistPhysicalView() {
|
|||
engine->createView(_vocbase, _id, this);
|
||||
}
|
||||
|
||||
void LogicalView::spawnImplementation(ViewCreator creator) {
|
||||
VPackBuilder properties;
|
||||
properties.openObject();
|
||||
toVelocyPack(properties);
|
||||
properties.close();
|
||||
_implementation = creator(this, getPhysical(), properties.slice());
|
||||
}
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
|
||||
#include "Basics/Common.h"
|
||||
#include "Basics/Result.h"
|
||||
#include "VocBase/ViewImplementation.h"
|
||||
#include "VocBase/voc-types.h"
|
||||
#include "VocBase/vocbase.h"
|
||||
|
||||
|
@ -44,7 +45,7 @@ class LogicalView {
|
|||
|
||||
public:
|
||||
LogicalView(TRI_vocbase_t*, velocypack::Slice const&);
|
||||
~LogicalView();
|
||||
~LogicalView();
|
||||
|
||||
protected: // If you need a copy outside the class, use clone below.
|
||||
explicit LogicalView(LogicalView const&);
|
||||
|
@ -61,7 +62,7 @@ class LogicalView {
|
|||
}
|
||||
|
||||
inline TRI_voc_cid_t id() const { return _id; }
|
||||
|
||||
|
||||
TRI_voc_cid_t planId() const;
|
||||
|
||||
std::string type() const { return _type; }
|
||||
|
@ -72,7 +73,7 @@ class LogicalView {
|
|||
void setDeleted(bool);
|
||||
|
||||
PhysicalView* getPhysical() const { return _physical.get(); }
|
||||
|
||||
|
||||
void drop();
|
||||
|
||||
// SECTION: Serialization
|
||||
|
@ -87,7 +88,10 @@ class LogicalView {
|
|||
/// This should be called AFTER the view is successfully
|
||||
/// created and only on Sinlge/DBServer
|
||||
void persistPhysicalView();
|
||||
|
||||
|
||||
/// @brief Create implementation object using factory method
|
||||
void spawnImplementation(ViewCreator creator);
|
||||
|
||||
static bool IsAllowedName(velocypack::Slice parameters);
|
||||
static bool IsAllowedName(std::string const& name);
|
||||
|
||||
|
@ -96,7 +100,7 @@ class LogicalView {
|
|||
//
|
||||
// @brief Local view id
|
||||
TRI_voc_cid_t const _id;
|
||||
|
||||
|
||||
// @brief Global view id
|
||||
TRI_voc_cid_t const _planId;
|
||||
|
||||
|
@ -111,9 +115,10 @@ class LogicalView {
|
|||
TRI_vocbase_t* _vocbase;
|
||||
|
||||
std::unique_ptr<PhysicalView> _physical;
|
||||
std::unique_ptr<ViewImplementation> _implementation;
|
||||
|
||||
mutable basics::ReadWriteLock _lock; // lock protecting the status and name
|
||||
mutable basics::ReadWriteLock _infoLock; // lock protecting the properties
|
||||
mutable basics::ReadWriteLock _lock; // lock protecting the status and name
|
||||
mutable basics::ReadWriteLock _infoLock; // lock protecting the properties
|
||||
};
|
||||
|
||||
} // namespace arangodb
|
||||
|
|
|
@ -0,0 +1,70 @@
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// DISCLAIMER
|
||||
///
|
||||
/// Copyright 2014-2016 ArangoDB GmbH, Cologne, Germany
|
||||
/// Copyright 2004-2014 triAGENS GmbH, Cologne, Germany
|
||||
///
|
||||
/// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
/// you may not use this file except in compliance with the License.
|
||||
/// You may obtain a copy of the License at
|
||||
///
|
||||
/// http://www.apache.org/licenses/LICENSE-2.0
|
||||
///
|
||||
/// Unless required by applicable law or agreed to in writing, software
|
||||
/// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
/// See the License for the specific language governing permissions and
|
||||
/// limitations under the License.
|
||||
///
|
||||
/// Copyright holder is ArangoDB GmbH, Cologne, Germany
|
||||
///
|
||||
/// @author Jan Steemann
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef ARANGOD_VOCBASE_VIEW_IMPLEMENTATION_H
|
||||
#define ARANGOD_VOCBASE_VIEW_IMPLEMENTATION_H 1
|
||||
|
||||
#include "Basics/Common.h"
|
||||
#include "VocBase/voc-types.h"
|
||||
|
||||
#include <velocypack/Builder.h>
|
||||
#include <velocypack/Slice.h>
|
||||
|
||||
namespace arangodb {
|
||||
class LogicalView;
|
||||
class PhysicalView;
|
||||
class Result;
|
||||
|
||||
class ViewImplementation {
|
||||
protected:
|
||||
ViewImplementation(LogicalView* logical, PhysicalView* physical,
|
||||
arangodb::velocypack::Slice const& info)
|
||||
: _logicalView(logical), _physicalView(physical) {}
|
||||
|
||||
public:
|
||||
virtual ~ViewImplementation() = default;
|
||||
|
||||
virtual arangodb::Result updateProperties(
|
||||
arangodb::velocypack::Slice const& slice, bool doSync) = 0;
|
||||
virtual arangodb::Result persistProperties() noexcept = 0;
|
||||
|
||||
/// @brief export properties
|
||||
virtual void getPropertiesVPack(velocypack::Builder&) const = 0;
|
||||
|
||||
/// @brief opens an existing view
|
||||
virtual void open(bool ignoreErrors) = 0;
|
||||
|
||||
virtual void drop() = 0;
|
||||
|
||||
protected:
|
||||
LogicalView* _logicalView;
|
||||
PhysicalView* _physicalView;
|
||||
};
|
||||
|
||||
typedef std::function<std::unique_ptr<ViewImplementation>(
|
||||
LogicalView*, PhysicalView*, arangodb::velocypack::Slice const&)>
|
||||
ViewCreator;
|
||||
|
||||
} // namespace arangodb
|
||||
|
||||
#endif
|
|
@ -29,9 +29,9 @@
|
|||
#include <velocypack/velocypack-aliases.h>
|
||||
|
||||
#include "ApplicationFeatures/ApplicationServer.h"
|
||||
#include "Aql/PlanCache.h"
|
||||
#include "Aql/QueryCache.h"
|
||||
#include "Aql/QueryList.h"
|
||||
#include "Aql/PlanCache.h"
|
||||
#include "Basics/ConditionLocker.h"
|
||||
#include "Basics/Exceptions.h"
|
||||
#include "Basics/FileUtils.h"
|
||||
|
@ -62,6 +62,7 @@
|
|||
#include "VocBase/LogicalView.h"
|
||||
#include "VocBase/PhysicalCollection.h"
|
||||
#include "VocBase/PhysicalView.h"
|
||||
#include "VocBase/ViewImplementation.h"
|
||||
#include "VocBase/replication-applier.h"
|
||||
#include "VocBase/ticks.h"
|
||||
|
||||
|
@ -69,7 +70,7 @@
|
|||
|
||||
using namespace arangodb;
|
||||
using namespace arangodb::basics;
|
||||
|
||||
|
||||
/// @brief increase the reference counter for a database
|
||||
bool TRI_vocbase_t::use() {
|
||||
auto expected = _refCount.load(std::memory_order_relaxed);
|
||||
|
@ -83,7 +84,9 @@ bool TRI_vocbase_t::use() {
|
|||
// marked as deleted
|
||||
auto updated = expected + 2;
|
||||
TRI_ASSERT((updated & 1) == 0);
|
||||
if (_refCount.compare_exchange_weak(expected, updated, std::memory_order_release, std::memory_order_relaxed)) {
|
||||
if (_refCount.compare_exchange_weak(expected, updated,
|
||||
std::memory_order_release,
|
||||
std::memory_order_relaxed)) {
|
||||
// compare-exchange worked. we're done
|
||||
return true;
|
||||
}
|
||||
|
@ -92,9 +95,7 @@ bool TRI_vocbase_t::use() {
|
|||
}
|
||||
}
|
||||
|
||||
void TRI_vocbase_t::forceUse() {
|
||||
_refCount += 2;
|
||||
}
|
||||
void TRI_vocbase_t::forceUse() { _refCount += 2; }
|
||||
|
||||
/// @brief decrease the reference counter for a database
|
||||
void TRI_vocbase_t::release() {
|
||||
|
@ -115,7 +116,7 @@ bool TRI_vocbase_t::isDangling() const {
|
|||
// that noone else references the database but it has been marked as deleted
|
||||
return (refCount == 1);
|
||||
}
|
||||
|
||||
|
||||
/// @brief whether or not the vocbase has been marked as deleted
|
||||
bool TRI_vocbase_t::isDropped() const {
|
||||
auto refCount = _refCount.load();
|
||||
|
@ -151,12 +152,14 @@ void TRI_vocbase_t::registerCollection(
|
|||
|
||||
// check name
|
||||
auto it = _collectionsByName.emplace(name, collection);
|
||||
|
||||
|
||||
if (!it.second) {
|
||||
LOG_TOPIC(ERR, arangodb::Logger::FIXME) << "duplicate entry for collection name '" << name << "'";
|
||||
LOG_TOPIC(ERR, arangodb::Logger::FIXME) << "collection id " << cid
|
||||
<< " has same name as already added collection "
|
||||
<< _collectionsByName[name]->cid();
|
||||
LOG_TOPIC(ERR, arangodb::Logger::FIXME)
|
||||
<< "duplicate entry for collection name '" << name << "'";
|
||||
LOG_TOPIC(ERR, arangodb::Logger::FIXME)
|
||||
<< "collection id " << cid
|
||||
<< " has same name as already added collection "
|
||||
<< _collectionsByName[name]->cid();
|
||||
|
||||
THROW_ARANGO_EXCEPTION(TRI_ERROR_ARANGO_DUPLICATE_NAME);
|
||||
}
|
||||
|
@ -168,13 +171,13 @@ void TRI_vocbase_t::registerCollection(
|
|||
if (!it2.second) {
|
||||
_collectionsByName.erase(name);
|
||||
|
||||
LOG_TOPIC(ERR, arangodb::Logger::FIXME) << "duplicate collection identifier " << collection->cid()
|
||||
<< " for name '" << name << "'";
|
||||
LOG_TOPIC(ERR, arangodb::Logger::FIXME)
|
||||
<< "duplicate collection identifier " << collection->cid()
|
||||
<< " for name '" << name << "'";
|
||||
|
||||
THROW_ARANGO_EXCEPTION(TRI_ERROR_ARANGO_DUPLICATE_IDENTIFIER);
|
||||
}
|
||||
}
|
||||
catch (...) {
|
||||
} catch (...) {
|
||||
_collectionsByName.erase(name);
|
||||
throw;
|
||||
}
|
||||
|
@ -183,14 +186,13 @@ void TRI_vocbase_t::registerCollection(
|
|||
|
||||
try {
|
||||
_collections.emplace_back(collection);
|
||||
}
|
||||
catch (...) {
|
||||
} catch (...) {
|
||||
_collectionsByName.erase(name);
|
||||
_collectionsById.erase(cid);
|
||||
TRI_ASSERT(_collectionsByName.size() == _collectionsById.size());
|
||||
throw;
|
||||
}
|
||||
|
||||
|
||||
collection->setStatus(TRI_VOC_COL_STATUS_UNLOADED);
|
||||
TRI_ASSERT(_collectionsByName.size() == _collectionsById.size());
|
||||
}
|
||||
|
@ -199,10 +201,11 @@ void TRI_vocbase_t::registerCollection(
|
|||
/// @brief removes a collection name from the global list of collections
|
||||
/// This function is called when a collection is dropped.
|
||||
/// NOTE: You need a writelock on _collectionsLock
|
||||
bool TRI_vocbase_t::unregisterCollection(arangodb::LogicalCollection* collection) {
|
||||
bool TRI_vocbase_t::unregisterCollection(
|
||||
arangodb::LogicalCollection* collection) {
|
||||
TRI_ASSERT(collection != nullptr);
|
||||
std::string const colName(collection->name());
|
||||
|
||||
|
||||
// pre-condition
|
||||
TRI_ASSERT(_collectionsByName.size() == _collectionsById.size());
|
||||
|
||||
|
@ -211,8 +214,8 @@ bool TRI_vocbase_t::unregisterCollection(arangodb::LogicalCollection* collection
|
|||
// this is because someone else might have created a new collection with the
|
||||
// same name, but with a different id
|
||||
_collectionsByName.erase(colName);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// post-condition
|
||||
TRI_ASSERT(_collectionsByName.size() == _collectionsById.size());
|
||||
|
||||
|
@ -221,8 +224,8 @@ bool TRI_vocbase_t::unregisterCollection(arangodb::LogicalCollection* collection
|
|||
|
||||
/// @brief adds a new view
|
||||
/// caller must hold _viewLock in write mode or set doLock
|
||||
void TRI_vocbase_t::registerView(
|
||||
bool doLock, std::shared_ptr<arangodb::LogicalView> view) {
|
||||
void TRI_vocbase_t::registerView(bool doLock,
|
||||
std::shared_ptr<arangodb::LogicalView> view) {
|
||||
std::string const name = view->name();
|
||||
TRI_voc_cid_t const id = view->id();
|
||||
{
|
||||
|
@ -230,12 +233,13 @@ void TRI_vocbase_t::registerView(
|
|||
|
||||
// check name
|
||||
auto it = _viewsByName.emplace(name, view);
|
||||
|
||||
|
||||
if (!it.second) {
|
||||
LOG_TOPIC(ERR, arangodb::Logger::FIXME) << "duplicate entry for view name '" << name << "'";
|
||||
LOG_TOPIC(ERR, arangodb::Logger::FIXME) << "view id " << id
|
||||
<< " has same name as already added view "
|
||||
<< _viewsByName[name]->id();
|
||||
LOG_TOPIC(ERR, arangodb::Logger::FIXME)
|
||||
<< "duplicate entry for view name '" << name << "'";
|
||||
LOG_TOPIC(ERR, arangodb::Logger::FIXME)
|
||||
<< "view id " << id << " has same name as already added view "
|
||||
<< _viewsByName[name]->id();
|
||||
|
||||
THROW_ARANGO_EXCEPTION(TRI_ERROR_ARANGO_DUPLICATE_NAME);
|
||||
}
|
||||
|
@ -247,13 +251,13 @@ void TRI_vocbase_t::registerView(
|
|||
if (!it2.second) {
|
||||
_viewsByName.erase(name);
|
||||
|
||||
LOG_TOPIC(ERR, arangodb::Logger::FIXME) << "duplicate view identifier " << view->id()
|
||||
<< " for name '" << name << "'";
|
||||
LOG_TOPIC(ERR, arangodb::Logger::FIXME) << "duplicate view identifier "
|
||||
<< view->id() << " for name '"
|
||||
<< name << "'";
|
||||
|
||||
THROW_ARANGO_EXCEPTION(TRI_ERROR_ARANGO_DUPLICATE_IDENTIFIER);
|
||||
}
|
||||
}
|
||||
catch (...) {
|
||||
} catch (...) {
|
||||
_viewsByName.erase(name);
|
||||
throw;
|
||||
}
|
||||
|
@ -265,10 +269,11 @@ void TRI_vocbase_t::registerView(
|
|||
/// @brief removes a views name from the global list of views
|
||||
/// This function is called when a view is dropped.
|
||||
/// NOTE: You need a writelock on _viewsLock
|
||||
bool TRI_vocbase_t::unregisterView(std::shared_ptr<arangodb::LogicalView> view) {
|
||||
bool TRI_vocbase_t::unregisterView(
|
||||
std::shared_ptr<arangodb::LogicalView> view) {
|
||||
TRI_ASSERT(view != nullptr);
|
||||
std::string const name(view->name());
|
||||
|
||||
|
||||
// pre-condition
|
||||
TRI_ASSERT(_viewsByName.size() == _viewsById.size());
|
||||
|
||||
|
@ -277,8 +282,8 @@ bool TRI_vocbase_t::unregisterView(std::shared_ptr<arangodb::LogicalView> view)
|
|||
// this is because someone else might have created a new view with the
|
||||
// same name, but with a different id
|
||||
_viewsByName.erase(name);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// post-condition
|
||||
TRI_ASSERT(_viewsByName.size() == _viewsById.size());
|
||||
|
||||
|
@ -315,8 +320,9 @@ bool TRI_vocbase_t::UnloadCollectionCallback(LogicalCollection* collection) {
|
|||
|
||||
if (res != TRI_ERROR_NO_ERROR) {
|
||||
std::string const colName(collection->name());
|
||||
LOG_TOPIC(ERR, arangodb::Logger::FIXME) << "failed to close collection '" << colName
|
||||
<< "': " << TRI_last_error();
|
||||
LOG_TOPIC(ERR, arangodb::Logger::FIXME) << "failed to close collection '"
|
||||
<< colName
|
||||
<< "': " << TRI_last_error();
|
||||
|
||||
collection->setStatus(TRI_VOC_COL_STATUS_CORRUPTED);
|
||||
return true;
|
||||
|
@ -328,17 +334,19 @@ bool TRI_vocbase_t::UnloadCollectionCallback(LogicalCollection* collection) {
|
|||
}
|
||||
|
||||
/// @brief drops a collection
|
||||
bool TRI_vocbase_t::DropCollectionCallback(arangodb::LogicalCollection* collection) {
|
||||
bool TRI_vocbase_t::DropCollectionCallback(
|
||||
arangodb::LogicalCollection* collection) {
|
||||
std::string const name(collection->name());
|
||||
|
||||
{
|
||||
WRITE_LOCKER_EVENTUAL(statusLock, collection->_lock);
|
||||
WRITE_LOCKER_EVENTUAL(statusLock, collection->_lock);
|
||||
|
||||
if (collection->status() != TRI_VOC_COL_STATUS_DELETED) {
|
||||
LOG_TOPIC(ERR, arangodb::Logger::FIXME) << "someone resurrected the collection '" << name << "'";
|
||||
LOG_TOPIC(ERR, arangodb::Logger::FIXME)
|
||||
<< "someone resurrected the collection '" << name << "'";
|
||||
return false;
|
||||
}
|
||||
} // release status lock
|
||||
} // release status lock
|
||||
|
||||
// remove from list of collections
|
||||
TRI_vocbase_t* vocbase = collection->vocbase();
|
||||
|
@ -367,9 +375,10 @@ bool TRI_vocbase_t::DropCollectionCallback(arangodb::LogicalCollection* collecti
|
|||
/// @brief creates a new collection, worker function
|
||||
arangodb::LogicalCollection* TRI_vocbase_t::createCollectionWorker(
|
||||
VPackSlice parameters, TRI_voc_cid_t& cid) {
|
||||
std::string name = arangodb::basics::VelocyPackHelper::getStringValue(parameters, "name" , "");
|
||||
std::string name = arangodb::basics::VelocyPackHelper::getStringValue(
|
||||
parameters, "name", "");
|
||||
TRI_ASSERT(!name.empty());
|
||||
|
||||
|
||||
// Try to create a new collection. This is not registered yet
|
||||
|
||||
std::unique_ptr<arangodb::LogicalCollection> collection =
|
||||
|
@ -401,7 +410,7 @@ arangodb::LogicalCollection* TRI_vocbase_t::createCollectionWorker(
|
|||
|
||||
// Let's try to persist it.
|
||||
collection->persistPhysicalCollection();
|
||||
|
||||
|
||||
events::CreateCollection(name, TRI_ERROR_NO_ERROR);
|
||||
return collection.release();
|
||||
} catch (...) {
|
||||
|
@ -505,7 +514,9 @@ int TRI_vocbase_t::loadCollection(arangodb::LogicalCollection* collection,
|
|||
}
|
||||
|
||||
// only throw this particular error if the server is configured to do so
|
||||
auto databaseFeature = application_features::ApplicationServer::getFeature<DatabaseFeature>("Database");
|
||||
auto databaseFeature =
|
||||
application_features::ApplicationServer::getFeature<DatabaseFeature>(
|
||||
"Database");
|
||||
if (databaseFeature->throwCollectionNotLoadedError()) {
|
||||
return TRI_ERROR_ARANGO_COLLECTION_NOT_LOADED;
|
||||
}
|
||||
|
@ -526,7 +537,7 @@ int TRI_vocbase_t::loadCollection(arangodb::LogicalCollection* collection,
|
|||
// status while it is loading (loading may take a long time because of
|
||||
// disk activity, index creation etc.)
|
||||
locker.unlock();
|
||||
|
||||
|
||||
bool ignoreDatafileErrors = false;
|
||||
if (DatabaseFeature::DATABASE != nullptr) {
|
||||
ignoreDatafileErrors = DatabaseFeature::DATABASE->ignoreDatafileErrors();
|
||||
|
@ -535,15 +546,21 @@ int TRI_vocbase_t::loadCollection(arangodb::LogicalCollection* collection,
|
|||
try {
|
||||
collection->open(ignoreDatafileErrors);
|
||||
} catch (arangodb::basics::Exception const& ex) {
|
||||
LOG_TOPIC(ERR, arangodb::Logger::FIXME) << "caught exception while opening collection '" << collection->name() << "': " << ex.what();
|
||||
LOG_TOPIC(ERR, arangodb::Logger::FIXME)
|
||||
<< "caught exception while opening collection '" << collection->name()
|
||||
<< "': " << ex.what();
|
||||
collection->setStatus(TRI_VOC_COL_STATUS_CORRUPTED);
|
||||
return TRI_ERROR_ARANGO_CORRUPTED_COLLECTION;
|
||||
} catch (std::exception const& ex) {
|
||||
LOG_TOPIC(ERR, arangodb::Logger::FIXME) << "caught exception while opening collection '" << collection->name() << "': " << ex.what();
|
||||
LOG_TOPIC(ERR, arangodb::Logger::FIXME)
|
||||
<< "caught exception while opening collection '" << collection->name()
|
||||
<< "': " << ex.what();
|
||||
collection->setStatus(TRI_VOC_COL_STATUS_CORRUPTED);
|
||||
return TRI_ERROR_ARANGO_CORRUPTED_COLLECTION;
|
||||
} catch (...) {
|
||||
LOG_TOPIC(ERR, arangodb::Logger::FIXME) << "caught unknown exception while opening collection '" << collection->name() << "'";
|
||||
LOG_TOPIC(ERR, arangodb::Logger::FIXME)
|
||||
<< "caught unknown exception while opening collection '"
|
||||
<< collection->name() << "'";
|
||||
collection->setStatus(TRI_VOC_COL_STATUS_CORRUPTED);
|
||||
return TRI_ERROR_ARANGO_CORRUPTED_COLLECTION;
|
||||
}
|
||||
|
@ -563,8 +580,9 @@ int TRI_vocbase_t::loadCollection(arangodb::LogicalCollection* collection,
|
|||
}
|
||||
|
||||
std::string const colName(collection->name());
|
||||
LOG_TOPIC(ERR, arangodb::Logger::FIXME) << "unknown collection status " << collection->status() << " for '"
|
||||
<< colName << "'";
|
||||
LOG_TOPIC(ERR, arangodb::Logger::FIXME) << "unknown collection status "
|
||||
<< collection->status() << " for '"
|
||||
<< colName << "'";
|
||||
|
||||
return TRI_set_errno(TRI_ERROR_INTERNAL);
|
||||
}
|
||||
|
@ -574,10 +592,12 @@ int TRI_vocbase_t::dropCollectionWorker(arangodb::LogicalCollection* collection,
|
|||
DropState& state) {
|
||||
state = DROP_EXIT;
|
||||
std::string const colName(collection->name());
|
||||
|
||||
|
||||
// do not acquire these locks instantly
|
||||
CONDITIONAL_WRITE_LOCKER(writeLocker, _collectionsLock, basics::ConditionalLocking::DoNotLock);
|
||||
CONDITIONAL_WRITE_LOCKER(locker, collection->_lock, basics::ConditionalLocking::DoNotLock);
|
||||
CONDITIONAL_WRITE_LOCKER(writeLocker, _collectionsLock,
|
||||
basics::ConditionalLocking::DoNotLock);
|
||||
CONDITIONAL_WRITE_LOCKER(locker, collection->_lock,
|
||||
basics::ConditionalLocking::DoNotLock);
|
||||
|
||||
while (true) {
|
||||
TRI_ASSERT(!writeLocker.isLocked());
|
||||
|
@ -596,7 +616,7 @@ int TRI_vocbase_t::dropCollectionWorker(arangodb::LogicalCollection* collection,
|
|||
|
||||
// unlock the write locker so we don't block other operations
|
||||
writeLocker.unlock();
|
||||
|
||||
|
||||
TRI_ASSERT(!writeLocker.isLocked());
|
||||
TRI_ASSERT(!locker.isLocked());
|
||||
|
||||
|
@ -634,8 +654,8 @@ int TRI_vocbase_t::dropCollectionWorker(arangodb::LogicalCollection* collection,
|
|||
|
||||
if (!collection->deleted()) {
|
||||
collection->setDeleted(true);
|
||||
|
||||
try {
|
||||
|
||||
try {
|
||||
StorageEngine* engine = EngineSelectorFeature::ENGINE;
|
||||
engine->changeCollection(this, collection->cid(), collection, doSync);
|
||||
} catch (arangodb::basics::Exception const& ex) {
|
||||
|
@ -659,7 +679,7 @@ int TRI_vocbase_t::dropCollectionWorker(arangodb::LogicalCollection* collection,
|
|||
StorageEngine* engine = EngineSelectorFeature::ENGINE;
|
||||
TRI_ASSERT(engine != nullptr);
|
||||
engine->dropCollection(this, collection);
|
||||
|
||||
|
||||
DropCollectionCallback(collection);
|
||||
break;
|
||||
}
|
||||
|
@ -668,13 +688,17 @@ int TRI_vocbase_t::dropCollectionWorker(arangodb::LogicalCollection* collection,
|
|||
// collection is loaded
|
||||
collection->setDeleted(true);
|
||||
|
||||
bool doSync = application_features::ApplicationServer::getFeature<DatabaseFeature>("Database")->forceSyncProperties();
|
||||
bool doSync =
|
||||
application_features::ApplicationServer::getFeature<DatabaseFeature>(
|
||||
"Database")
|
||||
->forceSyncProperties();
|
||||
doSync = (doSync && !MMFilesLogfileManager::instance()->isInRecovery());
|
||||
|
||||
VPackBuilder builder;
|
||||
StorageEngine* engine = EngineSelectorFeature::ENGINE;
|
||||
engine->getCollectionInfo(this, collection->cid(), builder, false, 0);
|
||||
arangodb::Result res = collection->updateProperties(builder.slice().get("parameters"), doSync);
|
||||
arangodb::Result res = collection->updateProperties(
|
||||
builder.slice().get("parameters"), doSync);
|
||||
|
||||
if (!res.ok()) {
|
||||
return res.errorNumber();
|
||||
|
@ -733,7 +757,7 @@ void TRI_vocbase_t::shutdown() {
|
|||
setState(TRI_vocbase_t::State::SHUTDOWN_COMPACTOR);
|
||||
|
||||
StorageEngine* engine = EngineSelectorFeature::ENGINE;
|
||||
// shutdownDatabase() stops all threads
|
||||
// shutdownDatabase() stops all threads
|
||||
engine->shutdownDatabase(this);
|
||||
|
||||
// this will signal the cleanup thread to do one last iteration
|
||||
|
@ -781,9 +805,12 @@ std::vector<std::string> TRI_vocbase_t::collectionNames() {
|
|||
/// The list of collections will be sorted if sort function is given
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
std::shared_ptr<VPackBuilder> TRI_vocbase_t::inventory(TRI_voc_tick_t maxTick,
|
||||
bool (*filter)(arangodb::LogicalCollection*, void*), void* data, bool shouldSort,
|
||||
std::function<bool(arangodb::LogicalCollection*, arangodb::LogicalCollection*)> sortCallback) {
|
||||
std::shared_ptr<VPackBuilder> TRI_vocbase_t::inventory(
|
||||
TRI_voc_tick_t maxTick, bool (*filter)(arangodb::LogicalCollection*, void*),
|
||||
void* data, bool shouldSort,
|
||||
std::function<bool(arangodb::LogicalCollection*,
|
||||
arangodb::LogicalCollection*)>
|
||||
sortCallback) {
|
||||
std::vector<arangodb::LogicalCollection*> collections;
|
||||
|
||||
// cycle on write-lock
|
||||
|
@ -874,7 +901,8 @@ LogicalCollection* TRI_vocbase_t::lookupCollection(std::string const& name) {
|
|||
}
|
||||
|
||||
/// @brief looks up a collection by name
|
||||
LogicalCollection* TRI_vocbase_t::lookupCollectionNoLock(std::string const& name) {
|
||||
LogicalCollection* TRI_vocbase_t::lookupCollectionNoLock(
|
||||
std::string const& name) {
|
||||
if (name.empty()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
@ -904,7 +932,7 @@ LogicalCollection* TRI_vocbase_t::lookupCollectionNoLock(std::string const& name
|
|||
/// @brief looks up a collection by identifier
|
||||
LogicalCollection* TRI_vocbase_t::lookupCollection(TRI_voc_cid_t id) {
|
||||
READ_LOCKER(readLocker, _collectionsLock);
|
||||
|
||||
|
||||
auto it = _collectionsById.find(id);
|
||||
|
||||
if (it == _collectionsById.end()) {
|
||||
|
@ -914,7 +942,8 @@ LogicalCollection* TRI_vocbase_t::lookupCollection(TRI_voc_cid_t id) {
|
|||
}
|
||||
|
||||
/// @brief looks up a view by name
|
||||
std::shared_ptr<LogicalView> TRI_vocbase_t::lookupView(std::string const& name) {
|
||||
std::shared_ptr<LogicalView> TRI_vocbase_t::lookupView(
|
||||
std::string const& name) {
|
||||
if (name.empty()) {
|
||||
return std::shared_ptr<LogicalView>();
|
||||
}
|
||||
|
@ -940,7 +969,7 @@ std::shared_ptr<LogicalView> TRI_vocbase_t::lookupView(std::string const& name)
|
|||
/// @brief looks up a view by identifier
|
||||
std::shared_ptr<LogicalView> TRI_vocbase_t::lookupView(TRI_voc_cid_t id) {
|
||||
READ_LOCKER(readLocker, _viewsLock);
|
||||
|
||||
|
||||
auto it = _viewsById.find(id);
|
||||
|
||||
if (it == _viewsById.end()) {
|
||||
|
@ -955,19 +984,18 @@ std::shared_ptr<LogicalView> TRI_vocbase_t::lookupView(TRI_voc_cid_t id) {
|
|||
/// using a cid of > 0 is supported to import dumps from other servers etc.
|
||||
/// but the functionality is not advertised
|
||||
arangodb::LogicalCollection* TRI_vocbase_t::createCollection(
|
||||
VPackSlice parameters,
|
||||
TRI_voc_cid_t cid) {
|
||||
VPackSlice parameters, TRI_voc_cid_t cid) {
|
||||
// check that the name does not contain any strange characters
|
||||
if (!LogicalCollection::IsAllowedName(parameters)) {
|
||||
THROW_ARANGO_EXCEPTION(TRI_ERROR_ARANGO_ILLEGAL_NAME);
|
||||
}
|
||||
|
||||
|
||||
READ_LOCKER(readLocker, _inventoryLock);
|
||||
|
||||
// note: cid may be modified by this function call
|
||||
arangodb::LogicalCollection* collection = createCollectionWorker(parameters, cid);
|
||||
|
||||
arangodb::LogicalCollection* collection =
|
||||
createCollectionWorker(parameters, cid);
|
||||
|
||||
if (collection == nullptr) {
|
||||
// something went wrong... must not continue
|
||||
return nullptr;
|
||||
|
@ -977,13 +1005,15 @@ arangodb::LogicalCollection* TRI_vocbase_t::createCollection(
|
|||
TRI_ASSERT(engine != nullptr);
|
||||
// TODO Review
|
||||
arangodb::Result res2 = engine->persistCollection(this, collection);
|
||||
// API compatibility, we always return the collection, even if creation failed.
|
||||
// API compatibility, we always return the collection, even if creation
|
||||
// failed.
|
||||
|
||||
return collection;
|
||||
}
|
||||
|
||||
/// @brief unloads a collection
|
||||
int TRI_vocbase_t::unloadCollection(arangodb::LogicalCollection* collection, bool force) {
|
||||
int TRI_vocbase_t::unloadCollection(arangodb::LogicalCollection* collection,
|
||||
bool force) {
|
||||
TRI_voc_cid_t cid = collection->cid();
|
||||
{
|
||||
WRITE_LOCKER_EVENTUAL(locker, collection->_lock);
|
||||
|
@ -1043,9 +1073,9 @@ int TRI_vocbase_t::unloadCollection(arangodb::LogicalCollection* collection, boo
|
|||
// add callback for unload
|
||||
arangodb::MMFilesCollection::toMMFilesCollection(collection)
|
||||
->ditches()
|
||||
->createMMFilesUnloadCollectionDitch(collection, UnloadCollectionCallback,
|
||||
__FILE__, __LINE__);
|
||||
} // release locks
|
||||
->createMMFilesUnloadCollectionDitch(
|
||||
collection, UnloadCollectionCallback, __FILE__, __LINE__);
|
||||
} // release locks
|
||||
|
||||
collection->unload();
|
||||
|
||||
|
@ -1057,11 +1087,11 @@ int TRI_vocbase_t::unloadCollection(arangodb::LogicalCollection* collection, boo
|
|||
}
|
||||
|
||||
/// @brief drops a collection
|
||||
int TRI_vocbase_t::dropCollection(arangodb::LogicalCollection* collection, bool allowDropSystem) {
|
||||
int TRI_vocbase_t::dropCollection(arangodb::LogicalCollection* collection,
|
||||
bool allowDropSystem) {
|
||||
TRI_ASSERT(collection != nullptr);
|
||||
|
||||
if (!allowDropSystem &&
|
||||
collection->isSystem() &&
|
||||
if (!allowDropSystem && collection->isSystem() &&
|
||||
!MMFilesLogfileManager::instance()->isInRecovery()) {
|
||||
// prevent dropping of system collections
|
||||
return TRI_set_errno(TRI_ERROR_FORBIDDEN);
|
||||
|
@ -1083,8 +1113,8 @@ int TRI_vocbase_t::dropCollection(arangodb::LogicalCollection* collection, bool
|
|||
// add callback for dropping
|
||||
arangodb::MMFilesCollection::toMMFilesCollection(collection)
|
||||
->ditches()
|
||||
->createMMFilesDropCollectionDitch(collection, DropCollectionCallback,
|
||||
__FILE__, __LINE__);
|
||||
->createMMFilesDropCollectionDitch(
|
||||
collection, DropCollectionCallback, __FILE__, __LINE__);
|
||||
|
||||
// wake up the cleanup thread
|
||||
StorageEngine* engine = EngineSelectorFeature::ENGINE;
|
||||
|
@ -1104,7 +1134,8 @@ int TRI_vocbase_t::dropCollection(arangodb::LogicalCollection* collection, bool
|
|||
|
||||
/// @brief renames a collection
|
||||
int TRI_vocbase_t::renameCollection(arangodb::LogicalCollection* collection,
|
||||
std::string const& newName, bool doOverride) {
|
||||
std::string const& newName,
|
||||
bool doOverride) {
|
||||
if (collection->isSystem()) {
|
||||
return TRI_set_errno(TRI_ERROR_FORBIDDEN);
|
||||
}
|
||||
|
@ -1139,10 +1170,10 @@ int TRI_vocbase_t::renameCollection(arangodb::LogicalCollection* collection,
|
|||
}
|
||||
|
||||
READ_LOCKER(readLocker, _inventoryLock);
|
||||
|
||||
|
||||
CONDITIONAL_WRITE_LOCKER(writeLocker, _collectionsLock, false);
|
||||
CONDITIONAL_WRITE_LOCKER(locker, collection->_lock, false);
|
||||
|
||||
|
||||
while (true) {
|
||||
TRI_ASSERT(!writeLocker.isLocked());
|
||||
TRI_ASSERT(!locker.isLocked());
|
||||
|
@ -1160,17 +1191,17 @@ int TRI_vocbase_t::renameCollection(arangodb::LogicalCollection* collection,
|
|||
|
||||
// unlock the write locker so we don't block other operations
|
||||
writeLocker.unlock();
|
||||
|
||||
|
||||
TRI_ASSERT(!writeLocker.isLocked());
|
||||
TRI_ASSERT(!locker.isLocked());
|
||||
|
||||
// sleep for a while
|
||||
std::this_thread::yield();
|
||||
}
|
||||
|
||||
|
||||
TRI_ASSERT(writeLocker.isLocked());
|
||||
TRI_ASSERT(locker.isLocked());
|
||||
|
||||
|
||||
// Check for duplicate name
|
||||
auto other = lookupCollectionNoLock(newName);
|
||||
|
||||
|
@ -1220,8 +1251,8 @@ int TRI_vocbase_t::useCollection(arangodb::LogicalCollection* collection,
|
|||
}
|
||||
|
||||
/// @brief locks a (document) collection for usage by id
|
||||
arangodb::LogicalCollection* TRI_vocbase_t::useCollection(TRI_voc_cid_t cid,
|
||||
TRI_vocbase_col_status_e& status) {
|
||||
arangodb::LogicalCollection* TRI_vocbase_t::useCollection(
|
||||
TRI_voc_cid_t cid, TRI_vocbase_col_status_e& status) {
|
||||
// check that we have an existing name
|
||||
arangodb::LogicalCollection* collection = nullptr;
|
||||
{
|
||||
|
@ -1252,8 +1283,8 @@ arangodb::LogicalCollection* TRI_vocbase_t::useCollection(TRI_voc_cid_t cid,
|
|||
}
|
||||
|
||||
/// @brief locks a collection for usage by name
|
||||
arangodb::LogicalCollection* TRI_vocbase_t::useCollection(std::string const& name,
|
||||
TRI_vocbase_col_status_e& status) {
|
||||
arangodb::LogicalCollection* TRI_vocbase_t::useCollection(
|
||||
std::string const& name, TRI_vocbase_col_status_e& status) {
|
||||
// check that we have an existing name
|
||||
arangodb::LogicalCollection* collection = nullptr;
|
||||
|
||||
|
@ -1288,12 +1319,22 @@ void TRI_vocbase_t::releaseCollection(arangodb::LogicalCollection* collection) {
|
|||
collection->_lock.unlock();
|
||||
}
|
||||
|
||||
void TRI_vocbase_t::registerViewImplementation(std::string const& type,
|
||||
ViewCreator creator) {
|
||||
_viewImplementations.emplace(type, creator);
|
||||
}
|
||||
|
||||
bool TRI_vocbase_t::unregisterViewImplementation(std::string const& type) {
|
||||
return (_viewImplementations.erase(type) > 0);
|
||||
}
|
||||
|
||||
/// @brief creates a new view, worker function
|
||||
std::shared_ptr<arangodb::LogicalView> TRI_vocbase_t::createViewWorker(
|
||||
VPackSlice parameters, TRI_voc_cid_t& id) {
|
||||
std::string name = arangodb::basics::VelocyPackHelper::getStringValue(parameters, "name" , "");
|
||||
std::string name = arangodb::basics::VelocyPackHelper::getStringValue(
|
||||
parameters, "name", "");
|
||||
TRI_ASSERT(!name.empty());
|
||||
|
||||
|
||||
// Try to create a new view. This is not registered yet
|
||||
|
||||
std::shared_ptr<arangodb::LogicalView> view =
|
||||
|
@ -1317,7 +1358,16 @@ std::shared_ptr<arangodb::LogicalView> TRI_vocbase_t::createViewWorker(
|
|||
|
||||
// Let's try to persist it.
|
||||
view->persistPhysicalView();
|
||||
|
||||
|
||||
// now let's actually create the backing implementation
|
||||
/* no implementations exist yet, need a dummy for testing
|
||||
auto creator = _viewImplementations.find(view->type());
|
||||
if (creator != _viewImplementations.end()) {
|
||||
view->spawnImplementation(*creator);
|
||||
} else {
|
||||
throw; // no creator found for that type
|
||||
}*/
|
||||
|
||||
events::CreateView(name, TRI_ERROR_NO_ERROR);
|
||||
return view;
|
||||
} catch (...) {
|
||||
|
@ -1332,18 +1382,17 @@ std::shared_ptr<arangodb::LogicalView> TRI_vocbase_t::createViewWorker(
|
|||
/// using a cid of > 0 is supported to import dumps from other servers etc.
|
||||
/// but the functionality is not advertised
|
||||
std::shared_ptr<arangodb::LogicalView> TRI_vocbase_t::createView(
|
||||
VPackSlice parameters,
|
||||
TRI_voc_cid_t id) {
|
||||
VPackSlice parameters, TRI_voc_cid_t id) {
|
||||
// check that the name does not contain any strange characters
|
||||
if (!LogicalView::IsAllowedName(parameters)) {
|
||||
THROW_ARANGO_EXCEPTION(TRI_ERROR_ARANGO_ILLEGAL_NAME);
|
||||
}
|
||||
|
||||
|
||||
READ_LOCKER(readLocker, _inventoryLock);
|
||||
|
||||
// note: id may be modified by this function call
|
||||
std::shared_ptr<LogicalView> view = createViewWorker(parameters, id);
|
||||
|
||||
|
||||
if (view == nullptr) {
|
||||
// something went wrong... must not continue
|
||||
return nullptr;
|
||||
|
@ -1360,7 +1409,7 @@ std::shared_ptr<arangodb::LogicalView> TRI_vocbase_t::createView(
|
|||
|
||||
int TRI_vocbase_t::dropView(std::string const& name) {
|
||||
std::shared_ptr<LogicalView> view = lookupView(name);
|
||||
|
||||
|
||||
if (view == nullptr) {
|
||||
return TRI_ERROR_ARANGO_COLLECTION_NOT_FOUND;
|
||||
}
|
||||
|
@ -1373,10 +1422,12 @@ int TRI_vocbase_t::dropView(std::shared_ptr<arangodb::LogicalView> view) {
|
|||
TRI_ASSERT(view != nullptr);
|
||||
|
||||
READ_LOCKER(readLocker, _inventoryLock);
|
||||
|
||||
|
||||
// do not acquire these locks instantly
|
||||
CONDITIONAL_WRITE_LOCKER(writeLocker, _viewsLock, basics::ConditionalLocking::DoNotLock);
|
||||
CONDITIONAL_WRITE_LOCKER(locker, view->_lock, basics::ConditionalLocking::DoNotLock);
|
||||
CONDITIONAL_WRITE_LOCKER(writeLocker, _viewsLock,
|
||||
basics::ConditionalLocking::DoNotLock);
|
||||
CONDITIONAL_WRITE_LOCKER(locker, view->_lock,
|
||||
basics::ConditionalLocking::DoNotLock);
|
||||
|
||||
while (true) {
|
||||
TRI_ASSERT(!writeLocker.isLocked());
|
||||
|
@ -1395,7 +1446,7 @@ int TRI_vocbase_t::dropView(std::shared_ptr<arangodb::LogicalView> view) {
|
|||
|
||||
// unlock the write locker so we don't block other operations
|
||||
writeLocker.unlock();
|
||||
|
||||
|
||||
TRI_ASSERT(!writeLocker.isLocked());
|
||||
TRI_ASSERT(!locker.isLocked());
|
||||
|
||||
|
@ -1416,19 +1467,19 @@ int TRI_vocbase_t::dropView(std::shared_ptr<arangodb::LogicalView> view) {
|
|||
b.close();
|
||||
|
||||
bool doSync =
|
||||
application_features::ApplicationServer::getFeature<DatabaseFeature>(
|
||||
application_features::ApplicationServer::getFeature<DatabaseFeature>(
|
||||
"Database")
|
||||
->forceSyncProperties();
|
||||
view->updateProperties(b.slice(), doSync);
|
||||
view->updateProperties(b.slice(), doSync);
|
||||
|
||||
unregisterView(view);
|
||||
|
||||
|
||||
StorageEngine* engine = EngineSelectorFeature::ENGINE;
|
||||
engine->dropView(this, view.get());
|
||||
|
||||
locker.unlock();
|
||||
writeLocker.unlock();
|
||||
|
||||
|
||||
events::DropView(view->name(), TRI_ERROR_NO_ERROR);
|
||||
|
||||
return TRI_ERROR_NO_ERROR;
|
||||
|
@ -1445,7 +1496,6 @@ TRI_vocbase_t::TRI_vocbase_t(TRI_vocbase_type_e type, TRI_voc_tick_t id,
|
|||
_isOwnAppsDirectory(true),
|
||||
_deadlockDetector(false),
|
||||
_userStructures(nullptr) {
|
||||
|
||||
_queries.reset(new arangodb::aql::QueryList(this));
|
||||
_cursorRepository.reset(new arangodb::CursorRepository(this));
|
||||
_collectionKeys.reset(new arangodb::CollectionKeysRepository());
|
||||
|
@ -1471,7 +1521,7 @@ TRI_vocbase_t::~TRI_vocbase_t() {
|
|||
delete it;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
std::string TRI_vocbase_t::path() const {
|
||||
StorageEngine* engine = EngineSelectorFeature::ENGINE;
|
||||
return engine->databasePath(this);
|
||||
|
@ -1512,7 +1562,7 @@ bool TRI_vocbase_t::IsAllowedName(bool allowSystem, std::string const& name) {
|
|||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void TRI_vocbase_t::addReplicationApplier(TRI_replication_applier_t* applier) {
|
||||
_replicationApplier.reset(applier);
|
||||
}
|
||||
|
@ -1567,7 +1617,8 @@ std::vector<std::shared_ptr<arangodb::LogicalView>> TRI_vocbase_t::views() {
|
|||
return views;
|
||||
}
|
||||
|
||||
std::vector<arangodb::LogicalCollection*> TRI_vocbase_t::collections(bool includeDeleted) {
|
||||
std::vector<arangodb::LogicalCollection*> TRI_vocbase_t::collections(
|
||||
bool includeDeleted) {
|
||||
std::vector<arangodb::LogicalCollection*> collections;
|
||||
|
||||
{
|
||||
|
@ -1604,7 +1655,7 @@ TRI_voc_rid_t TRI_ExtractRevisionId(VPackSlice slice) {
|
|||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/// @brief extract the _rev attribute from a slice as a slice
|
||||
VPackSlice TRI_ExtractRevisionIdAsSlice(VPackSlice const slice) {
|
||||
if (!slice.isObject()) {
|
||||
|
@ -1623,9 +1674,8 @@ void TRI_SanitizeObject(VPackSlice const slice, VPackBuilder& builder) {
|
|||
while (it.valid()) {
|
||||
StringRef key(it.key());
|
||||
if (key.empty() || key[0] != '_' ||
|
||||
(key != StaticStrings::KeyString &&
|
||||
key != StaticStrings::IdString &&
|
||||
key != StaticStrings::RevString)) {
|
||||
(key != StaticStrings::KeyString && key != StaticStrings::IdString &&
|
||||
key != StaticStrings::RevString)) {
|
||||
builder.add(key.data(), key.size(), it.value());
|
||||
}
|
||||
it.next();
|
||||
|
@ -1634,17 +1684,16 @@ void TRI_SanitizeObject(VPackSlice const slice, VPackBuilder& builder) {
|
|||
|
||||
/// @brief sanitize an object, given as slice, builder must contain an
|
||||
/// open object which will remain open. also excludes _from and _to
|
||||
void TRI_SanitizeObjectWithEdges(VPackSlice const slice, VPackBuilder& builder) {
|
||||
void TRI_SanitizeObjectWithEdges(VPackSlice const slice,
|
||||
VPackBuilder& builder) {
|
||||
TRI_ASSERT(slice.isObject());
|
||||
VPackObjectIterator it(slice, true);
|
||||
while (it.valid()) {
|
||||
StringRef key(it.key());
|
||||
if (key.empty() || key[0] != '_' ||
|
||||
(key != StaticStrings::KeyString &&
|
||||
key != StaticStrings::IdString &&
|
||||
key != StaticStrings::RevString &&
|
||||
key != StaticStrings::FromString &&
|
||||
key != StaticStrings::ToString)) {
|
||||
(key != StaticStrings::KeyString && key != StaticStrings::IdString &&
|
||||
key != StaticStrings::RevString && key != StaticStrings::FromString &&
|
||||
key != StaticStrings::ToString)) {
|
||||
builder.add(key.data(), key.length(), it.value());
|
||||
}
|
||||
it.next();
|
||||
|
@ -1652,8 +1701,9 @@ void TRI_SanitizeObjectWithEdges(VPackSlice const slice, VPackBuilder& builder)
|
|||
}
|
||||
|
||||
/// @brief Convert a revision ID to a string
|
||||
constexpr static TRI_voc_rid_t tickLimit
|
||||
= static_cast<TRI_voc_rid_t>(2016ULL - 1970ULL) * 1000ULL * 60ULL * 60ULL * 24ULL * 365ULL;
|
||||
constexpr static TRI_voc_rid_t tickLimit =
|
||||
static_cast<TRI_voc_rid_t>(2016ULL - 1970ULL) * 1000ULL * 60ULL * 60ULL *
|
||||
24ULL * 365ULL;
|
||||
|
||||
std::string TRI_RidToString(TRI_voc_rid_t rid) {
|
||||
if (rid <= tickLimit) {
|
||||
|
@ -1669,18 +1719,20 @@ TRI_voc_rid_t TRI_StringToRid(char const* p, size_t len, bool warn) {
|
|||
}
|
||||
|
||||
/// @brief Convert a string into a revision ID, returns 0 if format invalid
|
||||
TRI_voc_rid_t TRI_StringToRid(std::string const& ridStr, bool& isOld, bool warn) {
|
||||
TRI_voc_rid_t TRI_StringToRid(std::string const& ridStr, bool& isOld,
|
||||
bool warn) {
|
||||
return TRI_StringToRid(ridStr.c_str(), ridStr.size(), isOld, warn);
|
||||
}
|
||||
|
||||
/// @brief Convert a string into a revision ID, returns 0 if format invalid
|
||||
TRI_voc_rid_t TRI_StringToRid(char const* p, size_t len, bool& isOld, bool warn) {
|
||||
TRI_voc_rid_t TRI_StringToRid(char const* p, size_t len, bool& isOld,
|
||||
bool warn) {
|
||||
if (len > 0 && *p >= '1' && *p <= '9') {
|
||||
TRI_voc_rid_t r = arangodb::basics::StringUtils::uint64_check(p, len);
|
||||
if (warn && r > tickLimit) {
|
||||
// An old tick value that could be confused with a time stamp
|
||||
LOG_TOPIC(WARN, arangodb::Logger::FIXME)
|
||||
<< "Saw old _rev value that could be confused with a time stamp!";
|
||||
<< "Saw old _rev value that could be confused with a time stamp!";
|
||||
}
|
||||
isOld = true;
|
||||
return r;
|
||||
|
@ -1688,4 +1740,3 @@ TRI_voc_rid_t TRI_StringToRid(char const* p, size_t len, bool& isOld, bool warn)
|
|||
isOld = false;
|
||||
return HybridLogicalClock::decodeTimeStamp(p, len);
|
||||
}
|
||||
|
||||
|
|
|
@ -31,10 +31,11 @@
|
|||
#include "Basics/ReadWriteLock.h"
|
||||
#include "Basics/StringUtils.h"
|
||||
#include "Basics/voc-errors.h"
|
||||
#include "VocBase/ViewImplementation.h"
|
||||
#include "VocBase/voc-types.h"
|
||||
|
||||
#include "velocypack/Slice.h"
|
||||
#include "velocypack/Builder.h"
|
||||
#include "velocypack/Slice.h"
|
||||
#include "velocypack/velocypack-aliases.h"
|
||||
|
||||
class TRI_replication_applier_t;
|
||||
|
@ -65,7 +66,7 @@ constexpr auto TRI_VOC_SYSTEM_DATABASE = "_system";
|
|||
constexpr size_t TRI_COL_NAME_LENGTH = 64;
|
||||
|
||||
/// @brief default maximal collection journal size
|
||||
constexpr size_t TRI_JOURNAL_DEFAULT_SIZE = 1024 * 1024 * 32; // 32 MB
|
||||
constexpr size_t TRI_JOURNAL_DEFAULT_SIZE = 1024 * 1024 * 32; // 32 MB
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief minimal collection journal size (for testing, we allow very small
|
||||
|
@ -74,11 +75,11 @@ constexpr size_t TRI_JOURNAL_DEFAULT_SIZE = 1024 * 1024 * 32; // 32 MB
|
|||
|
||||
#ifdef ARANGODB_ENABLE_MAINTAINER_MODE
|
||||
|
||||
constexpr size_t TRI_JOURNAL_MINIMAL_SIZE = 16 * 1024; // 16 KB
|
||||
constexpr size_t TRI_JOURNAL_MINIMAL_SIZE = 16 * 1024; // 16 KB
|
||||
|
||||
#else
|
||||
|
||||
constexpr size_t TRI_JOURNAL_MINIMAL_SIZE = 1024 * 1024; // 1 MB
|
||||
constexpr size_t TRI_JOURNAL_MINIMAL_SIZE = 1024 * 1024; // 1 MB
|
||||
|
||||
#endif
|
||||
|
||||
|
@ -96,7 +97,7 @@ constexpr auto TRI_INDEX_HANDLE_SEPARATOR_STR = "/";
|
|||
|
||||
/// @brief collection enum
|
||||
enum TRI_col_type_e : uint32_t {
|
||||
TRI_COL_TYPE_UNKNOWN = 0, // only used to signal an invalid collection type
|
||||
TRI_COL_TYPE_UNKNOWN = 0, // only used to signal an invalid collection type
|
||||
TRI_COL_TYPE_DOCUMENT = 2,
|
||||
TRI_COL_TYPE_EDGE = 3
|
||||
};
|
||||
|
@ -124,7 +125,7 @@ enum TRI_vocbase_col_status_e : int {
|
|||
struct TRI_vocbase_t {
|
||||
friend class arangodb::CollectionNameResolver;
|
||||
friend class arangodb::StorageEngine;
|
||||
|
||||
|
||||
/// @brief database state
|
||||
enum class State {
|
||||
NORMAL = 0,
|
||||
|
@ -133,51 +134,60 @@ struct TRI_vocbase_t {
|
|||
FAILED_VERSION = 3
|
||||
};
|
||||
|
||||
TRI_vocbase_t(TRI_vocbase_type_e type, TRI_voc_tick_t id, std::string const& name);
|
||||
TRI_vocbase_t(TRI_vocbase_type_e type, TRI_voc_tick_t id,
|
||||
std::string const& name);
|
||||
~TRI_vocbase_t();
|
||||
|
||||
private:
|
||||
/// @brief sleep interval used when polling for a loading collection's status
|
||||
static constexpr unsigned collectionStatusPollInterval() { return 10 * 1000; }
|
||||
|
||||
static constexpr unsigned collectionStatusPollInterval() { return 10 * 1000; }
|
||||
|
||||
/// @brief states for dropping
|
||||
enum DropState {
|
||||
DROP_EXIT, // drop done, nothing else to do
|
||||
DROP_AGAIN, // drop not done, must try again
|
||||
DROP_PERFORM // drop done, must perform actual cleanup routine
|
||||
DROP_EXIT, // drop done, nothing else to do
|
||||
DROP_AGAIN, // drop not done, must try again
|
||||
DROP_PERFORM // drop done, must perform actual cleanup routine
|
||||
};
|
||||
|
||||
TRI_voc_tick_t const _id; // internal database id
|
||||
TRI_voc_tick_t const _id; // internal database id
|
||||
std::string _name; // database name
|
||||
TRI_vocbase_type_e _type; // type (normal or coordinator)
|
||||
std::atomic<uint64_t> _refCount;
|
||||
State _state;
|
||||
bool _isOwnAppsDirectory;
|
||||
|
||||
|
||||
arangodb::basics::ReadWriteLock _collectionsLock; // collection iterator lock
|
||||
std::vector<arangodb::LogicalCollection*> _collections; // pointers to ALL collections
|
||||
std::vector<arangodb::LogicalCollection*> _deadCollections; // pointers to collections
|
||||
// dropped that can be
|
||||
// removed later
|
||||
|
||||
std::unordered_map<std::string, arangodb::LogicalCollection*> _collectionsByName; // collections by name
|
||||
std::unordered_map<TRI_voc_cid_t, arangodb::LogicalCollection*> _collectionsById; // collections by id
|
||||
|
||||
std::vector<arangodb::LogicalCollection*>
|
||||
_collections; // pointers to ALL collections
|
||||
std::vector<arangodb::LogicalCollection*>
|
||||
_deadCollections; // pointers to collections
|
||||
// dropped that can be
|
||||
// removed later
|
||||
|
||||
std::unordered_map<std::string, arangodb::LogicalCollection*>
|
||||
_collectionsByName; // collections by name
|
||||
std::unordered_map<TRI_voc_cid_t, arangodb::LogicalCollection*>
|
||||
_collectionsById; // collections by id
|
||||
|
||||
arangodb::basics::ReadWriteLock _viewsLock; // views management lock
|
||||
std::unordered_map<std::string, std::shared_ptr<arangodb::LogicalView>> _viewsByName; // views by name
|
||||
std::unordered_map<TRI_voc_cid_t, std::shared_ptr<arangodb::LogicalView>> _viewsById; // views by id
|
||||
|
||||
|
||||
std::unordered_map<std::string, std::shared_ptr<arangodb::LogicalView>>
|
||||
_viewsByName; // views by name
|
||||
std::unordered_map<TRI_voc_cid_t, std::shared_ptr<arangodb::LogicalView>>
|
||||
_viewsById; // views by id
|
||||
|
||||
std::unique_ptr<arangodb::aql::QueryList> _queries;
|
||||
std::unique_ptr<arangodb::CursorRepository> _cursorRepository;
|
||||
std::unique_ptr<arangodb::CollectionKeysRepository> _collectionKeys;
|
||||
|
||||
|
||||
std::unique_ptr<TRI_replication_applier_t> _replicationApplier;
|
||||
|
||||
|
||||
arangodb::basics::ReadWriteLock _replicationClientsLock;
|
||||
std::unordered_map<TRI_server_id_t, std::pair<double, TRI_voc_tick_t>>
|
||||
_replicationClients;
|
||||
|
||||
// view factory
|
||||
std::unordered_map<std::string, arangodb::ViewCreator> _viewImplementations;
|
||||
|
||||
public:
|
||||
arangodb::basics::DeadlockDetector<arangodb::LogicalCollection>
|
||||
_deadlockDetector;
|
||||
|
@ -199,13 +209,20 @@ struct TRI_vocbase_t {
|
|||
State state() const { return _state; }
|
||||
void setState(State state) { _state = state; }
|
||||
void updateReplicationClient(TRI_server_id_t, TRI_voc_tick_t);
|
||||
std::vector<std::tuple<TRI_server_id_t, double, TRI_voc_tick_t>> getReplicationClients();
|
||||
TRI_replication_applier_t* replicationApplier() const { return _replicationApplier.get(); }
|
||||
std::vector<std::tuple<TRI_server_id_t, double, TRI_voc_tick_t>>
|
||||
getReplicationClients();
|
||||
TRI_replication_applier_t* replicationApplier() const {
|
||||
return _replicationApplier.get();
|
||||
}
|
||||
void addReplicationApplier(TRI_replication_applier_t* applier);
|
||||
|
||||
arangodb::aql::QueryList* queryList() const { return _queries.get(); }
|
||||
arangodb::CursorRepository* cursorRepository() const { return _cursorRepository.get(); }
|
||||
arangodb::CollectionKeysRepository* collectionKeys() const { return _collectionKeys.get(); }
|
||||
arangodb::CursorRepository* cursorRepository() const {
|
||||
return _cursorRepository.get();
|
||||
}
|
||||
arangodb::CollectionKeysRepository* collectionKeys() const {
|
||||
return _collectionKeys.get();
|
||||
}
|
||||
|
||||
bool isOwnAppsDirectory() const { return _isOwnAppsDirectory; }
|
||||
void setIsOwnAppsDirectory(bool value) { _isOwnAppsDirectory = value; }
|
||||
|
@ -213,7 +230,7 @@ struct TRI_vocbase_t {
|
|||
/// @brief signal the cleanup thread to wake up
|
||||
void signalCleanup();
|
||||
|
||||
/// @brief increase the reference counter for a database.
|
||||
/// @brief increase the reference counter for a database.
|
||||
/// will return true if the refeence counter was increased, false otherwise
|
||||
/// in case false is returned, the database must not be used
|
||||
bool use();
|
||||
|
@ -222,7 +239,7 @@ struct TRI_vocbase_t {
|
|||
|
||||
/// @brief decrease the reference counter for a database
|
||||
void release();
|
||||
|
||||
|
||||
/// @brief returns whether the database is dangling
|
||||
bool isDangling() const;
|
||||
|
||||
|
@ -237,7 +254,7 @@ struct TRI_vocbase_t {
|
|||
|
||||
/// @brief closes a database and all collections
|
||||
void shutdown();
|
||||
|
||||
|
||||
/// @brief returns all known views
|
||||
std::vector<std::shared_ptr<arangodb::LogicalView>> views();
|
||||
|
||||
|
@ -256,7 +273,7 @@ struct TRI_vocbase_t {
|
|||
arangodb::LogicalCollection* lookupCollection(std::string const& name);
|
||||
/// @brief looks up a collection by identifier
|
||||
arangodb::LogicalCollection* lookupCollection(TRI_voc_cid_t id);
|
||||
|
||||
|
||||
/// @brief looks up a view by name
|
||||
std::shared_ptr<arangodb::LogicalView> lookupView(std::string const& name);
|
||||
/// @brief looks up a view by identifier
|
||||
|
@ -266,8 +283,9 @@ struct TRI_vocbase_t {
|
|||
/// and optionally indexes
|
||||
/// the result is sorted by type and name (vertices before edges)
|
||||
std::shared_ptr<arangodb::velocypack::Builder> inventory(
|
||||
TRI_voc_tick_t, bool (*)(arangodb::LogicalCollection*, void*), void*,
|
||||
bool, std::function<bool(arangodb::LogicalCollection*, arangodb::LogicalCollection*)>);
|
||||
TRI_voc_tick_t, bool (*)(arangodb::LogicalCollection*, void*), void*,
|
||||
bool, std::function<bool(arangodb::LogicalCollection*,
|
||||
arangodb::LogicalCollection*)>);
|
||||
|
||||
/// @brief renames a collection
|
||||
int renameCollection(arangodb::LogicalCollection* collection,
|
||||
|
@ -282,17 +300,25 @@ struct TRI_vocbase_t {
|
|||
arangodb::velocypack::Slice parameters, TRI_voc_cid_t cid);
|
||||
|
||||
/// @brief drops a collection
|
||||
int dropCollection(arangodb::LogicalCollection* collection, bool allowDropSystem);
|
||||
int dropCollection(arangodb::LogicalCollection* collection,
|
||||
bool allowDropSystem);
|
||||
|
||||
/// @brief callback for collection dropping
|
||||
static bool DropCollectionCallback(arangodb::LogicalCollection* collection);
|
||||
|
||||
/// @brief unloads a collection
|
||||
int unloadCollection(arangodb::LogicalCollection* collection, bool force);
|
||||
|
||||
|
||||
/// @brief callback for unloading a collection
|
||||
static bool UnloadCollectionCallback(arangodb::LogicalCollection* collection);
|
||||
|
||||
/// @brief adds a new view implementation
|
||||
void registerViewImplementation(std::string const& type,
|
||||
arangodb::ViewCreator creator);
|
||||
|
||||
/// @brief removes a view implementation
|
||||
bool unregisterViewImplementation(std::string const& type);
|
||||
|
||||
/// @brief creates a new view from parameter set
|
||||
/// view id is normally passed with a value of 0
|
||||
/// this means that the system will assign a new id automatically
|
||||
|
@ -308,19 +334,22 @@ struct TRI_vocbase_t {
|
|||
/// @brief locks a collection for usage, loading or manifesting it
|
||||
/// Note that this will READ lock the collection you have to release the
|
||||
/// collection lock by yourself.
|
||||
int useCollection(arangodb::LogicalCollection* collection, TRI_vocbase_col_status_e&);
|
||||
int useCollection(arangodb::LogicalCollection* collection,
|
||||
TRI_vocbase_col_status_e&);
|
||||
|
||||
/// @brief locks a collection for usage by id
|
||||
/// Note that this will READ lock the collection you have to release the
|
||||
/// collection lock by yourself and call @ref TRI_ReleaseCollectionVocBase
|
||||
/// when you are done with the collection.
|
||||
arangodb::LogicalCollection* useCollection(TRI_voc_cid_t cid, TRI_vocbase_col_status_e&);
|
||||
arangodb::LogicalCollection* useCollection(TRI_voc_cid_t cid,
|
||||
TRI_vocbase_col_status_e&);
|
||||
|
||||
/// @brief locks a collection for usage by name
|
||||
/// Note that this will READ lock the collection you have to release the
|
||||
/// collection lock by yourself and call @ref TRI_ReleaseCollectionVocBase
|
||||
/// when you are done with the collection.
|
||||
arangodb::LogicalCollection* useCollection(std::string const& name, TRI_vocbase_col_status_e&);
|
||||
arangodb::LogicalCollection* useCollection(std::string const& name,
|
||||
TRI_vocbase_col_status_e&);
|
||||
|
||||
/// @brief releases a collection from usage
|
||||
void releaseCollection(arangodb::LogicalCollection* collection);
|
||||
|
@ -330,8 +359,7 @@ struct TRI_vocbase_t {
|
|||
arangodb::LogicalCollection* lookupCollectionNoLock(std::string const& name);
|
||||
|
||||
int loadCollection(arangodb::LogicalCollection* collection,
|
||||
TRI_vocbase_col_status_e& status,
|
||||
bool setStatus = true);
|
||||
TRI_vocbase_col_status_e& status, bool setStatus = true);
|
||||
|
||||
/// @brief adds a new collection
|
||||
/// caller must hold _collectionsLock in write mode or set doLock
|
||||
|
@ -348,12 +376,11 @@ struct TRI_vocbase_t {
|
|||
/// @brief drops a collection, worker function
|
||||
int dropCollectionWorker(arangodb::LogicalCollection* collection,
|
||||
DropState& state);
|
||||
|
||||
|
||||
/// @brief creates a new view, worker function
|
||||
std::shared_ptr<arangodb::LogicalView> createViewWorker(
|
||||
arangodb::velocypack::Slice parameters, TRI_voc_cid_t& id);
|
||||
|
||||
|
||||
/// @brief adds a new view
|
||||
/// caller must hold _viewsLock in write mode or set doLock
|
||||
void registerView(bool doLock, std::shared_ptr<arangodb::LogicalView> view);
|
||||
|
@ -364,7 +391,7 @@ struct TRI_vocbase_t {
|
|||
};
|
||||
|
||||
// scope guard for a database
|
||||
// ensures that a database
|
||||
// ensures that a database
|
||||
class VocbaseGuard {
|
||||
public:
|
||||
VocbaseGuard() = delete;
|
||||
|
@ -386,7 +413,7 @@ class VocbaseGuard {
|
|||
|
||||
/// @brief extract the _rev attribute from a slice
|
||||
TRI_voc_rid_t TRI_ExtractRevisionId(VPackSlice const slice);
|
||||
|
||||
|
||||
/// @brief extract the _rev attribute from a slice as a slice
|
||||
VPackSlice TRI_ExtractRevisionIdAsSlice(VPackSlice const slice);
|
||||
|
||||
|
|
Loading…
Reference in New Issue