MojErr MojDbIndex::addWatch(const MojDbQueryPlan& plan, MojDbCursor& cursor, MojDbWatcher* watcher, MojDbReq& req) { MojAssert(watcher); MojLogTrace(s_log); // TODO: use interval tree instead of vector for watches MojThreadWriteGuard guard(m_lock); MojErr err = m_watcherVec.push(watcher); MojErrCheck(err); // update count map watcher->domain(req.domain()); WatcherMap::Iterator iter; err = m_watcherMap.find(req.domain(), iter); MojErrCheck(err); if (iter == m_watcherMap.end()) { err = m_watcherMap.put(req.domain(), 1); MojErrCheck(err); } else { iter.value() += 1; if (iter.value() > WatchWarningThreshold) { MojLogWarning(s_log, _T("db:'%s' has %zd watches open on index '%s - %s'"), req.domain().data(), iter.value(), m_kind->id().data(), m_name.data()); } } MojLogInfo(s_log, _T("DbIndex_addWatch - '%s' on index '%s - %s'"), req.domain().data(), m_kind->id().data(), m_name.data()); // drop lock before acquiring watcher mutex in init guard.unlock(); watcher->init(this, plan.ranges(), plan.desc(), false); return MojErrNone; }
MojErr MojDbIndex::cancelWatch(MojDbWatcher* watcher) { LOG_TRACE("Entering function %s", __FUNCTION__); MojAssert(isOpen()); MojAssert(watcher); LOG_DEBUG("[db_mojodb] Index_cancelWatch: index name = %s; domain = %s\n", this->name().data(), watcher->domain().data()); MojThreadWriteGuard guard(m_lock); MojSize idx; MojSize size = m_watcherVec.size(); for (idx = 0; idx < size; ++idx) { if (m_watcherVec.at(idx).get() == watcher) { MojErr err = m_watcherVec.erase(idx); MojErrCheck(err); WatcherMap::Iterator iter; err = m_watcherMap.find(watcher->domain(), iter); MojErrCheck(err); if (iter != m_watcherMap.end()) { iter.value() -= 1; if (iter.value() == 0) { bool found = false; m_watcherMap.del(iter.key(), found); MojAssert(found); LOG_DEBUG("[db_mojodb] Index_cancelwatch: Domain Del found = %d; index name = %s; domain = %s\n", (int)found, this->name().data(), watcher->domain().data()); } } break; } } if (idx == size) MojErrThrow(MojErrDbWatcherNotRegistered); return MojErrNone; }
MojErr MojDbIndex::cancelWatch(MojDbWatcher* watcher) { MojAssert(isOpen()); MojAssert(watcher); MojLogTrace(s_log); MojLogInfo(s_log, _T("Index_cancelWatch: index name = %s; domain = %s\n"), this->name().data(), watcher->domain().data()); MojThreadWriteGuard guard(m_lock); MojSize idx; MojSize size = m_watcherVec.size(); for (idx = 0; idx < size; ++idx) { if (m_watcherVec.at(idx).get() == watcher) { MojErr err = m_watcherVec.erase(idx); MojErrCheck(err); WatcherMap::Iterator iter; err = m_watcherMap.find(watcher->domain(), iter); MojErrCheck(err); if (iter != m_watcherMap.end()) { iter.value() -= 1; if (iter.value() == 0) { bool found = false; m_watcherMap.del(iter.key(), found); MojAssert(found); MojLogInfo(s_log, _T("Index_cancelwatch: Domain Del found = %d; index name = %s; domain = %s\n"), (int)found, this->name().data(), watcher->domain().data()); } } break; } } if (idx == size) MojErrThrow(MojErrDbWatcherNotRegistered); return MojErrNone; }
MojErr MojDbIndex::addWatch(const MojDbQueryPlan& plan, MojDbCursor& cursor, MojDbWatcher* watcher, MojDbReq& req) { LOG_TRACE("Entering function %s", __FUNCTION__); MojAssert(watcher); // TODO: use interval tree instead of vector for watches MojThreadWriteGuard guard(m_lock); MojErr err = m_watcherVec.push(watcher); MojErrCheck(err); // update count map watcher->domain(req.domain()); WatcherMap::Iterator iter; err = m_watcherMap.find(req.domain(), iter); MojErrCheck(err); if (iter == m_watcherMap.end()) { err = m_watcherMap.put(req.domain(), 1); MojErrCheck(err); } else { iter.value() += 1; if (iter.value() > WatchWarningThreshold) { LOG_WARNING(MSGID_MOJ_DB_INDEX_WARNING, 4, PMLOGKS("domain", req.domain().data()), PMLOGKFV("iter", "%zd", iter.value()), PMLOGKS("kindId", m_kind->id().data()), PMLOGKS("name", m_name.data()), "db:'domain' has 'iter' watches open on index 'kindId - name'"); } } LOG_DEBUG("[db_mojodb] DbIndex_addWatch - '%s' on index '%s - %s'", req.domain().data(), m_kind->id().data(), m_name.data()); // drop lock before acquiring watcher mutex in init guard.unlock(); watcher->init(this, plan.ranges(), plan.desc(), false); return MojErrNone; }