mirror of https://gitee.com/bigwinds/arangodb
code cleanup
This commit is contained in:
parent
eaa91592e5
commit
65ea2bfbb9
|
@ -170,8 +170,7 @@ int IResearchLink::drop() {
|
|||
|
||||
// if the collection is in the process of being removed then drop it from the view
|
||||
if (_collection->deleted()) {
|
||||
auto result =
|
||||
_view->updateLogicalProperties(emptyObjectSlice(), true, false); // revalidate all links
|
||||
auto result = _view->updateProperties(emptyObjectSlice(), true, false); // revalidate all links
|
||||
|
||||
if (!result.ok()) {
|
||||
LOG_TOPIC(WARN, iresearch::IResearchFeature::IRESEARCH)
|
||||
|
|
|
@ -765,10 +765,11 @@ IResearchView::PersistedStore::PersistedStore(irs::utf8_path&& path)
|
|||
}
|
||||
|
||||
IResearchView::IResearchView(
|
||||
TRI_vocbase_t* vocbase,
|
||||
arangodb::velocypack::Slice const& info,
|
||||
irs::utf8_path&& persistedPath
|
||||
) : DBServerLogicalView(vocbase, info),
|
||||
TRI_vocbase_t* vocbase,
|
||||
arangodb::velocypack::Slice const& info,
|
||||
irs::utf8_path&& persistedPath,
|
||||
bool isNew
|
||||
) : DBServerLogicalView(vocbase, info, isNew),
|
||||
FlushTransaction(toString(*this)),
|
||||
_asyncMetaRevision(1),
|
||||
_asyncSelf(irs::memory::make_unique<AsyncSelf>(this)),
|
||||
|
@ -1038,8 +1039,103 @@ void IResearchView::apply(arangodb::TransactionState& state) {
|
|||
}
|
||||
|
||||
void IResearchView::drop() {
|
||||
dropImpl();
|
||||
DBServerLogicalView::drop();
|
||||
std::unordered_set<TRI_voc_cid_t> collections;
|
||||
|
||||
// drop all known links
|
||||
if (vocbase()) {
|
||||
arangodb::velocypack::Builder builder;
|
||||
|
||||
{
|
||||
ReadMutex mutex(_mutex);
|
||||
SCOPED_LOCK(mutex); // '_meta' and '_trackedCids' can be asynchronously updated
|
||||
|
||||
builder.openObject();
|
||||
|
||||
if (!appendLinkRemoval(builder, _meta)) {
|
||||
throw std::runtime_error(std::string("failed to construct link removal directive while removing iResearch view '") + std::to_string(id()) + "'");
|
||||
}
|
||||
|
||||
builder.close();
|
||||
}
|
||||
|
||||
if (!updateLinks(collections, *(vocbase()), *this, builder.slice()).ok()) {
|
||||
throw std::runtime_error(std::string("failed to remove links while removing iResearch view '") + std::to_string(id()) + "'");
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
WriteMutex mutex(_asyncSelf->_mutex);
|
||||
SCOPED_LOCK(mutex); // wait for all the view users to finish
|
||||
_asyncSelf->_value.store(nullptr); // the view data-stores are being deallocated, view use is no longer valid
|
||||
}
|
||||
|
||||
_asyncTerminate.store(true); // mark long-running async jobs for terminatation
|
||||
|
||||
{
|
||||
SCOPED_LOCK(_asyncMutex);
|
||||
_asyncCondition.notify_all(); // trigger reload of settings for async jobs
|
||||
}
|
||||
|
||||
_threadPool.stop();
|
||||
|
||||
WriteMutex mutex(_mutex); // members can be asynchronously updated
|
||||
SCOPED_LOCK(mutex);
|
||||
|
||||
collections.insert(_meta._collections.begin(), _meta._collections.end());
|
||||
|
||||
if (vocbase()) {
|
||||
validateLinks(collections, *(vocbase()), *this);
|
||||
}
|
||||
|
||||
// ArangoDB global consistency check, no known dangling links
|
||||
if (!collections.empty()) {
|
||||
throw std::runtime_error(std::string("links still present while removing iResearch view '") + std::to_string(id()) + "'");
|
||||
}
|
||||
|
||||
// ...........................................................................
|
||||
// if an exception occurs below than a drop retry would most likely happen
|
||||
// ...........................................................................
|
||||
try {
|
||||
_storeByTid.clear();
|
||||
|
||||
for (size_t i = 0, count = IRESEARCH_COUNTOF(_memoryNodes); i < count; ++i) {
|
||||
auto& memoryStore = _memoryNodes[i]._store;
|
||||
|
||||
memoryStore._writer->close();
|
||||
memoryStore._writer.reset();
|
||||
memoryStore._directory->close();
|
||||
memoryStore._directory.reset();
|
||||
}
|
||||
|
||||
if (_storePersisted) {
|
||||
_storePersisted._writer->close();
|
||||
_storePersisted._writer.reset();
|
||||
_storePersisted._directory->close();
|
||||
_storePersisted._directory.reset();
|
||||
}
|
||||
|
||||
bool exists;
|
||||
|
||||
// remove persisted data store directory if present
|
||||
if (_storePersisted._path.exists_directory(exists)
|
||||
&& (!exists || _storePersisted._path.remove())) {
|
||||
DBServerLogicalView::drop();
|
||||
deleted(true);
|
||||
return; // success
|
||||
}
|
||||
} catch (std::exception const& e) {
|
||||
LOG_TOPIC(WARN, iresearch::IResearchFeature::IRESEARCH)
|
||||
<< "caught exception while removing iResearch view '" << id() << "': " << e.what();
|
||||
IR_LOG_EXCEPTION();
|
||||
throw;
|
||||
} catch (...) {
|
||||
LOG_TOPIC(WARN, iresearch::IResearchFeature::IRESEARCH)
|
||||
<< "caught exception while removing iResearch view '" << id() << "'";
|
||||
IR_LOG_EXCEPTION();
|
||||
throw;
|
||||
}
|
||||
|
||||
throw std::runtime_error(std::string("failed to remove iResearch view '") + arangodb::basics::StringUtils::itoa(id()) + "'");
|
||||
}
|
||||
|
||||
int IResearchView::drop(TRI_voc_cid_t cid) {
|
||||
|
@ -1199,271 +1295,6 @@ arangodb::Result IResearchView::commit() {
|
|||
return {TRI_ERROR_INTERNAL};
|
||||
}
|
||||
|
||||
void IResearchView::dropImpl() {
|
||||
deleted(true);
|
||||
|
||||
std::unordered_set<TRI_voc_cid_t> collections;
|
||||
|
||||
// drop all known links
|
||||
if (vocbase()) {
|
||||
arangodb::velocypack::Builder builder;
|
||||
|
||||
{
|
||||
ReadMutex mutex(_mutex);
|
||||
SCOPED_LOCK(mutex); // '_meta' and '_trackedCids' can be asynchronously updated
|
||||
|
||||
builder.openObject();
|
||||
|
||||
if (!appendLinkRemoval(builder, _meta)) {
|
||||
throw std::runtime_error(std::string("failed to construct link removal directive while removing iResearch view '") + std::to_string(id()) + "'");
|
||||
}
|
||||
|
||||
builder.close();
|
||||
}
|
||||
|
||||
if (!updateLinks(collections, *(vocbase()), *this, builder.slice()).ok()) {
|
||||
throw std::runtime_error(std::string("failed to remove links while removing iResearch view '") + std::to_string(id()) + "'");
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
WriteMutex mutex(_asyncSelf->_mutex);
|
||||
SCOPED_LOCK(mutex); // wait for all the view users to finish
|
||||
_asyncSelf->_value.store(nullptr); // the view data-stores are being deallocated, view use is no longer valid
|
||||
}
|
||||
|
||||
_asyncTerminate.store(true); // mark long-running async jobs for terminatation
|
||||
|
||||
{
|
||||
SCOPED_LOCK(_asyncMutex);
|
||||
_asyncCondition.notify_all(); // trigger reload of settings for async jobs
|
||||
}
|
||||
|
||||
_threadPool.stop();
|
||||
|
||||
WriteMutex mutex(_mutex); // members can be asynchronously updated
|
||||
SCOPED_LOCK(mutex);
|
||||
|
||||
collections.insert(_meta._collections.begin(), _meta._collections.end());
|
||||
|
||||
if (vocbase()) {
|
||||
validateLinks(collections, *(vocbase()), *this);
|
||||
}
|
||||
|
||||
// ArangoDB global consistency check, no known dangling links
|
||||
if (!collections.empty()) {
|
||||
throw std::runtime_error(std::string("links still present while removing iResearch view '") + std::to_string(id()) + "'");
|
||||
}
|
||||
|
||||
// ...........................................................................
|
||||
// if an exception occurs below than a drop retry would most likely happen
|
||||
// ...........................................................................
|
||||
try {
|
||||
_storeByTid.clear();
|
||||
|
||||
for (size_t i = 0, count = IRESEARCH_COUNTOF(_memoryNodes); i < count; ++i) {
|
||||
auto& memoryStore = _memoryNodes[i]._store;
|
||||
|
||||
memoryStore._writer->close();
|
||||
memoryStore._writer.reset();
|
||||
memoryStore._directory->close();
|
||||
memoryStore._directory.reset();
|
||||
}
|
||||
|
||||
if (_storePersisted) {
|
||||
_storePersisted._writer->close();
|
||||
_storePersisted._writer.reset();
|
||||
_storePersisted._directory->close();
|
||||
_storePersisted._directory.reset();
|
||||
}
|
||||
|
||||
bool exists;
|
||||
|
||||
// remove persisted data store directory if present
|
||||
if (_storePersisted._path.exists_directory(exists)
|
||||
&& (!exists || _storePersisted._path.remove())) {
|
||||
return; // success
|
||||
}
|
||||
} catch (std::exception const& e) {
|
||||
LOG_TOPIC(WARN, iresearch::IResearchFeature::IRESEARCH)
|
||||
<< "caught exception while removing iResearch view '" << id() << "': " << e.what();
|
||||
IR_LOG_EXCEPTION();
|
||||
throw;
|
||||
} catch (...) {
|
||||
LOG_TOPIC(WARN, iresearch::IResearchFeature::IRESEARCH)
|
||||
<< "caught exception while removing iResearch view '" << id() << "'";
|
||||
IR_LOG_EXCEPTION();
|
||||
throw;
|
||||
}
|
||||
|
||||
throw std::runtime_error(std::string("failed to remove iResearch view '") + arangodb::basics::StringUtils::itoa(id()) + "'");
|
||||
}
|
||||
|
||||
arangodb::Result IResearchView::updatePropertiesImpl(
|
||||
const velocypack::Slice &slice,
|
||||
bool partialUpdate,
|
||||
bool doSync
|
||||
) {
|
||||
auto* vocbase = this->vocbase();
|
||||
|
||||
if (!vocbase) {
|
||||
return arangodb::Result(
|
||||
TRI_ERROR_INTERNAL,
|
||||
std::string("failed to find vocbase while updating links for iResearch view '") + std::to_string(id()) + "'"
|
||||
);
|
||||
}
|
||||
|
||||
std::string error;
|
||||
IResearchViewMeta meta;
|
||||
IResearchViewMeta::Mask mask;
|
||||
WriteMutex mutex(_mutex); // '_meta' can be asynchronously read
|
||||
arangodb::Result res = arangodb::Result(/*TRI_ERROR_NO_ERROR*/);
|
||||
|
||||
{
|
||||
SCOPED_LOCK(mutex);
|
||||
|
||||
arangodb::velocypack::Builder originalMetaJson; // required for reverting links on failure
|
||||
|
||||
if (!_meta.json(arangodb::velocypack::ObjectBuilder(&originalMetaJson))) {
|
||||
return arangodb::Result(
|
||||
TRI_ERROR_INTERNAL,
|
||||
std::string("failed to generate json definition while updating iResearch view '") + std::to_string(id()) + "'"
|
||||
);
|
||||
}
|
||||
|
||||
auto& initialMeta = partialUpdate ? _meta : IResearchViewMeta::DEFAULT();
|
||||
|
||||
if (!meta.init(slice, error, initialMeta, &mask)) {
|
||||
return arangodb::Result(TRI_ERROR_BAD_PARAMETER, std::move(error));
|
||||
}
|
||||
|
||||
// FIXME TODO remove once View::updateProperties(...) will be fixed to write
|
||||
// the update delta into the WAL marker instead of the full persisted state
|
||||
// below is a very dangerous hack as it allows multiple links from the same
|
||||
// collection to point to the same view, thus breaking view data consistency
|
||||
{
|
||||
auto* engine = arangodb::EngineSelectorFeature::ENGINE;
|
||||
|
||||
if (engine && engine->inRecovery()) {
|
||||
arangodb::velocypack::Builder linksBuilder;
|
||||
|
||||
linksBuilder.openObject();
|
||||
|
||||
// remove links no longer present in incming update
|
||||
for (auto& cid: _meta._collections) {
|
||||
if (meta._collections.find(cid) == meta._collections.end()) {
|
||||
linksBuilder.add(
|
||||
std::to_string(cid),
|
||||
arangodb::velocypack::Value(arangodb::velocypack::ValueType::Null)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
for (auto& cid: meta._collections) {
|
||||
auto collection = vocbase->lookupCollection(cid);
|
||||
|
||||
if (collection) {
|
||||
_meta._collections.emplace(cid);
|
||||
|
||||
for (auto& index: collection->getIndexes()) {
|
||||
if (index && arangodb::Index::TRI_IDX_TYPE_IRESEARCH_LINK == index->type()) {
|
||||
auto* link = dynamic_cast<arangodb::iresearch::IResearchLink*>(index.get());
|
||||
|
||||
if (link && link->_defaultId == id() && !link->view()) {
|
||||
arangodb::velocypack::Builder linkBuilder;
|
||||
bool valid;
|
||||
|
||||
linkBuilder.openObject();
|
||||
valid = link->json(linkBuilder, true);
|
||||
linkBuilder.close();
|
||||
|
||||
linksBuilder.add(
|
||||
std::to_string(cid),
|
||||
arangodb::velocypack::Value(arangodb::velocypack::ValueType::Null)
|
||||
);
|
||||
|
||||
if (valid) {
|
||||
linksBuilder.add(std::to_string(cid), linkBuilder.slice());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::unordered_set<TRI_voc_cid_t> collections;
|
||||
|
||||
linksBuilder.close();
|
||||
updateLinks(collections, *vocbase, *this, linksBuilder.slice());
|
||||
collections.insert(_meta._collections.begin(), _meta._collections.end());
|
||||
validateLinks(collections, *vocbase, *this); // remove invalid cids (no such collection or no such link)
|
||||
_meta._collections = std::move(collections);
|
||||
}
|
||||
}
|
||||
|
||||
// reset non-updatable values to match current meta
|
||||
meta._collections = _meta._collections;
|
||||
|
||||
if (mask._threadsMaxIdle) {
|
||||
_threadPool.max_idle(meta._threadsMaxIdle);
|
||||
}
|
||||
|
||||
if (mask._threadsMaxTotal) {
|
||||
_threadPool.max_threads(meta._threadsMaxTotal);
|
||||
}
|
||||
|
||||
{
|
||||
SCOPED_LOCK(_asyncMutex);
|
||||
_asyncCondition.notify_all(); // trigger reload of timeout settings for async jobs
|
||||
}
|
||||
|
||||
_meta = std::move(meta);
|
||||
}
|
||||
|
||||
std::unordered_set<TRI_voc_cid_t> collections;
|
||||
|
||||
// update links if requested (on a best-effort basis)
|
||||
// indexing of collections is done in different threads so no locks can be held and rollback is not possible
|
||||
// as a result it's also possible for links to be simultaneously modified via a different callflow (e.g. from collections)
|
||||
if (slice.hasKey(LINKS_FIELD)) {
|
||||
if (partialUpdate) {
|
||||
res = updateLinks(collections, *vocbase, *this, slice.get(LINKS_FIELD));
|
||||
} else {
|
||||
arangodb::velocypack::Builder builder;
|
||||
|
||||
builder.openObject();
|
||||
|
||||
if (!appendLinkRemoval(builder, _meta)
|
||||
|| !mergeSlice(builder, slice.get(LINKS_FIELD))) {
|
||||
return arangodb::Result(
|
||||
TRI_ERROR_INTERNAL,
|
||||
std::string("failed to construct link update directive while updating iResearch view '") + std::to_string(id()) + "'"
|
||||
);
|
||||
}
|
||||
|
||||
builder.close();
|
||||
res = updateLinks(collections, *vocbase, *this, builder.slice());
|
||||
}
|
||||
}
|
||||
|
||||
// ...........................................................................
|
||||
// if an exception occurs below then it would only affect collection linking
|
||||
// consistency and an update retry would most likely happen
|
||||
// always re-validate '_collections' because may have had externally triggered
|
||||
// collection/link drops
|
||||
// ...........................................................................
|
||||
{
|
||||
SCOPED_LOCK(mutex); // '_meta' can be asynchronously read
|
||||
collections.insert(_meta._collections.begin(), _meta._collections.end());
|
||||
validateLinks(collections, *vocbase, *this); // remove invalid cids (no such collection or no such link)
|
||||
_meta._collections = std::move(collections);
|
||||
}
|
||||
|
||||
// FIXME TODO to ensure valid recovery remove the original datapath only if the entire, but under lock to prevent double rename
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
void IResearchView::getPropertiesVPack(
|
||||
arangodb::velocypack::Builder& builder, bool forPersistence
|
||||
) const {
|
||||
|
@ -1757,9 +1588,9 @@ arangodb::Result IResearchView::link(
|
|||
}
|
||||
|
||||
/*static*/ std::shared_ptr<LogicalView> IResearchView::make(
|
||||
TRI_vocbase_t& vocbase,
|
||||
arangodb::velocypack::Slice const& info,
|
||||
bool isNew
|
||||
TRI_vocbase_t& vocbase,
|
||||
arangodb::velocypack::Slice const& info,
|
||||
bool isNew
|
||||
) {
|
||||
auto const id = readViewId(info);
|
||||
|
||||
|
@ -1793,8 +1624,8 @@ arangodb::Result IResearchView::link(
|
|||
dataPath += "-";
|
||||
dataPath += std::to_string(id);
|
||||
|
||||
auto ptr = std::unique_ptr<IResearchView>(
|
||||
new IResearchView(&vocbase, info, std::move(dataPath))
|
||||
auto view = std::unique_ptr<IResearchView>(
|
||||
new IResearchView(&vocbase, info, std::move(dataPath), isNew)
|
||||
);
|
||||
|
||||
auto props = info.get("properties");
|
||||
|
@ -1806,14 +1637,14 @@ arangodb::Result IResearchView::link(
|
|||
|
||||
std::string error;
|
||||
|
||||
if (!ptr->_meta.init(props, error)) {
|
||||
if (!view->_meta.init(props, error)) {
|
||||
LOG_TOPIC(WARN, iresearch::IResearchFeature::IRESEARCH)
|
||||
<< "failed to initialize iResearch view from definition, error: " << error;
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return std::shared_ptr<IResearchView>(std::move(ptr));
|
||||
return std::shared_ptr<IResearchView>(std::move(view));
|
||||
}
|
||||
|
||||
size_t IResearchView::memory() const {
|
||||
|
@ -1845,6 +1676,8 @@ size_t IResearchView::memory() const {
|
|||
}
|
||||
|
||||
void IResearchView::open() {
|
||||
DBServerLogicalView::open();
|
||||
|
||||
auto* engine = arangodb::EngineSelectorFeature::ENGINE;
|
||||
|
||||
if (engine) {
|
||||
|
@ -2121,15 +1954,6 @@ bool IResearchView::sync(size_t maxMsec /*= 0*/) {
|
|||
return type;
|
||||
}
|
||||
|
||||
arangodb::Result IResearchView::updateLogicalProperties(
|
||||
arangodb::velocypack::Slice const& slice,
|
||||
bool partialUpdate,
|
||||
bool doSync
|
||||
) {
|
||||
// FIXME remove
|
||||
return updateProperties(slice, partialUpdate, doSync);
|
||||
}
|
||||
|
||||
void IResearchView::toVelocyPack(
|
||||
velocypack::Builder& result,
|
||||
bool includeProperties,
|
||||
|
@ -2157,14 +1981,168 @@ void IResearchView::toVelocyPack(
|
|||
}
|
||||
|
||||
arangodb::Result IResearchView::updateProperties(
|
||||
arangodb::velocypack::Slice const& slice,
|
||||
bool partialUpdate,
|
||||
bool doSync
|
||||
const velocypack::Slice &slice,
|
||||
bool partialUpdate,
|
||||
bool doSync
|
||||
) {
|
||||
WRITE_LOCKER(writeLocker, _infoLock);
|
||||
|
||||
// the implementation may filter/change/react to the changes
|
||||
auto res = updatePropertiesImpl(slice, partialUpdate, doSync);
|
||||
auto* vocbase = this->vocbase();
|
||||
|
||||
if (!vocbase) {
|
||||
return arangodb::Result(
|
||||
TRI_ERROR_INTERNAL,
|
||||
std::string("failed to find vocbase while updating links for iResearch view '") + std::to_string(id()) + "'"
|
||||
);
|
||||
}
|
||||
|
||||
std::string error;
|
||||
IResearchViewMeta meta;
|
||||
IResearchViewMeta::Mask mask;
|
||||
WriteMutex mutex(_mutex); // '_meta' can be asynchronously read
|
||||
arangodb::Result res;
|
||||
|
||||
{
|
||||
SCOPED_LOCK(mutex);
|
||||
|
||||
arangodb::velocypack::Builder originalMetaJson; // required for reverting links on failure
|
||||
|
||||
if (!_meta.json(arangodb::velocypack::ObjectBuilder(&originalMetaJson))) {
|
||||
return arangodb::Result(
|
||||
TRI_ERROR_INTERNAL,
|
||||
std::string("failed to generate json definition while updating iResearch view '") + std::to_string(id()) + "'"
|
||||
);
|
||||
}
|
||||
|
||||
auto& initialMeta = partialUpdate ? _meta : IResearchViewMeta::DEFAULT();
|
||||
|
||||
if (!meta.init(slice, error, initialMeta, &mask)) {
|
||||
return arangodb::Result(TRI_ERROR_BAD_PARAMETER, std::move(error));
|
||||
}
|
||||
|
||||
// FIXME TODO remove once View::updateProperties(...) will be fixed to write
|
||||
// the update delta into the WAL marker instead of the full persisted state
|
||||
// below is a very dangerous hack as it allows multiple links from the same
|
||||
// collection to point to the same view, thus breaking view data consistency
|
||||
{
|
||||
auto* engine = arangodb::EngineSelectorFeature::ENGINE;
|
||||
|
||||
if (engine && engine->inRecovery()) {
|
||||
arangodb::velocypack::Builder linksBuilder;
|
||||
|
||||
linksBuilder.openObject();
|
||||
|
||||
// remove links no longer present in incming update
|
||||
for (auto& cid: _meta._collections) {
|
||||
if (meta._collections.find(cid) == meta._collections.end()) {
|
||||
linksBuilder.add(
|
||||
std::to_string(cid),
|
||||
arangodb::velocypack::Value(arangodb::velocypack::ValueType::Null)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
for (auto& cid: meta._collections) {
|
||||
auto collection = vocbase->lookupCollection(cid);
|
||||
|
||||
if (collection) {
|
||||
_meta._collections.emplace(cid);
|
||||
|
||||
for (auto& index: collection->getIndexes()) {
|
||||
if (index && arangodb::Index::TRI_IDX_TYPE_IRESEARCH_LINK == index->type()) {
|
||||
auto* link = dynamic_cast<arangodb::iresearch::IResearchLink*>(index.get());
|
||||
|
||||
if (link && link->_defaultId == id() && !link->view()) {
|
||||
arangodb::velocypack::Builder linkBuilder;
|
||||
bool valid;
|
||||
|
||||
linkBuilder.openObject();
|
||||
valid = link->json(linkBuilder, true);
|
||||
linkBuilder.close();
|
||||
|
||||
linksBuilder.add(
|
||||
std::to_string(cid),
|
||||
arangodb::velocypack::Value(arangodb::velocypack::ValueType::Null)
|
||||
);
|
||||
|
||||
if (valid) {
|
||||
linksBuilder.add(std::to_string(cid), linkBuilder.slice());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::unordered_set<TRI_voc_cid_t> collections;
|
||||
|
||||
linksBuilder.close();
|
||||
updateLinks(collections, *vocbase, *this, linksBuilder.slice());
|
||||
collections.insert(_meta._collections.begin(), _meta._collections.end());
|
||||
validateLinks(collections, *vocbase, *this); // remove invalid cids (no such collection or no such link)
|
||||
_meta._collections = std::move(collections);
|
||||
}
|
||||
}
|
||||
|
||||
// reset non-updatable values to match current meta
|
||||
meta._collections = _meta._collections;
|
||||
|
||||
if (mask._threadsMaxIdle) {
|
||||
_threadPool.max_idle(meta._threadsMaxIdle);
|
||||
}
|
||||
|
||||
if (mask._threadsMaxTotal) {
|
||||
_threadPool.max_threads(meta._threadsMaxTotal);
|
||||
}
|
||||
|
||||
{
|
||||
SCOPED_LOCK(_asyncMutex);
|
||||
_asyncCondition.notify_all(); // trigger reload of timeout settings for async jobs
|
||||
}
|
||||
|
||||
_meta = std::move(meta);
|
||||
}
|
||||
|
||||
std::unordered_set<TRI_voc_cid_t> collections;
|
||||
|
||||
// update links if requested (on a best-effort basis)
|
||||
// indexing of collections is done in different threads so no locks can be held and rollback is not possible
|
||||
// as a result it's also possible for links to be simultaneously modified via a different callflow (e.g. from collections)
|
||||
if (slice.hasKey(LINKS_FIELD)) {
|
||||
if (partialUpdate) {
|
||||
res = updateLinks(collections, *vocbase, *this, slice.get(LINKS_FIELD));
|
||||
} else {
|
||||
arangodb::velocypack::Builder builder;
|
||||
|
||||
builder.openObject();
|
||||
|
||||
if (!appendLinkRemoval(builder, _meta)
|
||||
|| !mergeSlice(builder, slice.get(LINKS_FIELD))) {
|
||||
return arangodb::Result(
|
||||
TRI_ERROR_INTERNAL,
|
||||
std::string("failed to construct link update directive while updating iResearch view '") + std::to_string(id()) + "'"
|
||||
);
|
||||
}
|
||||
|
||||
builder.close();
|
||||
res = updateLinks(collections, *vocbase, *this, builder.slice());
|
||||
}
|
||||
}
|
||||
|
||||
// ...........................................................................
|
||||
// if an exception occurs below then it would only affect collection linking
|
||||
// consistency and an update retry would most likely happen
|
||||
// always re-validate '_collections' because may have had externally triggered
|
||||
// collection/link drops
|
||||
// ...........................................................................
|
||||
{
|
||||
SCOPED_LOCK(mutex); // '_meta' can be asynchronously read
|
||||
collections.insert(_meta._collections.begin(), _meta._collections.end());
|
||||
validateLinks(collections, *vocbase, *this); // remove invalid cids (no such collection or no such link)
|
||||
_meta._collections = std::move(collections);
|
||||
}
|
||||
|
||||
// FIXME TODO to ensure valid recovery remove the original datapath only if the entire, but under lock to prevent double rename
|
||||
|
||||
if (res.ok()) {
|
||||
res = DBServerLogicalView::updateProperties(slice, partialUpdate, doSync);
|
||||
|
|
|
@ -246,16 +246,6 @@ class IResearchView final: public arangodb::DBServerLogicalView,
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
static arangodb::LogicalDataSource::Type const& type() noexcept;
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief update the view properties via the LogicalView allowing for tracking
|
||||
/// update via WAL entries
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
arangodb::Result updateLogicalProperties(
|
||||
arangodb::velocypack::Slice const& slice,
|
||||
bool partialUpdate,
|
||||
bool doSync
|
||||
);
|
||||
|
||||
void toVelocyPack(
|
||||
velocypack::Builder& result,
|
||||
bool includeProperties,
|
||||
|
@ -327,15 +317,8 @@ class IResearchView final: public arangodb::DBServerLogicalView,
|
|||
IResearchView(
|
||||
TRI_vocbase_t* vocbase,
|
||||
arangodb::velocypack::Slice const& info,
|
||||
irs::utf8_path&& persistedPath
|
||||
);
|
||||
|
||||
// FIXME remove
|
||||
void dropImpl();
|
||||
arangodb::Result updatePropertiesImpl(
|
||||
arangodb::velocypack::Slice const& slice,
|
||||
bool partialUpdate,
|
||||
bool doSync
|
||||
irs::utf8_path&& persistedPath,
|
||||
bool isNew
|
||||
);
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
@ -115,26 +115,16 @@ LogicalView::LogicalView(TRI_vocbase_t* vocbase, VPackSlice const& info)
|
|||
TRI_UpdateTickServer(static_cast<TRI_voc_tick_t>(id()));
|
||||
}
|
||||
|
||||
/// @brief Persist the connected physical view
|
||||
/// This should be called AFTER the view is successfully
|
||||
/// created and only on Single/DBServer
|
||||
void LogicalView::persistPhysicalView() {
|
||||
// Coordinators are not allowed to have local views!
|
||||
TRI_ASSERT(!ServerState::instance()->isCoordinator());
|
||||
|
||||
// We have not yet persisted this view
|
||||
StorageEngine* engine = EngineSelectorFeature::ENGINE;
|
||||
engine->createView(vocbase(), id(), this);
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- DBServerLogicalView
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
DBServerLogicalView::DBServerLogicalView(
|
||||
TRI_vocbase_t* vocbase,
|
||||
VPackSlice const& info
|
||||
) : LogicalView(vocbase, info) {
|
||||
VPackSlice const& info,
|
||||
bool isNew
|
||||
) : LogicalView(vocbase, info),
|
||||
_isNew(isNew) {
|
||||
}
|
||||
|
||||
DBServerLogicalView::~DBServerLogicalView() {
|
||||
|
@ -145,6 +135,20 @@ DBServerLogicalView::~DBServerLogicalView() {
|
|||
}
|
||||
}
|
||||
|
||||
void DBServerLogicalView::open() {
|
||||
// Coordinators are not allowed to have local views!
|
||||
TRI_ASSERT(!ServerState::instance()->isCoordinator());
|
||||
|
||||
if (!_isNew) {
|
||||
return;
|
||||
}
|
||||
|
||||
StorageEngine* engine = EngineSelectorFeature::ENGINE;
|
||||
TRI_ASSERT(engine);
|
||||
engine->createView(vocbase(), id(), this);
|
||||
_isNew = false;
|
||||
}
|
||||
|
||||
void DBServerLogicalView::drop() {
|
||||
TRI_ASSERT(!ServerState::instance()->isCoordinator());
|
||||
StorageEngine* engine = EngineSelectorFeature::ENGINE;
|
||||
|
|
|
@ -93,12 +93,6 @@ class LogicalView : public LogicalDataSource {
|
|||
bool doSync
|
||||
) = 0;
|
||||
|
||||
//FIXME remove
|
||||
/// @brief Persist the connected physical view.
|
||||
/// This should be called AFTER the view is successfully
|
||||
/// created and only on Sinlge/DBServer
|
||||
void persistPhysicalView();
|
||||
|
||||
protected:
|
||||
static TRI_voc_cid_t readViewId(velocypack::Slice slice);
|
||||
|
||||
|
@ -132,6 +126,8 @@ class DBServerLogicalView : public LogicalView {
|
|||
public:
|
||||
~DBServerLogicalView() override;
|
||||
|
||||
void open() override;
|
||||
|
||||
void drop() override;
|
||||
|
||||
Result rename(
|
||||
|
@ -152,7 +148,14 @@ class DBServerLogicalView : public LogicalView {
|
|||
) override;
|
||||
|
||||
protected:
|
||||
DBServerLogicalView(TRI_vocbase_t* vocbase, velocypack::Slice const& definition);
|
||||
DBServerLogicalView(
|
||||
TRI_vocbase_t* vocbase,
|
||||
velocypack::Slice const& definition,
|
||||
bool isNew
|
||||
);
|
||||
|
||||
private:
|
||||
bool _isNew;
|
||||
}; // LogicalView
|
||||
|
||||
} // namespace arangodb
|
||||
|
|
|
@ -314,10 +314,12 @@ bool TRI_vocbase_t::unregisterCollection(
|
|||
auto itr = _dataSourceById.find(collection->id());
|
||||
|
||||
if (itr == _dataSourceById.end()
|
||||
|| !std::dynamic_pointer_cast<arangodb::LogicalCollection>(itr->second)) {
|
||||
|| itr->second->category() != LogicalCollection::category()) {
|
||||
return true; // no such collection
|
||||
}
|
||||
|
||||
TRI_ASSERT(std::dynamic_pointer_cast<arangodb::LogicalCollection>(itr->second));
|
||||
|
||||
// only if we find the collection by its id, we can delete it by name
|
||||
_dataSourceById.erase(itr);
|
||||
|
||||
|
@ -391,10 +393,12 @@ bool TRI_vocbase_t::unregisterView(
|
|||
auto itr = _dataSourceById.find(view->id());
|
||||
|
||||
if (itr == _dataSourceById.end()
|
||||
|| !std::dynamic_pointer_cast<arangodb::LogicalView>(itr->second)) {
|
||||
|| itr->second->category() != arangodb::LogicalView::category()) {
|
||||
return true; // no such view
|
||||
}
|
||||
|
||||
TRI_ASSERT(std::dynamic_pointer_cast<arangodb::LogicalView>(itr->second));
|
||||
|
||||
// only if we find the collection by its id, we can delete it by name
|
||||
_dataSourceById.erase(itr);
|
||||
|
||||
|
@ -1590,8 +1594,6 @@ std::shared_ptr<arangodb::LogicalView> TRI_vocbase_t::createViewWorker(
|
|||
);
|
||||
}
|
||||
|
||||
// FIXME first check for existence???
|
||||
|
||||
// Try to create a new view. This is not registered yet
|
||||
auto view = viewFactory(*this, parameters, true);
|
||||
|
||||
|
@ -1609,27 +1611,26 @@ std::shared_ptr<arangodb::LogicalView> TRI_vocbase_t::createViewWorker(
|
|||
|
||||
if (it != _dataSourceByName.end()) {
|
||||
events::CreateView(name, TRI_ERROR_ARANGO_DUPLICATE_NAME);
|
||||
|
||||
THROW_ARANGO_EXCEPTION(TRI_ERROR_ARANGO_DUPLICATE_NAME);
|
||||
}
|
||||
|
||||
registerView(basics::ConditionalLocking::DoNotLock, view);
|
||||
|
||||
try {
|
||||
// id might have been assigned
|
||||
id = view->id();
|
||||
|
||||
// Let's try to persist it.
|
||||
view->persistPhysicalView();
|
||||
|
||||
// And lets open it.
|
||||
view->open();
|
||||
|
||||
events::CreateView(name, TRI_ERROR_NO_ERROR);
|
||||
return view;
|
||||
} catch (...) {
|
||||
unregisterView(view);
|
||||
throw;
|
||||
}
|
||||
|
||||
// noexcept below
|
||||
id = view->id();
|
||||
|
||||
return view;
|
||||
}
|
||||
|
||||
/// @brief creates a new view from parameter set
|
||||
|
|
Loading…
Reference in New Issue