Esempio n. 1
0
MojErr MojObjectFilter::init(const StringSet& selectProps)
{
	MojAssert(m_root.get() == NULL);

	//create the root node
	m_root.reset(new Node(MojString()));
	MojAllocCheck(m_root.get());

	for (StringSet::ConstIterator i = selectProps.begin(); i != selectProps.end(); i++) {
		MojVector<MojString> parts;
		MojErr err = i->split(_T('.'), parts);
		MojErrCheck(err);

		Node* curNode = m_root.get();
		for (MojVector<MojString>::ConstIterator pi = parts.begin(); pi != parts.end(); ++pi) {
			Node* child = curNode->find(*pi);
			if (child) {
				if (child->m_children.empty()) {
					break;
				} else {
					curNode = child;
				}
			} else {
				MojAutoPtr<Node> node(new Node(*pi));
				MojAllocCheck(node.get());
				Node* nextNode = node.get();
				MojErr err = curNode->addChild(node);
				MojErrCheck(err);
				curNode = nextNode;
			}
		}
	}
	return MojErrNone;
}
Esempio n. 2
0
/*
 * Unformat the from address - removes blanks and converts to lower case
 *
 *  see IMAddressFormatter.unformat() - palm.com.messaging.data
 */
MojErr IMMessage::unformatFromAddress(const MojString formattedScreenName, MojString& unformattedName) {

	if(!formattedScreenName.empty()) {
		MojVector<MojString> stringTokens;
		MojErr err = formattedScreenName.split(' ', stringTokens);
		MojErrCheck(err);

		MojVector<MojString>::ConstIterator itr = stringTokens.begin();
		while (itr != stringTokens.end()) {
			err = unformattedName.append(*itr);
			MojErrCheck(err);
			itr++;
		}
		err = unformattedName.toLower();
		MojErrCheck(err);
	}
	return MojErrNone;
}
Esempio n. 3
0
MojErr MojThreadTest::basicTest()
{
	MojVector<MojThreadT> threads;
	MojThreadTestArgs args;
	for (int i = 0; i < MojTestNumThreads; ++i) {
		MojThreadT thread = MojInvalidThread;
		MojErr err = MojThreadCreate(thread, MojThreadTestFn, &args);
		MojTestErrCheck(err);
		MojTestAssert(thread != MojInvalidThread);
		err = threads.push(thread);
		MojTestErrCheck(err);
	}

	{
		MojThreadGuard guard(args.m_mutex);
		while (args.m_counter < (MojTestNumThreads * MojTestNumIterations)) {
			MojErr err = args.m_countCond.wait(args.m_mutex);
			MojErrCheck(err);
		}
		MojTestAssert(args.m_counter == (MojTestNumThreads * MojTestNumIterations));
		MojTestAssert(args.m_atomicCounter == (MojTestNumThreads * MojTestNumIterations));
		guard.unlock();
		MojErr err = MojSleep(MojMillisecs(500));
		MojTestErrCheck(err);
		guard.lock();
		args.m_wait = false;
		err = args.m_waitCond.broadcast();
		MojTestErrCheck(err);
	}

	for (MojVector<MojThreadT>::ConstIterator i = threads.begin();
		 i != threads.end();
		 ++i) {
		MojErr threadErr = MojErrNone;
		MojErr err = MojThreadJoin(*i, threadErr);
		MojTestErrCheck(err);
		MojTestErrCheck(threadErr);
	}
	MojTestAssert(args.m_counter == 0);
	MojTestAssert(args.m_atomicCounter == 0);

	return MojErrNone;
}
Esempio n. 4
0
MojErr MojDbKind::updateIndexes(const MojObject* newObj, const MojObject* oldObj, const MojDbReq& req, MojDbOp op, MojVector<MojDbKind*>& kindVec, MojInt32& idxcount)
{
	MojErr err = kindVec.push(this);
	MojErrCheck(err);

	// update supers
	for (KindVec::ConstIterator i = m_supers.begin();
		 i != m_supers.end(); ++i) {
		if (kindVec.find((*i), 0) == MojInvalidIndex) {
			err = (*i)->updateIndexes(newObj, oldObj, req, op, kindVec, idxcount);
			MojErrCheck(err);
		} else {
			return MojErrNone;
		}
	}
	err = updateOwnIndexes(newObj, oldObj, req, idxcount);
	MojErrCheck(err);

	return MojErrNone;
}
Esempio n. 5
0
MojErr MojHashMapTest::check(MojHashMap<int, int> map, int maxExpected, int& numFound)
{
    MojVector<bool> v;

    numFound = 0;
    MojErr err = v.resize(maxExpected, false);
    MojTestErrCheck(err);
    for (MojHashMap<int, int>::ConstIterator i = map.begin(); i != map.end(); ++i) {
        int key = i.key();
        int val = i.value();
        MojTestAssert(key == val);
        MojTestAssert(key >= 0 && key <= maxExpected);
        MojTestAssert(!v.at(key));
        err = v.setAt(key, true);
        MojTestErrCheck(err);
        ++numFound;
    }

    return MojErrNone;
}
Esempio n. 6
0
MojErr MojDbKind::subKinds(MojVector<MojObject>& kindsOut, const MojDbKind* parent)
{
	if (!m_supers.empty() && parent != m_supers[0])
		return MojErrNone;

	if (!m_builtin) {
		MojErr err = kindsOut.push(m_obj);
		MojErrCheck(err);
	}
	for (KindVec::ConstIterator i = m_subs.begin(); i != m_subs.end(); ++i) {
		MojErr err = (*i)->subKinds(kindsOut, this);
		MojErrCheck(err);
	}
	return MojErrNone;
}
Esempio n. 7
0
/**
 * testShardCreateAndRemoveWithRecords
 *
 * - create 3 new shards
 * - add records to 1st and 2nd shard
 * - remove shard 1
 * - verify existance of shard 1
 * - verify records of shard 2
 * - remove shard 2
 * - verify existance of shard 2
 * - verify records of shard 3 (== 0)
 * - remove shard 3
 * - verify existance of shard 3
 */
MojErr MojDbShardManagerTest::testShardCreateAndRemoveWithRecords (MojDb& db)
{
    MojDbShardEngine* p_eng = db.shardEngine();
    MojTestAssert(p_eng);

    MojDbShardInfo shard1, shard2;
    MojVector<MojUInt32> arrShardIds;
    MojUInt32 count;

    //---------------------------------------------------------------
    // test shard 1
    //---------------------------------------------------------------

    MojErr err = createShardObjects1(db, shard1);
    MojErrCheck(err);

    //verify number of records for shard 1 (shard is active)
    err = verifyRecords(_T("TestShard1:1"), db, shard1, count);
    MojTestErrCheck(err);
    MojTestAssert(count == 1);

    //err = db.shardEngine()->purgeShardObjects(1);
    //MojTestErrCheck(err);

    //remove shard 1
    arrShardIds.push(shard1.id);
    err = p_eng->removeShardObjects(arrShardIds);
    MojErrCheck(err);

    //verify number of records for shard 1
    err = verifyRecords(_T("TestShard1:1"), db, shard1, count);
    MojErrCheck(err);
    MojTestAssert(count == 0);

    //verify existance of shard 1
    err = verifyShardExistance(db, shard1);
    MojErrCheck(err);

    //---------------------------------------------------------------
    // test shard 2
    //---------------------------------------------------------------

    err = createShardObjects2(db, shard2);
    MojErrCheck(err);

    //verify number of records for shard 1 (shard is active)
    err = verifyRecords(_T("TestShard1:1"), db, shard2, count);
    MojTestErrCheck(err);
    MojTestAssert(count == 1);

    err = verifyRecords(_T("TestShard2:1"), db, shard2, count);
    MojTestErrCheck(err);
    MojTestAssert(count == 1);

    err = verifyRecords(_T("TestShard3:1"), db, shard2, count);
    MojTestErrCheck(err);
    MojTestAssert(count == 1);

    //remove shard 1
    arrShardIds.push(shard2.id);
    err = p_eng->removeShardObjects(arrShardIds);
    MojErrCheck(err);

    //verify number of records for shard 1
    err = verifyRecords(_T("TestShard1:1"), db, shard2, count);
    MojErrCheck(err);
    MojTestAssert(count == 0);

    err = verifyRecords(_T("TestShard2:1"), db, shard2, count);
    MojErrCheck(err);
    MojTestAssert(count == 0);

    err = verifyRecords(_T("TestShard3:1"), db, shard2, count);
    MojErrCheck(err);
    MojTestAssert(count == 0);

    //verify existance of shard 1
    err = verifyShardExistance(db, shard2);
    MojErrCheck(err);

    return MojErrNone;
}
Esempio n. 8
0
MojErr MojStringTest::run()
{
	MojString str1;
	MojString str2;
	MojString str3;
	MojString str4;
	MojString str5;
	const MojChar* const chars1 = _T("hello");
	const MojChar* const chars2 = _T("howdy!!");
	const MojChar* const chars3 = _T(" hi there  ");
	MojAutoArrayPtr<MojChar> bigFormatStr;
	MojVector<MojString> vec;
	MojSize idx;

	// empty strings
	MojErr err = str2.assign(_T(""));
	MojTestErrCheck(err);
	str3.assign(str2);
	MojTestAssert(str1.data() == str2.data());
	MojTestAssert(str2.data() == str3.data());
	MojTestAssert(str1.length() == 0);
	MojTestAssert(str2.length() == 0);
	MojTestAssert(str3.length() == 0);
	MojTestAssert(str1.empty());
	MojTestAssert(str2.empty());
	MojTestAssert(str3.empty());
	MojTestAssert(str1.compare(_T("")) == 0);
	MojTestAssert(str1.compare(_T(""), 0) == 0);
	MojTestAssert(str1.compareCaseless(_T("")) == 0);
	MojTestAssert(str1.compareCaseless(_T(""), 0) == 0);
	MojTestAssert(str1.startsWith(_T("")));
	MojTestAssert(!str1.startsWith(_T("hello")));
	MojTestAssert(str1 == _T(""));
	MojTestAssert(str1 >= _T(""));
	MojTestAssert(str1 <= _T(""));
	MojTestAssert(!(str1 != _T("")));
	MojTestAssert(!(str1 > _T("")));
	MojTestAssert(!(str1 < _T("")));
	str2.clear();
	MojTestAssert(str1.data() == str2.data());
	str1.swap(str1);
	MojTestAssert(str1 == str2);
	err = str1.assign(_T(""));
	MojTestErrCheck(err);
	MojTestAssert(str1.empty());
	err = str1.truncate(0);
	MojTestErrCheck(err);
	MojTestAssert(str1.empty());
	err = str1.resize(0);
	MojTestErrCheck(err);
	MojTestAssert(str1.empty());
	err = str1.assign(NULL, 0);
	MojTestErrCheck(err);
	MojTestAssert(str1.empty());
	err = str1.append(_T(""));
	MojTestErrCheck(err);
	MojTestAssert(str1.empty());
	err = str1.append(NULL, 0);
	MojTestErrCheck(err);
	MojTestAssert(str1.empty());
	MojTestAssert(str1.find(_T('h')) == MojInvalidIndex);
	MojTestAssert(str1.rfind(_T('h')) == MojInvalidIndex);
	err = str1.substring(0, 0, str2);
	MojTestErrCheck(err);
	MojTestAssert(str2.empty());
	err = str1.split(_T(' '), vec);
	MojTestErrCheck(err);
	MojTestAssert(vec.empty());
	MojString::Iterator iter;
	err = str1.begin(iter);
	MojTestErrCheck(err);
	MojTestAssert(iter == str1.begin());
	MojTestAssert(*iter == 0);
	err = str1.end(iter);
	MojTestErrCheck(err);
	MojTestAssert(iter == str1.end());
	MojTestAssert(*iter == 0);

	// non-empty strings
	err = str1.assign(chars1);
	MojTestErrCheck(err);
	err = str2.assign(chars2);
	MojTestErrCheck(err);
	str3.assign(str1);
	err = str4.assign(_T("hEllo World!"), 5);
	MojTestErrCheck(err);
	err = str4.setAt(0, _T('H'));
	MojTestErrCheck(err);
	err = str4.setAt(4, _T('O'));
	MojTestErrCheck(err);
	MojTestAssert(str4 == _T("HEllO"));
	MojTestAssert(str1.data() != chars1);
	MojTestAssert(str1.length() == 5);
	MojTestAssert(str2.length() == 7);
	MojTestAssert(str3.length() == 5);
	MojTestAssert(!str1.empty());
	MojTestAssert(!str2.empty());
	MojTestAssert(!str3.empty());
	MojTestAssert(str1.compare(chars1) == 0);
	MojTestAssert(str1.compare(chars1, 3) == 0);
	MojTestAssert(str1.compare(chars1, 3000) == 0);
	MojTestAssert(str1.compare(str3) == 0);
	MojTestAssert(str1.compare(chars2) < 0);
	MojTestAssert(str1.compare(chars2, 2) < 0);
	MojTestAssert(str1.compare(str2) < 0);
	MojTestAssert(str1.compare(str4) > 0);
	MojTestAssert(str2.compare(chars1) > 0);
	MojTestAssert(str2.compare(str1) > 0);
	MojTestAssert(str1.compareCaseless(chars1) == 0);
	MojTestAssert(str1.compareCaseless(chars1, 3) == 0);
	MojTestAssert(str1.compareCaseless(str3) == 0);
	MojTestAssert(str1.compareCaseless(str4) == 0);
	MojTestAssert(str1.compareCaseless(chars2) < 0);
	MojTestAssert(str1.compareCaseless(str2) < 0);
	MojTestAssert(str2.compareCaseless(chars1) > 0);
	MojTestAssert(str2.compareCaseless(str1) > 0);
	MojTestAssert(str1.startsWith(_T("")));
	MojTestAssert(str1.startsWith(_T("he")));
	MojTestAssert(str1.startsWith(chars1));
	MojTestAssert(str1.startsWith(str1));
	MojTestAssert(str1.at(0) == chars1[0] && str1.at(3) == chars1[3]);
	MojTestAssert(str1 == chars1);
	MojTestAssert(str1 == str3);
	MojTestAssert(str1 != chars2);
	MojTestAssert(str1 != str2);
	MojTestAssert(str1 != str4);
	MojTestAssert(str1 < chars2);
	MojTestAssert(str1 < str2);
	MojTestAssert(str1 <= chars2);
	MojTestAssert(str1 <= str2);
	MojTestAssert(str1 <= chars1);
	MojTestAssert(str1 <= str3);
	MojTestAssert(str2 > chars1);
	MojTestAssert(str2 > str1);
	MojTestAssert(str2 >= chars1);
	MojTestAssert(str2 >= str2);
	MojTestAssert(str1 >= chars1);
	MojTestAssert(str1 >= str3);
	str1.clear();
	MojTestAssert(str1.empty());
	MojTestAssert(str1.length() == 0);
	MojTestAssert(str1 == _T(""));

	// self-assignment
	err = str1.assign(chars1);
	MojTestErrCheck(err);
	str1.assign(str1);
	MojTestAssert(str1 == chars1);
	err = str1.substring(0, 2, str1);
	MojTestErrCheck(err);
	MojTestAssert(str1 == _T("he"));

	// find char
	err = str1.assign(chars3);
	MojTestErrCheck(err);
	idx = str1.find(_T(' '));
	MojTestAssert(idx == 0);
	idx = str1.find(_T(' '), idx + 1);
	MojTestAssert(idx == 3);
	idx = str1.find(_T(' '), idx + 1);
	MojTestAssert(idx == 9);
	idx = str1.find(_T(' '), idx + 1);
	MojTestAssert(idx == 10);
	idx = str1.find(_T('?'), idx);
	MojTestAssert(idx == MojInvalidIndex);
	idx = str1.rfind(_T(' '));
	MojTestAssert(idx == 10);
	idx = str1.rfind(_T(' '), idx - 1);
	MojTestAssert(idx == 9);
	idx = str1.rfind(_T(' '), idx - 1);
	MojTestAssert(idx == 3);
	idx = str1.rfind(_T(' '), idx - 1);
	MojTestAssert(idx == 0);
	idx = str1.rfind(_T('&'));
	MojTestAssert(idx == MojInvalidIndex);
	// find str
	idx = str1.find(_T(" "));
	MojTestAssert(idx == 0);
	idx = str1.find(_T(" "), idx + 1);
	MojTestAssert(idx == 3);
	idx = str1.find(_T(" "), idx + 1);
	MojTestAssert(idx == 9);
	idx = str1.find(_T(" "), idx + 1);
	MojTestAssert(idx == 10);
	idx = str1.find(_T("?"), idx);
	MojTestAssert(idx == MojInvalidIndex);
	idx = str1.find(_T("hi"));
	MojTestAssert(idx == 1);

	// split
	err = str1.assign(_T(" hi   there   !  "));
	MojTestErrCheck(err);
	err = str1.split(_T(' '), vec);
	MojTestErrCheck(err);
	MojTestAssert(vec.size() == 3);
	MojTestAssert(vec[0] == _T("hi"));
	MojTestAssert(vec[1] == _T("there"));
	MojTestAssert(vec[2] == _T("!"));
	err = str1.assign(_T("     "));
	MojTestErrCheck(err);
	err = str1.split(_T(' '), vec);
	MojTestErrCheck(err);
	MojTestAssert(vec.empty());
	err = str1.assign(_T("howdy"));
	MojTestErrCheck(err);
	err = str1.split(_T(' '), vec);
	MojTestErrCheck(err);
	MojTestAssert(vec.size() == 1);
	MojTestAssert(vec[0] == _T("howdy"));
	err = str1.assign(_T("a b"));
	MojTestErrCheck(err);
	err = str1.split(_T(' '), vec);
	MojTestErrCheck(err);
	MojTestAssert(vec.size() == 2);
	MojTestAssert(vec[0] == _T("a"));
	MojTestAssert(vec[1] == _T("b"));

	// ref counting
	err = str1.assign(chars1);
	MojTestErrCheck(err);
	str2 = str1;
	MojTestAssert(str1.data() == str2.data());
	err = str2.assign(chars2);
	MojTestErrCheck(err);
	MojTestAssert(str1.data() != str2.data());
	str1.swap(str2);
	MojTestAssert(str1 == chars2);
	MojTestAssert(str2 == chars1);

	// format
	err = str1.format(_T("hello %s %d"), _T("world"), 14);
	MojTestErrCheck(err);
	MojTestAssert(str1 == _T("hello world 14"));
	MojTestAssert(str1.length() == 14);
	MojTestAssert(str1.first() == _T('h') && str1.last() == _T('4'));
	bigFormatStr.reset(new MojChar[10003]);
	MojAllocCheck(bigFormatStr.get());
	MojStrCpy(bigFormatStr.get(), _T("%s"));
	for (int i = 2; i < 10002; i++)
		bigFormatStr.get()[i] = _T('f');
	bigFormatStr.get()[10002] = _T('\0');
	err = str1.format(bigFormatStr.get(), _T("hi"));
	MojTestErrCheck(err);
	MojTestAssert(str1.length() == 10002);
	MojTestAssert(str1.at(0) == _T('h') && str1.at(1) == _T('i'));
	for (int i = 2; i < 10002; ++i)
		MojTestAssert(str1.at(i) == _T('f'));

	// append
	str1.clear();
	for (int i = 0; i < 1000; ++i) {
		err = str1.append(_T('a'));
		MojTestErrCheck(err);
		MojTestAssert(str1.at(i) == _T('a'));
	}
	MojTestAssert(str1.length() == 1000);
	str1.clear();
	err = str1.append(_T("hello"));
	MojTestErrCheck(err);
	MojTestAssert(str1 == _T("hello"));
	err = str1.append(_T('!'));
	MojTestErrCheck(err);
	MojTestAssert(str1 == _T("hello!"));
	err = str1.appendFormat(_T(" %s"), _T("world"));
	MojTestErrCheck(err);
	MojTestAssert(str1 == _T("hello! world"));
	err = str1.append(_T('!'));
	MojTestErrCheck(err);
	MojTestAssert(str1 == _T("hello! world!"));

	// truncate
	err = str1.truncate(1000);
	MojTestErrCheck(err);
	MojTestAssert(str1 == _T("hello! world!"));
	err = str1.truncate(5);
	MojTestErrCheck(err);
	MojTestAssert(str1 == _T("hello"));
	err = str1.truncate(0);
	MojTestErrCheck(err);
	MojTestAssert(str1 == _T(""));

	// reserve
	MojTestAssert(str5.capacity() == 0);
	err = str5.reserve(0);
	MojTestErrCheck(err);
	MojTestAssert(str5.capacity() == 0);
	err = str5.reserve(5);
	MojTestErrCheck(err);
	MojTestAssert(str5.capacity() == 5);
	err = str5.reserve(1);
	MojTestErrCheck(err);
	MojTestAssert(str5.capacity() == 5);
	err = str5.assign(_T("hello"));
	MojTestErrCheck(err);
	err = str5.reserve(1000);
	MojTestErrCheck(err);
	MojTestAssert(str5.capacity() == 1000);
	MojTestAssert(str5 == _T("hello"));

	// resize
	err = str1.assign(_T("hello"));
	MojTestErrCheck(err);
	err = str1.resize(4);
	MojTestErrCheck(err);
	MojTestAssert(str1.length() == 4);
	MojTestAssert(str1 == _T("hell"));
	err = str1.resize(100);
	MojTestErrCheck(err);
	MojTestAssert(str1.length() == 100);
	err = str1.resize(1);
	MojTestAssert(str1.length() == 1);
	MojTestAssert(str1 == _T("h"));
	err = str1.resize(0);
	MojTestErrCheck(err);
	MojTestAssert(str1.empty());

	// ref-count
	err = str1.assign(_T("hello"));
	MojTestErrCheck(err);
	str2 = str1;
	err = str1.setAt(0, _T('H'));
	MojTestErrCheck(err);
	MojTestAssert(str1 == _T("Hello"));
	MojTestAssert(str2 == _T("hello"));
	str2 = str1;
	err = str1.format(_T("%d"), 52);
	MojTestErrCheck(err);
	MojTestAssert(str1 == _T("52"));
	MojTestAssert(str2 == _T("Hello"));
	str2 = str1;
	err = str1.append(_T('0'));
	MojTestErrCheck(err);
	MojTestAssert(str1 == _T("520"));
	MojTestAssert(str2 == _T("52"));
	str2 = str1;
	err = str1.append(_T("1"));
	MojTestErrCheck(err);
	MojTestAssert(str1 == _T("5201"));
	MojTestAssert(str2 == _T("520"));
	str2 = str1;
	err = str1.appendFormat(_T("%d"), 89);
	MojTestErrCheck(err);
	MojTestAssert(str1 == _T("520189"));
	MojTestAssert(str2 == _T("5201"));
	str2 = str1;
	err = str1.reserve(1000);
	MojTestErrCheck(err);
	MojTestAssert(str1 == _T("520189"));
	MojTestAssert(str2 == _T("520189"));
	str2 = str1;
	err = str1.truncate(2);
	MojTestErrCheck(err);
	MojTestAssert(str1 == _T("52"));
	MojTestAssert(str2 == _T("520189"));

	// base64
	MojVector<MojByte> bv;
	str1.clear();
	err = str1.base64Encode(bv);
	MojTestErrCheck(err);
	MojTestAssert(str1.empty());
	err = str1.base64Decode(bv);
	MojTestErrCheck(err);
	MojTestAssert(bv.empty());
	MojByte input[] = {0x14, 0xfb, 0x9c, 0x03, 0xd9};
	err = bv.assign(input, input + sizeof(input));
	MojTestErrCheck(err);
	err = str1.base64Encode(bv);
	MojTestErrCheck(err);
	MojTestAssert(str1 == _T("4EiR+xZ="));
	MojVector<MojByte> bv2;
	err = str1.base64Decode(bv2);
	MojTestErrCheck(err);
	MojTestAssert(bv == bv2);
	err = str1.base64Encode(bv, false);
	MojTestErrCheck(err);
	MojTestAssert(str1 == _T("4EiR+xZ"));
	err = str1.base64Decode(bv2);
	MojTestErrCheck(err);
	MojTestAssert(bv == bv2);

	// tolower
	str1.clear();
	err = str1.toLower();
	MojTestErrCheck(err);
	MojTestAssert(str1.empty());
	MojTestAssert(str1 == _T(""));
	err = str1.assign(_T("HeLlO"));
	MojTestErrCheck(err);
	err = str1.toLower();
	MojTestErrCheck(err);
	MojTestAssert(str1 == _T("hello"));
	err = str1.assign(_T("AnOtHER"));
	MojErrCheck(err);
	err = str1.toLower();
	MojErrCheck(err);
	MojTestAssert(str1 == _T("another"));

	return MojErrNone;
}
Esempio n. 9
0
MojErr MojDb::dump(const MojChar* path, MojUInt32& countOut, bool incDel, MojDbReqRef req, bool backup,
		MojUInt32 maxBytes, const MojObject* incrementalKey, MojObject* backupResponse)
{
	MojAssert(path);
	MojLogTrace(s_log);

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

	if (!req->admin()) {
		MojLogError(s_log, _T("access denied: '%s' cannot dump db to path: '%s'"), req->domain().data(), path);
		MojErrThrow(MojErrDbAccessDenied);
	}

	MojFile file;
	err = file.open(path, MOJ_O_WRONLY | MOJ_O_CREAT | MOJ_O_TRUNC, MOJ_S_IRUSR | MOJ_S_IWUSR);
	MojErrCheck(err);

	// write out kinds first, then existing objects, then deleted objects
	MojSize bytesWritten = 0;
	MojSize totalwarns = 0;
	MojSize newwarns = 0;
	MojDbQuery objQuery;
	MojVector<MojObject> kindVec;
	MojObject revParam = -1;
	MojObject delRevParam = -1;

	// if we were given an incremental key, pull out the revs now
	if (incrementalKey) {
		incrementalKey->get(MojDbServiceDefs::RevKey, revParam);
		incrementalKey->get(MojDbServiceDefs::DeletedRevKey, delRevParam);
	}

	err = m_kindEngine.getKinds(kindVec);
	MojErrCheck(err);

	// write kinds - if incremental, only write the kinds that have changed since the respective revs
	MojString countStr;
	for (MojVector<MojObject>::ConstIterator i = kindVec.begin(); i != kindVec.end(); ++i) {
		if (backup) {
			bool backupKind = false;
			i->get(MojDbKind::SyncKey, backupKind);
			if (!backupKind)
				continue;
			MojString id;
			err = i->getRequired(MojDbServiceDefs::IdKey, id);
			MojErrCheck(err);
			MojDbQuery countQuery;
			err = countQuery.from(id);
			MojErrCheck(err);
			MojDbCursor cursor;
			err = find(countQuery, cursor, req);
			MojErrCheck(err);
			MojUInt32 count = 0;
			err = cursor.count(count);
			MojErrCheck(err);
			if (count > 0) {
				if (i != kindVec.begin()) {
					err = countStr.appendFormat(_T(", "));
					MojErrCheck(err);
				}
				err = countStr.appendFormat("%s=%u", id.data(), count);
				MojErrCheck(err);
			}
		}
		bool deleted = false;
		i->get(DelKey, deleted);
		MojObject kindRev;
		err = i->getRequired(RevKey, kindRev);
		MojErrCheck(err);
		if ((deleted && kindRev > delRevParam) || (!deleted && kindRev > revParam)) {
			err = dumpObj(file, (*i), bytesWritten, maxBytes);
			MojErrCheck(err);
			countOut++;
		}
	}

	// dump all the non-deleted objects
	err = dumpImpl(file, backup, false, revParam, delRevParam, true, countOut, req, backupResponse, MojDbServiceDefs::RevKey, bytesWritten, newwarns, maxBytes);
	MojErrCheck(err);
	totalwarns += newwarns;
	// If we're supposed to include deleted objects, dump the deleted objects now.
	// There's a chance that we may have run out of space in our backup.  If that's the case,
	// we don't want to try to dump deleted objects - we can detect this by looking for the HasMoreKey
	if (incDel && backupResponse && !backupResponse->contains(MojDbServiceDefs::HasMoreKey)) {
		err = dumpImpl(file, backup, true, revParam, delRevParam, false, countOut, req, backupResponse, MojDbServiceDefs::DeletedRevKey, bytesWritten, newwarns, maxBytes);
		MojErrCheck(err);
	}
	totalwarns += newwarns;

	// Add the Full and Version keys
	if (backup && backupResponse) {
		bool incremental = (incrementalKey != NULL);
		err = backupResponse->putBool(MojDbServiceDefs::FullKey, !incremental);
		MojErrCheck(err);
		err = backupResponse->put(MojDbServiceDefs::VersionKey, DatabaseVersion);
		MojErrCheck(err);
		err = backupResponse->put(MojDbServiceDefs::WarningsKey, (MojInt32)totalwarns);
		MojErrCheck(err);
		MojString description;
		err = description.format(_T("incremental=%u"), countOut);
		MojErrCheck(err);
		if (!countStr.empty()) {
			err = description.appendFormat(_T(", %s"), countStr.data());
			MojErrCheck(err);
		}
		err = backupResponse->put(_T("description"), description);
		MojErrCheck(err);
	}

	err = req->end();
	MojErrCheck(err);

	return MojErrNone;
}