MojErr MojService::dispatchReply(MojServiceMessage* msg) { MojAssert(msg); MojAssertMutexUnlocked(m_mutex); MojLogTrace(s_log); // parse payload MojObjectBuilder builder; MojObject payload; MojErr err = MojErrNone; MojInt64 errCode = MojErrNone; errCode = err = msg->payload(builder); MojErrCatchAll(err); if (errCode == MojErrNone) payload = builder.object(); // get errCode bool retVal = false; if (payload.get(MojServiceMessage::ReturnValueKey, retVal) && !retVal) { if (!payload.get(MojServiceMessage::ErrorCodeKey, errCode)) errCode = MojErrUnknown; } // find request MojRefCountedPtr<MojServiceRequest> req; err = getRequest(msg, req); MojErrCheck(err); // do the dispatch err = dispatchReplyImpl(req.get(), msg, payload, (MojErr) errCode); MojErrCatchAll(err); return MojErrNone; }
MojErr MojDbQuery::toObject(MojObject& objOut) const { MojObjectBuilder builder; MojErr err = toObject(builder); MojErrCheck(err); objOut = builder.object(); return MojErrNone; }
MojErr MojDbIsamQuery::parseId(MojObject& idOut) { // parse id out of key MojObjectEater eater; MojObjectReader reader(m_keyData, m_keySize); for (MojSize i = 0; i < m_plan->idIndex(); ++i) { MojErr err = reader.nextObject(eater); MojErrCheck(err); } MojObjectBuilder builder; MojErr err = reader.nextObject(builder); MojErrCheck(err); idOut = builder.object(); return MojErrNone; }
MojErr MojDb::get(const MojObject& id, MojObject& objOut, bool& foundOut, MojDbReqRef req) { MojLogTrace(s_log); objOut.clear(); foundOut = false; MojObjectBuilder builder; MojErr err = get(&id, &id + 1, builder, req); MojErrCheck(err); objOut = builder.object(); foundOut = !objOut.undefined(); return MojErrNone; }
MojErr MojDbDistinctTest::check(MojDb& db, const MojDbQuery& query, MojDbCursor& cursor, const MojChar* queryString, const MojChar* expectedIdsJson) { MojErr err = db.find(query, cursor); MojTestErrCheck(err); MojObjectBuilder builder; err = builder.beginArray(); MojTestErrCheck(err); err = cursor.visit(builder); MojTestErrCheck(err); err = cursor.close(); MojTestErrCheck(err); err = builder.endArray(); MojTestErrCheck(err); MojObject results = builder.object(); MojString json; err = results.toJson(json); MojTestErrCheck(err); MojObject expected; err = expected.fromJson(expectedIdsJson); MojTestErrCheck(err); // size check MojTestAssert(expected.size() == results.size()); // value check MojObject::ConstArrayIterator j = results.arrayBegin(); for (MojObject::ConstArrayIterator i = expected.arrayBegin(); i != expected.arrayEnd(); ++i, ++j) { MojObject value; err = j->getRequired(queryString, value); MojTestErrCheck(err); MojTestAssert(*i == value); } return MojErrNone; }
MojErr MojDbSearchTest::check(MojDb& db, const MojDbQuery& query, const MojChar* expectedIdsJson) { MojString str; MojDbSearchCursor cursor(str); MojErr err = db.find(query, cursor); MojTestErrCheck(err); MojObjectBuilder builder; err = builder.beginArray(); MojTestErrCheck(err); err = cursor.visit(builder); MojTestErrCheck(err); err = cursor.close(); MojTestErrCheck(err); err = builder.endArray(); MojTestErrCheck(err); MojObject results = builder.object(); MojString json; err = results.toJson(json); MojTestErrCheck(err); MojObject expected; err = expected.fromJson(expectedIdsJson); MojTestErrCheck(err); MojTestAssert(expected.size() == results.size()); MojObject::ConstArrayIterator j = results.arrayBegin(); for (MojObject::ConstArrayIterator i = expected.arrayBegin(); i != expected.arrayEnd(); ++i, ++j) { MojObject id; err = j->getRequired(MojDb::IdKey, id); MojTestErrCheck(err); MojTestAssert(*i == id); } return MojErrNone; }
/** **************************************************************************************************** * @run MojObject stores key-value pairs.Internally it provides separate implmentation for all data types. Provides facility to push single entry or entire array of data into MojObject. Supports put/get/delete operation. Data having key and value is converted to Node type and then node is inserted into TreeBase. All operation happens on TreeBase are based on key. Provides interface to convert JSON string to JSON object and viceversa. * @param : None * @retval : MojErr **************************************************************************************************** **/ MojErr MojObjectTest::run() { MojObject obj0; MojObject obj1; MojObject obj2; MojObject obj3; MojObject obj4; MojString str1; MojObjectBuilder builder; int count = 0; bool found = false; // empty object MojTestAssert(obj1.type() == MojObject::TypeUndefined); MojErr err = emptyTest(obj1); MojTestErrCheck(err); obj1.clear(MojObject::TypeNull); MojTestAssert(obj1.type() == MojObject::TypeNull); err = emptyTest(obj1); MojTestErrCheck(err); obj1.clear(MojObject::TypeObject); MojTestAssert(obj1.type() == MojObject::TypeObject); err = emptyTest(obj1); MojTestErrCheck(err); obj1.clear(MojObject::TypeArray); MojTestAssert(obj1.type() == MojObject::TypeArray); err = emptyTest(obj1); MojTestErrCheck(err); obj1.clear(MojObject::TypeString); MojTestAssert(obj1.type() == MojObject::TypeString); err = emptyTest(obj1); MojTestErrCheck(err); obj1.clear(MojObject::TypeBool); MojTestAssert(obj1.type() == MojObject::TypeBool); err = emptyTest(obj1); MojTestErrCheck(err); obj1.clear(MojObject::TypeDecimal); MojTestAssert(obj1.type() == MojObject::TypeDecimal); err = emptyTest(obj1); MojTestErrCheck(err); obj1.clear(MojObject::TypeInt); MojTestAssert(obj1.type() == MojObject::TypeInt); err = emptyTest(obj1); MojTestErrCheck(err); err = obj2.fromJson("{}"); MojTestAssert(obj2.type() == MojObject::TypeObject); MojTestErrCheck(err); err = emptyTest(obj2); MojTestErrCheck(err); err = obj3.put(_T("hello"), 5LL); MojTestErrCheck(err); err = obj3.del(_T("hello"), found); MojTestErrCheck(err); MojTestAssert(found); err = emptyTest(obj3); MojTestErrCheck(err); err = obj3.put(_T("hello"), 5LL); MojTestErrCheck(err); obj3.clear(); err = emptyTest(obj3); MojTestErrCheck(err); // put/get/del err = putTest(obj1); MojTestErrCheck(err); err = getTest(obj1); MojTestErrCheck(err); err = obj1.visit(builder); MojTestErrCheck(err); err = getTest(builder.object()); MojTestErrCheck(err); err = obj1.toJson(str1); MojTestErrCheck(err); err = obj2.fromJson(str1); MojTestErrCheck(err); err = getTest(obj2); MojTestErrCheck(err); obj3 = obj2; err = getTest(obj3); MojTestErrCheck(err); obj3.clear(); MojTestAssert(obj3.empty()); // iterator for (MojObject::ConstIterator i = obj2.begin(); i != obj2.end(); ++i) { count++; obj3.put(i.key(), i.value()); } MojTestAssert(count == 10); err = getTest(obj3); MojTestErrCheck(err); // types err = typeTest(); MojTestErrCheck(err); return MojErrNone; }
MojErr MojDb::load(const MojChar* path, MojUInt32& countOut, MojUInt32 flags, MojDbReqRef req) { MojAssert(path); MojLogTrace(s_log); MojErr err = beginReq(req, true); MojErrCheck(err); MojFile file; err = file.open(path, MOJ_O_RDONLY); MojErrCheck(err); MojJsonParser parser; parser.begin(); MojSize bytesRead = 0; MojObjectBuilder visitor; int total_mutexes, mutexes_free, mutexes_used, mutexes_used_highwater, mutex_regionsize; m_objDb->mutexStats(&total_mutexes, &mutexes_free, &mutexes_used, &mutexes_used_highwater, &mutex_regionsize); MojLogDebug(s_log, _T("Starting load of %s, total_mutexes: %d, mutexes_free: %d, mutexes_used: %d, mutexes_used_highwater: %d, &mutex_regionsize: %d\n"), path, total_mutexes, mutexes_free, mutexes_used, mutexes_used_highwater, mutex_regionsize); int orig_mutexes_used = mutexes_used; struct timeval startTime = {0,0}, stopTime = {0,0}; gettimeofday(&startTime, NULL); int total_transaction_time = 0; int total = 0; int transactions = 0; do { MojChar buf[MojFile::MojFileBufSize]; err = file.read(buf, sizeof(buf), bytesRead); MojErrCheck(err); const MojChar* parseEnd = buf; while (parseEnd < (buf + bytesRead)) { err = parser.parseChunk(visitor, parseEnd, bytesRead - (parseEnd - buf), parseEnd); MojErrCheck(err); if (parser.finished()) { //store the object err = loadImpl(visitor.object(), flags, req); MojErrCheck(err); countOut++; parser.begin(); visitor.reset(); total++; if ((total % 10) == 0) { // For debugging mutex consumption during load operations, we periodically retrieve the mutex stats. m_objDb->mutexStats(&total_mutexes, &mutexes_free, &mutexes_used, &mutexes_used_highwater, &mutex_regionsize); MojLogDebug(s_log, _T("Loading %s record %d, total_mutexes: %d, mutexes_free: %d, mutexes_used: %d, mutexes_used_highwater: %d, &mutex_regionsize: %d\n"), path, total, total_mutexes, mutexes_free, mutexes_used, mutexes_used_highwater, mutex_regionsize); } // If a loadStepSize is configured, then break up the load into separate transactions. // This is intended to prevent run-away mutex consumption in some particular scenarios. // The transactions do not reverse or prevent mutex consumption, but seem to reduce the // growth and eventually cause it to level off. if ((m_loadStepSize > 0) && ((total % m_loadStepSize) == 0)) { // Close and reopen transaction, to prevent a very large transaction from building up. MojLogDebug(s_log, _T("Loading %s record %d, closing and reopening transaction.\n"), path, total); struct timeval transactionStartTime = {0,0}, transactionStopTime = {0,0}; gettimeofday(&transactionStartTime, NULL); err = req->end(); MojErrCheck(err); err = req->endBatch(); MojErrCheck(err); req->beginBatch(); // beginBatch() invocation for first transaction happened in MojDbServiceHandlerBase::invokeImpl err = beginReq(req, true); MojErrCheck(err); gettimeofday(&transactionStopTime, NULL); long int elapsedTransactionTimeMS = (transactionStopTime.tv_sec - transactionStartTime.tv_sec) * 1000 + (transactionStopTime.tv_usec - transactionStartTime.tv_usec) / 1000; total_transaction_time += (int)elapsedTransactionTimeMS; transactions++; } } } } while (bytesRead > 0); err = parser.end(visitor); MojErrCheck(err); if (parser.finished()) { err = loadImpl(visitor.object(), flags, req); MojErrCheck(err); countOut++; } else if (bytesRead > 0) { MojErrThrow(MojErrJsonParseEof); } err = req->end(); MojErrCheck(err); gettimeofday(&stopTime, NULL); long int elapsedTimeMS = (stopTime.tv_sec - startTime.tv_sec) * 1000 + (stopTime.tv_usec - startTime.tv_usec) / 1000; m_objDb->mutexStats(&total_mutexes, &mutexes_free, &mutexes_used, &mutexes_used_highwater, &mutex_regionsize); MojLogDebug(s_log, _T("Finished load of %s, total_mutexes: %d, mutexes_free: %d, mutexes_used: %d, mutexes_used_highwater: %d, &mutex_regionsize: %d\n"), path, total_mutexes, mutexes_free, mutexes_used, mutexes_used_highwater, mutex_regionsize); MojLogDebug(s_log, _T("Loaded %s with %d records in %ldms (%dms of that for %d extra transactions), consuming %d mutexes, afterwards %d are available out of %d\n"), path, total, elapsedTimeMS, total_transaction_time, transactions, mutexes_used - orig_mutexes_used, mutexes_free, total_mutexes); return MojErrNone; }