MojErr MojDbPutHandler::open(const MojObject& conf, MojDb* db, MojDbReq& req) { LOG_TRACE("Entering function %s", __FUNCTION__); MojAssertWriteLocked(db->schemaLock()); m_db = db; // configure MojErr err = configure(conf, req); MojErrCheck(err); // load permissions from db MojDbQuery query; err = query.from(m_kindId); MojErrCheck(err); MojDbCursor cursor; err = db->find(query, cursor, req); MojErrCheck(err); for (;;) { bool found = false; MojObject perm; err = cursor.get(perm, found); MojErrCheck(err); if (!found) break; err = put(perm, req, false); MojErrCheck(err); } return MojErrNone; }
MojErr MojDbQuotaEngine::refreshImpl(MojDbStorageTxn* txn) { MojLogTrace(s_log); MojAssert(txn); MojAssertWriteLocked(m_db->schemaLock()); // zero out quota usages for (QuotaMap::ConstIterator i = m_quotas.begin(); i != m_quotas.end(); ++i) { (*i)->usage(0); } // recalculate from kind usages MojDbKindEngine::KindMap& kinds = m_db->kindEngine()->kindMap(); for (MojDbKindEngine::KindMap::ConstIterator i = kinds.begin(); i != kinds.end(); ++i) { MojRefCountedPtr<Quota> quota; MojErr err = quotaForKind(i->get(), quota); MojErrCheck(err); if (quota.get()) { MojInt64 usage = 0; err = kindUsage((*i)->id(), usage, txn); MojErrCheck(err); quota->offset(usage); } } return MojErrNone; }
MojErr MojDbQuotaEngine::commitQuota(const MojString& owner, MojInt64 size) { LOG_TRACE("Entering function %s", __FUNCTION__); MojAssertWriteLocked(m_db->schemaLock()); // get or create quota object QuotaMap::Iterator iter; MojErr err = m_quotas.find(owner, iter); MojErrCheck(err); if (iter == m_quotas.end()) { MojRefCountedPtr<Quota> quota(new Quota(size)); MojAllocCheck(quota.get()); err = m_quotas.put(owner, quota); MojErrCheck(err); } else { iter.value()->size(size); } if (m_isOpen) { err = refresh(); MojErrCheck(err); } return MojErrNone; }
MojErr MojDbKindEngine::setupRootKind() { MojLogTrace(s_log); MojAssertWriteLocked(m_db->m_schemaLock); MojDbKind* kind = NULL; MojErr err = getKind(RootKindId, kind); MojErrCheck(err); return MojErrNone; }
MojErr MojDbKindEngine::addBuiltin(const MojChar* json, MojDbReq& req) { MojLogTrace(s_log); MojAssertWriteLocked(m_db->m_schemaLock); MojObject obj; MojErr err = obj.fromJson(json); MojErrCheck(err); err = putKind(obj, req, true); MojErrCheck(err); return MojErrNone; }
MojErr MojDbKindEngine::updateLocale(const MojChar* locale, MojDbReq& req) { MojAssert(locale); MojAssert(isOpen()); MojAssertWriteLocked(m_db->m_schemaLock); MojLogTrace(s_log); MojErr err = m_locale.assign(locale); MojErrCheck(err); for (KindMap::ConstIterator i = m_kinds.begin(); i != m_kinds.end(); ++i) { err = (*i)->updateLocale(locale, req); MojErrCheck(err); } return MojErrNone; }
MojErr MojDbQuotaEngine::refresh() { MojLogTrace(s_log); MojAssertWriteLocked(m_db->schemaLock()); MojRefCountedPtr<MojDbStorageTxn> txn; MojErr err = m_db->storageEngine()->beginTxn(txn); MojErrCheck(err); err = refreshImpl(txn.get()); MojErrCheck(err); err = txn->commit(); MojErrCheck(err); return MojErrNone; }
MojErr MojDbQuotaEngine::refresh() { LOG_TRACE("Entering function %s", __FUNCTION__); MojAssertWriteLocked(m_db->schemaLock()); MojRefCountedPtr<MojDbStorageTxn> txn; MojErr err = m_db->storageEngine()->beginTxn(txn); MojErrCheck(err); err = refreshImpl(txn.get()); MojErrCheck(err); err = txn->commit(); MojErrCheck(err); return MojErrNone; }
MojErr MojDbKindEngine::reloadKind(const MojString& id, const MojObject& kindObj, MojDbReq& req) { MojAssert(isOpen()); MojAssertWriteLocked(m_db->m_schemaLock); MojLogTrace(s_log); // delete old one bool found = false; MojErr err = m_kinds.del(id, found); MojErrCheck(err); // replace with new one err = createKind(id, kindObj, req); MojErrCheck(err); return MojErrNone; }
MojErr MojDbQuotaEngine::put(MojObject& obj, MojDbReq& req, bool putObj) { MojLogTrace(s_log); MojAssertWriteLocked(m_db->schemaLock()); // check for admin permission if (!req.admin()) { MojErrThrow(MojErrDbPermissionDenied); } // pull params out of object MojString owner; MojErr err = obj.getRequired(MojDbServiceDefs::OwnerKey, owner); MojErrCheck(err); MojInt64 size = 0; err = obj.getRequired(MojDbServiceDefs::SizeKey, size); MojErrCheck(err); // validate owner err = validateWildcard(owner, MojErrDbInvalidOwner); MojErrCheck(err); // put object if (putObj) { MojString id; err = id.format(_T("_quotas/%s"), owner.data()); MojErrCheck(err); err = obj.put(MojDb::IdKey, id); MojErrCheck(err); err = obj.putString(MojDb::KindKey, MojDbKindEngine::QuotaId); MojErrCheck(err); MojDbAdminGuard adminGuard(req); err = m_db->put(obj, MojDb::FlagForce, req); MojErrCheck(err); // defer commit of quota until txn commit MojRefCountedPtr<MojDbQuotaCommitHandler> handler(new MojDbQuotaCommitHandler(this, owner, size, req.txn())); MojAllocCheck(handler.get()); } else { err = commitQuota(owner, size); MojErrCheck(err); } return MojErrNone; }
MojErr MojDbPutHandler::configure(const MojObject& conf, MojDbReq& req) { LOG_TRACE("Entering function %s", __FUNCTION__); MojAssertWriteLocked(m_db->schemaLock()); // built-in permissions MojObject objects; if (conf.get(m_confProp, objects)) { MojObject::ConstArrayIterator end = objects.arrayEnd(); for (MojObject::ConstArrayIterator i = objects.arrayBegin(); i != end; ++i) { MojObject perm(*i); MojErr err = put(perm, req, false); MojErrCheck(err); } } return MojErrNone; }
MojErr MojDbKindEngine::delKind(const MojString& id, MojDbReq& req) { MojAssert(isOpen()); MojAssertWriteLocked(m_db->m_schemaLock); MojLogTrace(s_log); KindMap::ConstIterator i = m_kinds.find(id); if (i != m_kinds.end()) { // notify kind obj MojErr err = (*i)->drop(req); MojErrCheck(err); // delete from map bool found = false; err = m_kinds.del(id, found); MojErrCheck(err); MojAssert(found); } return MojErrNone; }
MojErr MojDbKindEngine::open(MojDb* db, MojDbReq& req) { MojAssert(db); MojAssertWriteLocked(db->m_schemaLock); MojLogTrace(s_log); // open kind db and index seq m_db = db; MojDbStorageEngine* engine = db->storageEngine(); MojDbStorageTxn* txn = req.txn(); MojAssert(engine); MojErr err = engine->openDatabase(KindsDbName, txn, m_kindDb); MojErrCheck(err); err = engine->openDatabase(IndexIdsDbName, txn, m_indexIdDb); MojErrCheck(err); err = engine->openSequence(IndexIdsSeqName, txn, m_indexIdSeq); MojErrCheck(err); // built-in kinds err = addBuiltin(RootKindJson, req); MojErrCheck(err); err = addBuiltin(KindKindJson, req); MojErrCheck(err); err = addBuiltin(RevTimestampJson, req); MojErrCheck(err); err = addBuiltin(DbStateJson, req); MojErrCheck(err); err = addBuiltin(PermissionJson, req); MojErrCheck(err); err = addBuiltin(QuotaJson, req); MojErrCheck(err); // built-in indexes err = setupRootKind(); MojErrCheck(err); // locale err = db->getLocale(m_locale, req); MojErrCheck(err); // load kinds from obj db err = loadKinds(req); MojErrCheck(err); return MojErrNone; }
MojErr MojDbKindEngine::loadKinds(MojDbReq& req) { MojAssert(isOpen()); MojAssertWriteLocked(m_db->m_schemaLock); MojLogTrace(s_log); MojDbQuery query; MojErr err = query.from(KindKindId); MojErrCheck(err); MojDbCursor cursor; err = m_db->find(query, cursor, req); MojErrCheck(err); for (;;) { MojObject obj; bool found = false; err = cursor.get(obj, found); MojErrCheck(err); if (!found) break; // load kind MojErr loadErr = err = putKind(obj, req); MojErrCatchAll(err) { MojString id; bool found = false; MojErr err = obj.get(MojDbServiceDefs::IdKey, id, found); MojErrCheck(err); MojString errStr; MojErrToString(loadErr, errStr); MojLogError(s_log, _T("error loading kind '%s' - %s"), id.data(), errStr.data()); } } err = cursor.close(); MojErrCheck(err); return MojErrNone; }
MojErr MojDbKindEngine::putKind(const MojObject& obj, MojDbReq& req, bool builtin) { MojAssert(isOpen()); MojAssertWriteLocked(m_db->m_schemaLock); MojLogTrace(s_log); // parse out id MojString id; MojErr err = obj.getRequired(MojDbServiceDefs::IdKey, id); MojErrCheck(err); KindMap::ConstIterator i = m_kinds.find(id); if (i == m_kinds.end()) { // new kind err = createKind(id, obj, req, builtin); MojErrCheck(err); } else { // existing kind MojLogDebug(s_log, _T("UpdatingKind: %s \n"), id.data()); err = (*i)->configure(obj, m_kinds, m_locale, req); MojErrCheck(err); } return MojErrNone; }