/***********************************************************************
 * setPagePosition
 *
 * Move cursor position to page id provided in query.
 *   1. Find item "_id" which is equal to page id iteratively.
 *   2. If found, set begin/last position and next page.
 ***********************************************************************/
MojErr MojDbSearchCursor::setPagePosition()
{
    LOG_TRACE("Entering function %s", __FUNCTION__);

    MojErr err;
    MojDbStorageItem* item;
    m_pos = m_items.begin();
    ItemVec::ConstIterator last = m_items.end();
    m_limitPos = last;
    // retrieve page id from query
    MojObject pageKey;
    err = m_page.toObject(pageKey);
    MojErrCheck(err);
    while (m_pos != last) {
        // retrieve id from query
        item = m_pos->get();
        const MojObject id = item->id();
        // If match, set begin/last position and next page
        if(pageKey.compare(id) == 0) {
            if (m_limit >= (last-m_pos)) {
                m_limitPos = m_items.end();
                m_page.clear();
            } else {
                m_limitPos = m_pos + m_limit;
                // set next page
                MojDbStorageItem* nextItem = m_limitPos->get();
                const MojObject nextId = nextItem->id();
                m_page.fromObject(nextId);
                // print log for nextId
                MojString strOut;
                err = nextId.toJson(strOut);
                MojErrCheck(err);
                LOG_DEBUG("[db_mojodb] nextId : %s \n", strOut.data());
            }
            break;
        }
        ++m_pos;
    }

    return MojErrNone;
}
Exemple #2
0
MojErr MojDb::merge(const MojDbQuery& query, const MojObject& props, MojUInt32& countOut, MojUInt32 flags, MojDbReqRef req)
{
	MojLogTrace(s_log);

	countOut = 0;
	MojErr err = beginReq(req);
	MojErrCheck(err);

	MojDbCursor cursor;
	err = findImpl(query, cursor, NULL, req, OpUpdate);
	MojErrCheck(err);
	MojAssert(cursor.txn());

	MojUInt32 count = 0;
	MojUInt32 warns = 0;
	bool found = false;
	MojObject prev;
	for (;;) {
		// get prev rev from cursor
		MojDbStorageItem* prevItem = NULL;
		err = cursor.get(prevItem, found);
		if (err == MojErrInternalIndexOnFind) {
			warns++;
			continue;
		}
		MojErrCheck(err);
		if (!found)
			break;
		err = prevItem->toObject(prev, m_kindEngine);
		MojErrCheck(err);
		// merge obj into prev
		MojObject merged;
		err = mergeInto(merged, props, prev);
		MojErrCheck(err);
		// and update the db
		const MojObject& id = prevItem->id();
		err = putObj(id, merged, &prev, prevItem, req, OpUpdate);
		MojErrCheck(err);
		++count;
	}
	if (warns > 0)
		MojLogWarning(s_log, _T("Merge index_warnings: %s; count: %d\n"), query.from().data(), warns);
	err = cursor.close();
	MojErrCheck(err);
	err = req->end();
	MojErrCheck(err);

	countOut = count;

	return MojErrNone;
}
MojErr MojDbSearchCursor::load()
{
    LOG_TRACE("Entering function %s", __FUNCTION__);

    // pull unique ids from index
    ObjectSet ids;
    MojErr err = loadIds(ids);
    MojErrCheck(err);

    // load objects into memory
    err = loadObjects(ids);
    MojErrCheck(err);
    // sort results
    if (!m_orderProp.empty()) {
        err = sort();
        MojErrCheck(err);
    }
    // distinct
    if (!m_distinct.empty()) {
        distinct();
    }
    // reverse for desc
    if (m_query.desc()) {
        err = m_items.reverse();
        MojErrCheck(err);
    }
    // next page
    if (!m_page.empty()) {
        err = setPagePosition();
        MojErrCheck(err);
    } else {
        // set begin/last position.
        m_pos = m_items.begin();
        if (m_limit >= m_items.size()) {
            m_limitPos = m_items.end();
        } else {
            // if item size is bigger than limit, set next page.
            m_limitPos = m_items.begin() + m_limit;
            MojDbStorageItem* nextItem = m_limitPos->get();
            const MojObject nextId = nextItem->id();
            m_page.fromObject(nextId);
        }
    }
    // set remainder count
    m_count = m_items.end() - m_pos;

    return MojErrNone;
}
Exemple #4
0
MojErr MojDb::delImpl(const MojDbQuery& quer, MojUInt32& countOut, MojDbReq& req, MojUInt32 flags)
{
	MojLogTrace(s_log);

	countOut = 0;
	MojInt32 warns = 0;
    MojDbQuery newQuery = quer;
    MojUInt32 queryLimit = newQuery.limit();

    if(newQuery.limit() == MojDbQuery::LimitDefault)
        newQuery.limit(AutoBatchSize);

    while(queryLimit > 0)
    {
        MojDbCursor cursor;
        MojErr err = findImpl(newQuery, cursor, NULL, req, OpDelete);

        MojErrCheck(err);
        MojAssert(cursor.txn());

        MojUInt32 count = 0;
        MojUInt32 numberInBatch = 0;

        bool found = false;

        MojObject obj;
        for (;;) {
            MojDbStorageItem* item = NULL;
            err = cursor.get(item, found);
            // We simply skip ghost keys and continue; A warning is already written to the system log earlier
            if (err == MojErrInternalIndexOnFind) {
                warns++;
                numberInBatch++;
                continue;
            }
            MojErrCheck(err);
            if (!found)
                break;
            err = item->toObject(obj, m_kindEngine);
            MojErrCheck(err);
            const MojObject& id = item->id();
            MojObject deleted;
            err = delObj(id, obj, item, deleted, req, flags);
            MojErrCheck(err);
            ++count;
            numberInBatch++;
        }

        if (warns > 0)
            MojLogInfo(s_log, _T("delquery index_warnings: %s, count: %d\n"), newQuery.from().data(), warns);
        countOut += count;

        err = cursor.close();
        MojErrCheck(err);

        if(numberInBatch >= AutoBatchSize) // sing > - just in case something messed up
        {
            err = commitBatch(req);
            MojErrCheck(err);
        }

        if(count == 0)
            break;

        queryLimit -= newQuery.limit();
        if(queryLimit > AutoBatchSize)
            newQuery.limit(AutoBatchSize);
        else
            newQuery.limit(queryLimit);
    }

    return MojErrNone;
}