MojErr MojDb::delObj(const MojObject& id, const MojObject& obj, MojDbStorageItem* item, MojObject& foundObjOut, MojDbReq& req, MojUInt32 flags) { MojAssert(item); MojLogTrace(s_log); if (MojFlagGet(flags, FlagPurge)) { // update indexes MojTokenSet tokenSet; // we want purge to force delete req.fixmode(true); MojErr err = m_kindEngine.update(NULL, &obj, req, OpDelete, tokenSet); MojErrCheck(err); // gross layering violation err = req.txn()->offsetQuota(-(MojInt64) item->size()); MojErrCheck(err); // permanently delete bool found = false; err = m_objDb->del(id, req.txn(), found); MojErrCheck(err); if (!found) MojErrThrow(MojErrDbCorruptDatabase); err = foundObjOut.put(IdKey, id); MojErrCheck(err); } else { // set deleted flag and put if we are not purging MojObject newObj = obj; MojErr err = newObj.putBool(DelKey, true); MojErrCheck(err); err = putObj(id, newObj, &obj, item, req, OpDelete); MojErrCheck(err); foundObjOut = newObj; } return MojErrNone; }
MojErr MojDbKind::updateOwnIndexes(const MojObject* newObj, const MojObject* oldObj, const MojDbReq& req, MojInt32& idxcount) { MojInt32 count = 0; for (IndexVec::ConstIterator i = m_indexes.begin(); i != m_indexes.end(); ++i) { count++; MojErr err = (*i)->update(newObj, oldObj, req.txn(), req.fixmode()); MojErrCheck(err); } MojLogInfo(s_log, _T("Kind_UpdateOwnIndexes: %s; count: %d \n"), this->id().data(), count); idxcount += count; return MojErrNone; }
MojErr MojDb::purgeImpl(MojObject& obj, MojUInt32& countOut, MojDbReq& req) { MojLogTrace(s_log); MojObject val; MojErr err = obj.getRequired(RevNumKey, val); MojErrCheck(err); MojObject timestamp; err = obj.getRequired(TimestampKey, timestamp); MojErrCheck(err); // purge all objects that were deleted on or prior to this rev num // query for objects in two passes - once where backup is true and once where backup is false MojDbQuery objQuery; err = objQuery.from(MojDbKindEngine::RootKindId); MojErrCheck(err); err = objQuery.where(DelKey, MojDbQuery::OpEq, true); MojErrCheck(err); err = objQuery.where(SyncKey, MojDbQuery::OpEq, true); MojErrCheck(err); err = objQuery.where(RevKey, MojDbQuery::OpLessThanEq, val); MojErrCheck(err); MojUInt32 backupCount = 0; req.autobatch(true); req.fixmode(true); objQuery.limit(AutoBatchSize); err = delImpl(objQuery, backupCount, req, FlagPurge); MojErrCheck(err); MojDbQuery objQuery2; err = objQuery2.from(MojDbKindEngine::RootKindId); MojErrCheck(err); err = objQuery2.where(DelKey, MojDbQuery::OpEq, true); MojErrCheck(err); err = objQuery2.where(SyncKey, MojDbQuery::OpEq, false); MojErrCheck(err); err = objQuery2.where(RevKey, MojDbQuery::OpLessThanEq, val); MojErrCheck(err); MojUInt32 count = 0; MojUInt32 batchRemain = 0; if (backupCount <= AutoBatchSize) batchRemain = AutoBatchSize - backupCount; req.autobatch(true); // enable auto batch req.fixmode(true); // force deletion of bad entries if (batchRemain > 0) { objQuery2.limit(batchRemain); err = delImpl(objQuery2, count, req, FlagPurge); MojErrCheck(err); } countOut = count + backupCount; req.autobatch(false); // if we actually deleted objects, store this rev num as the last purge rev if (countOut > 0) { err = updateState(LastPurgedRevKey, val, req); MojErrCheck(err); } // delete all the RevTimestamp entries prior to this one MojDbQuery revTimestampQuery; err = revTimestampQuery.from(MojDbKindEngine::RevTimestampId); MojErrCheck(err); err = revTimestampQuery.where(TimestampKey, MojDbQuery::OpLessThanEq, timestamp); MojErrCheck(err); count = 0; err = delImpl(revTimestampQuery, count, req, FlagPurge); MojErrCheck(err); return MojErrNone; }