mirror of https://gitee.com/bigwinds/arangodb
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:
parent
adc651e338
commit
6674a4282d
|
@ -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
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
@ -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
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
@ -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
|
||||
// -----------------------------------------------------------------------------
|
||||
// -----------------------------------------------------------------------------
|
||||
|
|
|
@ -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
|
||||
);
|
||||
};
|
||||
|
||||
|
|
Loading…
Reference in New Issue