1
0
Fork 0

avoid calling cluster related functions while instantiating views on … (#7509)

* avoid calling cluster related functions while instantiating views on a db server

* minor cleanup
This commit is contained in:
Andrey Abramov 2018-11-29 15:43:53 +03:00 committed by GitHub
parent adc651e338
commit 6674a4282d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 43 additions and 152 deletions

View File

@ -1224,68 +1224,6 @@ std::shared_ptr<LogicalView> ClusterInfo::getView(
return nullptr;
}
std::shared_ptr<LogicalView> ClusterInfo::getViewCurrent(
DatabaseID const& databaseID,
ViewID const& viewID
) {
if (viewID.empty()) {
return nullptr;
}
static const auto lookupView = [](
AllViews const& dbs,
DatabaseID const& databaseID,
ViewID const& viewID
) noexcept -> std::shared_ptr<LogicalView> {
auto const db = dbs.find(databaseID); // look up database by id
if (db != dbs.end()) {
auto& views = db->second;
auto const itr = views.find(viewID); // look up view by id (or by name)
if (itr != views.end()) {
return itr->second;
}
}
return nullptr;
};
if (std::this_thread::get_id() == _planLoader) {
return lookupView(_plannedViews, databaseID, viewID);
}
size_t planReloads = 0;
if (!_planProt.isValid) {
loadPlan(); // current Views are actually in Plan instead of Current
++planReloads;
}
for(;;) {
{
READ_LOCKER(readLocker, _planProt.lock);
auto const view = lookupView(_plannedViews, databaseID, viewID);
if (view) {
return view;
}
}
if (planReloads >= 2) {
break;
}
loadPlan(); // current Views are actually in Plan instead of Current (must load plan outside the lock)
++planReloads;
}
LOG_TOPIC(INFO, Logger::CLUSTER)
<< "View not found: '" << viewID << "' in database '" << databaseID << "'";
return nullptr;
}
//////////////////////////////////////////////////////////////////////////////
/// @brief ask about all views of a database
//////////////////////////////////////////////////////////////////////////////

View File

@ -358,16 +358,6 @@ class ClusterInfo {
ViewID const& viewID
);
//////////////////////////////////////////////////////////////////////////////
/// @brief ask about a view in current.
/// If it is not found in the cache (and not currently loading plan), then the
/// cache is reloaded once.
//////////////////////////////////////////////////////////////////////////////
std::shared_ptr<LogicalView> getViewCurrent(
DatabaseID const& vocbase,
ViewID const& viewID
);
//////////////////////////////////////////////////////////////////////////////
/// @brief ask about all views of a database
//////////////////////////////////////////////////////////////////////////////

View File

@ -231,41 +231,21 @@ struct IResearchViewDBServer::ViewFactory: public arangodb::ViewFactory {
);
}
auto wiew = std::shared_ptr<IResearchViewDBServer>(
new IResearchViewDBServer(vocbase, definition, *feature, planVersion)
);
std::string error;
IResearchViewMeta meta;
auto meta = std::make_shared<AsyncMeta>();
if (!meta.init(definition, error)) {
if (!meta->init(definition, error)) {
return arangodb::Result(
TRI_ERROR_BAD_PARAMETER,
error.empty()
? (std::string("failed to initialize arangosearch View '") + wiew->name() + "' from definition: " + definition.toString())
: (std::string("failed to initialize arangosearch View '") + wiew->name() + "' from definition, error in attribute '" + error + "': " + definition.toString())
? (std::string("failed to initialize arangosearch View '") + static_cast<std::string>(name) + "' from definition: " + definition.toString())
: (std::string("failed to initialize arangosearch View '") + static_cast<std::string>(name) + "' from definition, error in attribute '" + error + "': " + definition.toString())
);
}
// search for the previous view instance and check if it's meta is the same
{
auto oldLogicalWiew =
ci->getViewCurrent(vocbase.name(), std::to_string(wiew->id()));
auto* oldWiew = arangodb::LogicalView::cast<IResearchViewDBServer>(
oldLogicalWiew.get()
);
if (oldWiew && *(oldWiew->_meta) == meta) {
wiew->_meta = oldWiew->_meta;
}
}
if (!(wiew->_meta)) {
wiew->_meta = std::make_shared<AsyncMeta>();
static_cast<IResearchViewMeta&>(*(wiew->_meta)) = std::move(meta);
}
view = wiew;
view = std::shared_ptr<IResearchViewDBServer>(
new IResearchViewDBServer(vocbase, definition, *feature, planVersion, std::move(meta))
);
return arangodb::Result();
}
@ -281,36 +261,6 @@ struct IResearchViewDBServer::ViewFactory: public arangodb::ViewFactory {
return arangodb::Result(); // resuse view from vocbase
}
auto* ci = ClusterInfo::instance();
std::shared_ptr<AsyncMeta> meta;
// reference meta from cluster-wide view if available to
// avoid memory and thread allocation
// if not availble then the meta will be reassigned when
// the per-cid instance is associated with the cluster-wide view
if (ci) {
auto planId = arangodb::basics::VelocyPackHelper::stringUInt64(
definition.get(arangodb::StaticStrings::DataSourcePlanId)
); // planId set in ensure(...)
auto wiewId = std::to_string(planId);
auto logicalWiew = ci->getView(vocbase.name(), wiewId); // here if creating per-cid view during loadPlan()
auto* wiew = arangodb::LogicalView::cast<IResearchViewDBServer>(
logicalWiew.get()
);
// if not found in 'Plan' then search in 'Current'
if (!wiew) {
logicalWiew = ci->getViewCurrent(vocbase.name(), wiewId); // here if creating per-cid view outisde of loadPlan()
wiew = arangodb::LogicalView::cast<IResearchViewDBServer>(
logicalWiew.get()
);
}
if (wiew) {
meta = wiew->_meta;
}
}
// no view for shard
arangodb::LogicalView::ptr impl;
auto res = IResearchView::factory().instantiate(
@ -328,29 +278,39 @@ struct IResearchViewDBServer::ViewFactory: public arangodb::ViewFactory {
);
}
if (meta) {
res = arangodb::LogicalView::cast<IResearchView>(*impl).updateProperties(meta);
if (!res.ok()) {
return res;
}
}
// a wrapper to remove the view from vocbase if it no longer has any links
// hold a reference to the original view in the deleter so that the view is
// still valid for the duration of the pointer wrapper
view = std::shared_ptr<arangodb::LogicalView>(
impl.get(),
[impl](arangodb::LogicalView*)->void {
static const auto visitor = [](TRI_voc_cid_t)->bool { return false; };
[impl] (arangodb::LogicalView*) noexcept -> void {
auto& vocbase = impl->vocbase();
// same view in vocbase and with no collections
if (impl.get() == vocbase.lookupView(impl->id()).get() // avoid double dropView(...)
&& impl->visitCollections(visitor)
&& !impl->drop().ok()) { // per-cid collections always system
LOG_TOPIC(WARN, arangodb::iresearch::TOPIC)
<< "failure to drop stale arangosearch View '" << impl->name() << "' while from database '" << vocbase.name() << "'";
// suppress any errors in destructor
try {
// same view in vocbase and with no collections
if (impl == vocbase.lookupView(impl->id()) // avoid double dropView(...)
&& impl->visitCollections([](TRI_voc_cid_t){ return false; })
&& !impl->drop().ok()) { // per-cid collections always system
LOG_TOPIC(WARN, arangodb::iresearch::TOPIC)
<< "failure to drop stale arangosearch View '" << impl->name() << "' while from database '" << vocbase.name() << "'";
}
} catch (basics::Exception const& e) {
LOG_TOPIC(ERR, arangodb::iresearch::TOPIC)
<< "caught exception while dropping stale arangosearch View '" << impl->name()
<< "' while from database '" << vocbase.name()
<< "', errorCode: '" << e.code()
<< "', error: '" << e.message();
} catch (std::exception const& e) {
LOG_TOPIC(ERR, arangodb::iresearch::TOPIC)
<< "caught exception while dropping stale arangosearch View '" << impl->name()
<< "' while from database '" << vocbase.name()
<< "', error: '" << e.what() << "'";
} catch (...) {
LOG_TOPIC(ERR, arangodb::iresearch::TOPIC)
<< "caught an unspecified exception while dropping stale arangosearch View '" << impl->name()
<< "' while from database '" << vocbase.name() << "'";
}
}
);
@ -362,12 +322,14 @@ struct IResearchViewDBServer::ViewFactory: public arangodb::ViewFactory {
IResearchViewDBServer::IResearchViewDBServer(
TRI_vocbase_t& vocbase,
arangodb::velocypack::Slice const& info,
arangodb::DatabasePathFeature const& dbPathFeature,
uint64_t planVersion
): LogicalViewClusterInfo(vocbase, info, planVersion) {
arangodb::DatabasePathFeature const& /*dbPathFeature*/,
uint64_t planVersion,
std::shared_ptr<AsyncMeta> meta /*=nullptr*/
) : LogicalViewClusterInfo(vocbase, info, planVersion),
_meta(std::move(meta)) {
}
IResearchViewDBServer::~IResearchViewDBServer() {
IResearchViewDBServer::~IResearchViewDBServer() noexcept {
_collections.clear(); // ensure view distructors called before mutex is deallocated
}
@ -821,4 +783,4 @@ bool IResearchViewDBServer::visitCollections(
// -----------------------------------------------------------------------------
// --SECTION-- END-OF-FILE
// -----------------------------------------------------------------------------
// -----------------------------------------------------------------------------

View File

@ -53,7 +53,7 @@ class AsyncMeta;
class IResearchViewDBServer final: public arangodb::LogicalViewClusterInfo {
public:
virtual ~IResearchViewDBServer();
virtual ~IResearchViewDBServer() noexcept;
using LogicalView::drop;
@ -122,7 +122,8 @@ class IResearchViewDBServer final: public arangodb::LogicalViewClusterInfo {
TRI_vocbase_t& vocbase,
arangodb::velocypack::Slice const& info,
arangodb::DatabasePathFeature const& dbPathFeature,
uint64_t planVersion
uint64_t planVersion,
std::shared_ptr<AsyncMeta> meta = nullptr
);
};