Exemple #1
0
MojErr MojDbQuery::updateClause(WhereClause& clause, CompOp op, const MojObject& val, MojDbCollationStrength coll)
{
	// the only case where we can have two ops for the same prop is a combination
	// of '<' or '<=' with '>' or '>='
	switch (op) {
	case OpLessThan:
	case OpLessThanEq: {
		CompOp lowerOp = clause.lowerOp();
		if (lowerOp != OpNone && lowerOp != OpGreaterThan && lowerOp != OpGreaterThanEq)
			MojErrThrow(MojErrDbInvalidQueryOpCombo);
		MojErr err = clause.setUpper(op, val, coll);
		MojErrCheck(err);
		break;
	}
	case OpGreaterThan:
	case OpGreaterThanEq: {
		CompOp upperOp = clause.upperOp();
		if (upperOp != OpNone && upperOp != OpLessThan && upperOp != OpLessThanEq)
			MojErrThrow(MojErrDbInvalidQueryOpCombo);
		MojErr err = clause.setLower(op, val, coll);
		MojErrCheck(err);
		break;
	}
	default:
		// all other ops invalid in combination
		MojErrThrow(MojErrDbInvalidQueryOpCombo);
	}
	return MojErrNone;
}
MojErr MojDbServiceHandler::handleBatch(MojServiceMessage* msg, MojObject& payload, MojDbReq& req)
{
	MojAssert(msg);
	MojLogTrace(s_log);

	MojObject operations;
	MojErr err = payload.getRequired(MojDbServiceDefs::OperationsKey, operations);
	MojErrCheck(err);
	MojObject::ArrayIterator begin;
	err = operations.arrayBegin(begin);
	MojErrCheck(err);

	//start the response array
	MojObjectVisitor& writer = msg->writer();
	err = writer.beginObject();
	MojErrCheck(err);
	err = writer.boolProp(MojServiceMessage::ReturnValueKey, true);
	MojErrCheck(err);
	err = writer.propName(MojDbServiceDefs::ResponsesKey);
	MojErrCheck(err);
	err = writer.beginArray();
	MojErrCheck(err);

	for (MojObject* i = begin; i != operations.arrayEnd(); ++i) {
		MojString method;
		err = i->getRequired(MojDbServiceDefs::MethodKey, method);
		MojErrCheck(err);
		MojObject params;
		err = i->getRequired(MojDbServiceDefs::ParamsKey, params);
		MojErrCheck(err);
		// not allowed to specify watch key in a batch
		bool watchValue = false;
		if (payload.get(MojDbServiceDefs::WatchKey, watchValue) && watchValue) {
			MojErrThrow(MojErrDbInvalidBatch);
		}
		DbCallback cb;
		if (!m_batchCallbacks.get(method, cb)) {
			MojErrThrow(MojErrDbInvalidBatch);
		}
		err = (this->*cb)(msg, params, req);
		MojErrCheck(err);
	}

	err = writer.endArray();
	MojErrCheck(err);
	err = writer.endObject();
	MojErrCheck(err);

	return MojErrNone;
}
Exemple #3
0
MojErr MojDbQuery::appendClause(MojObjectVisitor& visitor, const MojChar* propName, CompOp op,
 							   const MojObject& val, MojDbCollationStrength coll)
{
	MojAssert(propName);

	MojErr err = visitor.beginObject();
	MojErrCheck(err);

	err = visitor.stringProp(PropKey, propName);
	MojErrCheck(err);
	const MojChar* opStr = opToString(op);
	if (!opStr) {
		MojErrThrow(MojErrDbInvalidQueryOp);
	}
	err = visitor.stringProp(OpKey, opStr);
	MojErrCheck(err);
	err = visitor.objectProp(ValKey, val);
	MojErrCheck(err);
	if (coll != MojDbCollationInvalid) {
		err = visitor.stringProp(CollateKey, MojDbUtils::collationToString(coll));
		MojErrCheck(err);
	}
	err = visitor.endObject();
	MojErrCheck(err);

	return MojErrNone;
}
Exemple #4
0
MojErr MojDbPropExtractor::fromObjectImpl(const MojObject& obj, const MojDbPropExtractor& defaultConfig, const MojChar* locale)
{
    LOG_TRACE("Entering function %s", __FUNCTION__);

	// super
	MojErr err = MojDbExtractor::fromObject(obj, locale);
	MojErrCheck(err);

	// default value
	m_default = defaultConfig.m_default;
	MojObject defaultVal;
	if (obj.get(DefaultKey, defaultVal)) {
		MojObject::Type type = defaultVal.type();
		MojDbKey key;
		if (type == MojObject::TypeArray) {
			// if the value is an array, act on its elements rather than the array object itself
			MojObject::ConstArrayIterator end = defaultVal.arrayEnd();
			for (MojObject::ConstArrayIterator j = defaultVal.arrayBegin(); j != end; ++j) {
				err = key.assign(*j);
				MojErrCheck(err);
				err = m_default.put(key);
				MojErrCheck(err);
			}
		} else {
			err = key.assign(defaultVal);
			MojErrCheck(err);
			err = m_default.put(key);
			MojErrCheck(err);
		}
	}

	// tokenizer
	m_tokenizer = defaultConfig.m_tokenizer;
	MojString tokenize;
	bool found = false;
	err = obj.get(TokenizeKey, tokenize, found);
	MojErrCheck(err);
	if (found) {
		if (tokenize == AllKey || tokenize == DefaultKey) {
			m_tokenizer.reset(new MojDbTextTokenizer);
			MojAllocCheck(m_tokenizer.get());
			err = m_tokenizer->init(locale);
			MojErrCheck(err);
		} else {
			MojErrThrow(MojErrDbInvalidTokenization);
		}
	}

	// collator
	if (m_collation == MojDbCollationInvalid)
		m_collation = defaultConfig.m_collation;
	err = updateLocale(locale);
	MojErrCheck(err);

	// set prop
	err = prop(m_name);
	MojErrCheck(err);

	return MojErrNone;
}
Exemple #5
0
MojErr MojService::CategoryHandler::invoke(const MojChar* method, MojServiceMessage* msg, MojObject& payload)
{
	MojAssert(method && msg);
	MojLogTrace(s_log);

	MojTime startTime;
	MojErr err = MojGetCurrentTime(startTime);
	MojErrCheck(err);

	// lookup callback
	CallbackInfo cb;
	if (!m_callbackMap.get(method, cb)) {
		MojErrThrow(MojErrMethodNotFound);
	}
	// validate schema
	if (cb.m_schema.get()) {
		MojSchema::Result res;
		err = cb.m_schema->validate(payload, res);
		MojErrCheck(err);
		if (!res.valid()) {
			MojErrThrowMsg(MojErrInvalidArg, _T("invalid parameters: caller='%s' error='%s'"), msg->senderName(), res.msg().data());
		}
	}
	// invoke method
	err = invoke(cb.m_callback, msg, payload);
	MojErrCheck(err);

	// log timing
	MojTime endTime;
	err = MojGetCurrentTime(endTime);
	MojErrCheck(err);
	MojLogInfo(s_log, _T("%s invoked: %.3fms"), method, (double) (endTime.microsecs() - startTime.microsecs()) / 1000);

	return MojErrNone;
}
Exemple #6
0
MojErr MojDbLevelIndex::del(const MojDbKey& key, MojDbStorageTxn* txn)
{
    LOG_TRACE("Entering function %s", __FUNCTION__);
    MojAssert(txn);
    MojAssert(isOpen());

    MojDbLevelItem keyItem;
    keyItem.fromBytesNoCopy(key.data(), key.size());

    bool found = false;
    MojErr err = m_db->del(keyItem, found, txn);

#ifdef MOJ_DEBUG
    char s[1024];
    size_t size1 = keyItem.size();
    MojErr err2 = MojByteArrayToHex(keyItem.data(), size1, s);
    MojErrCheck(err2);
    if (size1 > 16) // if the object-id is in key
        strncat(s, (char *)(keyItem.data()) + (size1 - 17), 16);
    LOG_DEBUG("[db_ldb] ldbindexdel: %s; keylen: %zu, key: %s ; err = %d\n", m_db->m_name.data(), size1, s, err);
    if (!found)
        LOG_WARNING(MSGID_LEVEL_DB_WARNING, 1,
            PMLOGKS("index", s),
            "ldbindexdel_warn: not found: %s \n", s);
#endif

    MojErrCheck(err);
    if (!found) {
        //MojErrThrow(MojErrDbInconsistentIndex);   // fix this to work around to deal with out of sync indexes
        MojErrThrow(MojErrInternalIndexOnDel);
    }
    return MojErrNone;
}
Exemple #7
0
MojErr MojDb::updateLocale(const MojChar* locale, MojDbReqRef req)
{
	MojAssert(locale);
	MojLogTrace(s_log);

	MojErr err = beginReq(req, true);
	MojErrCheck(err);
	MojString oldLocale;
	err = getLocale(oldLocale, req);
	MojErrCheck(err);
	MojString newLocale;
	err = newLocale.assign(locale);
	MojErrCheck(err);
	MojErr updateErr = err = updateLocaleImpl(oldLocale, newLocale, req);
	MojErrCatchAll(err) {
		err = req->abort();
		MojErrCheck(err);
		err = m_kindEngine.close();
		MojErrCheck(err);
		MojDbReq openReq;
		err = beginReq(openReq, true);
		MojErrCheck(err);
		err = m_kindEngine.open(this, openReq);
		MojErrCheck(err);
		err = openReq.end();
		MojErrCheck(err);
		MojErrThrow(updateErr);
	}
	return MojErrNone;
}
Exemple #8
0
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;
}
Exemple #9
0
MojErr MojSocketMessageHeader::read(MojDataReader& reader)
{
	MojErr err = reader.readUInt32(m_version);
	MojErrCheck(err);

	if (m_version != s_protocolVersion) {
		MojErrThrow(MojErrInvalidMsg);
	}

	err = reader.readUInt32(m_messageLen);
	MojErrCheck(err);
	if (m_messageLen > s_maxMsgSize || m_messageLen <= 0) {
		MojErrThrow(MojErrInvalidMsg);
	}

	return MojErrNone;
}
Exemple #10
0
MojErr MojDbQuery::WhereClause::collation(MojDbCollationStrength collation)
{
	if (m_collation != MojDbCollationInvalid && collation != m_collation)
		MojErrThrow(MojErrDbInvalidQueryCollationMismatch);
	m_collation = collation;

	return MojErrNone;
}
MojErr MojDbQuotaEngine::Offset::apply(MojInt64 offset)
{
	MojInt64 newOffset = m_offset + offset;
	if (m_quota.get() && newOffset > m_quota->available())
		MojErrThrow(MojErrDbQuotaExceeded);
	m_offset = newOffset;

	return MojErrNone;
}
Exemple #12
0
MojErr MojDbKind::deny(MojDbReq& req)
{
	MojLogWarning(s_log, _T("db: permission denied for caller '%s' on kind '%s'"), req.domain().data(), m_id.data());
	if (m_kindEngine->permissionEngine()->enabled()) {
		// don't leak any information in an error message
		MojErrThrow(MojErrDbPermissionDenied);
	}
	return MojErrNone;
}
Exemple #13
0
MojErr MojDbKindEngine::idFromToken(MojInt64 tok, MojString& idOut)
{
	TokMap::ConstIterator i = m_tokens.find(tok);
	if (i == m_tokens.end())
		MojErrThrow(MojErrDbInvalidKindToken);
	idOut = i.value();

	return MojErrNone;
}
Exemple #14
0
MojErr MojVPrintF(const MojChar* format, va_list args)
{
	MojAssert(format);

	int res = vprintf(format, args);
	if (res < 0)
		MojErrThrow(MojErrFormat);

	return MojErrNone;
}
Exemple #15
0
MojErr MojDbQuery::stringToOp(const MojChar* str, CompOp& opOut)
{
	for (const StrOp* op = s_ops; op->m_str != NULL; ++op) {
		if (MojStrCmp(op->m_str, str) == 0) {
			opOut = op->m_op;
			return MojErrNone;
		}
	}
	MojErrThrow(MojErrDbInvalidQueryOp);
}
Exemple #16
0
	virtual MojErr del(const MojDbKey& key, MojDbStorageTxn* txn)
	{
		bool found = false;
		MojErr err = m_set.del(key, found);
		MojErrCheck(err);
		if (!found)
			MojErrThrow(MojErrNotFound);
		++m_delCount;
		return MojErrNone;
	}
Exemple #17
0
MojErr MojDbQuotaEngine::Offset::apply(MojInt64 offset)
{
    LOG_TRACE("Entering function %s", __FUNCTION__);

	MojInt64 newOffset = m_offset + offset;
	if (m_quota.get() && newOffset > m_quota->available())
		MojErrThrow(MojErrDbQuotaExceeded);
	m_offset = newOffset;

	return MojErrNone;
}
Exemple #18
0
MojErr MojService::getRequest(MojServiceMessage* msg, MojRefCountedPtr<MojServiceRequest>& reqOut)
{
	MojAssert(msg);
	MojAssertMutexUnlocked(m_mutex);
	MojLogTrace(s_log);
	MojThreadGuard guard(m_mutex);

	if (!m_requests.get(msg->token(), reqOut)) {
		MojErrThrow(MojErrResponseHandlerNotFound);
	}
	return MojErrNone;
}
Exemple #19
0
MojErr MojDb::findImpl(const MojDbQuery& query, MojDbCursor& cursor, MojDbWatcher* watcher, MojDbReq& req, MojDbOp op)
{
	MojLogTrace(s_log);

	if (cursor.isOpen())
		MojErrThrow(MojErrDbCursorAlreadyOpen);

	MojErr err = m_kindEngine.find(query, cursor, watcher, req, op);
	MojErrCheck(err);

	return MojErrNone;
}
Exemple #20
0
MojErr MojService::getCategory(const MojChar* name, MojRefCountedPtr<Category>& catOut)
{
	MojAssert(name);
	MojAssertMutexUnlocked(m_mutex);
	MojLogTrace(s_log);
	MojThreadGuard guard(m_mutex);

	if (!m_categories.get(name, catOut)) {
		MojErrThrow(MojErrCategoryNotFound);
	}
	return MojErrNone;
}
MojErr MojDbQuotaEngine::quotaUsage(const MojChar* owner, MojInt64& sizeOut, MojInt64& usageOut)
{
	sizeOut = 0;
	usageOut = 0;
	QuotaMap::ConstIterator iter = m_quotas.find(owner);
	if (iter == m_quotas.end()) {
		MojErrThrow(MojErrNotFound);
	}
	sizeOut = iter.value()->size();
	usageOut = iter.value()->usage();

	return MojErrNone;
}
Exemple #22
0
MojErr MojDbQuery::WhereClause::setUpper(CompOp op, const MojObject& val, MojDbCollationStrength coll)
{
	if (m_upperOp != OpNone)
		MojErrThrow(MojErrDbInvalidQueryOpCombo);

	MojErr err = collation(coll);
	MojErrCheck(err);

	m_upperOp = op;
	m_upperVal = val;

	return MojErrNone;
}
Exemple #23
0
MojErr MojDbKindState::initTokens(MojDbReq& req, const StringSet& strings)
{
	// TODO: bug inside this function. (latest strace step)
	MojAssertMutexLocked(m_lock);

	// TODO: filing load tokens. Go inside readObj
	// load tokens
	MojErr err = readObj(TokensKey, m_tokensObj, m_kindEngine->kindDb(), req.txn(), m_oldTokensItem);
	MojErrCheck(err);

	// populate token vec
	MojUInt8 maxToken = 0;
	err = m_tokenVec.resize(m_tokensObj.size());
	MojErrCheck(err);
	for (MojObject::ConstIterator i = m_tokensObj.begin(); i != m_tokensObj.end(); ++i) {
		MojString key = i.key();
		MojInt64 value = i.value().intValue();
		MojSize idx = (MojSize) (value - MojObjectWriter::TokenStartMarker);
		if (value < MojObjectWriter::TokenStartMarker || value >= MojUInt8Max || idx >= m_tokenVec.size()) {
			MojErrThrow(MojErrDbInvalidToken);
		}
		if (value > maxToken) {
			maxToken = (MojUInt8) value;
		}
		err = m_tokenVec.setAt(idx, key);
		MojErrCheck(err);
	}
	if (maxToken > 0) {
		m_nextToken = (MojUInt8) (maxToken + 1);
	}

	// add strings
	bool updated = false;
	for (StringSet::ConstIterator i = strings.begin(); i != strings.end(); ++i) {
		if (!m_tokensObj.contains(*i)) {
			updated = true;
			MojUInt8 token = 0;
			TokenVec tokenVec;
			MojObject tokenObj;
			err = addPropImpl(*i, false, token, tokenVec, tokenObj);
			MojErrCheck(err);
		}
	}
	if (updated) {
		err = writeTokens(m_tokensObj);
		MojErrCheck(err);
	}
	return MojErrNone;
}
Exemple #24
0
MojErr MojDbKind::init(const MojString& id)
{
	MojLogTrace(s_log);

	// parse name and version out of id
	if (id.length() > KindIdLenMax)
		MojErrThrowMsg(MojErrDbMalformedId, _T("db: kind id too long"));
	MojSize sepIdx = id.rfind(VersionSeparator);
	if (sepIdx == MojInvalidIndex)
		MojErrThrow(MojErrDbMalformedId);
	MojErr err = id.substring(0, sepIdx, m_name);
	MojErrCheck(err);
	MojString str;
	err = id.substring(sepIdx + 1, id.length() - sepIdx - 1, str);
	MojErrCheck(err);
	const MojChar* end = NULL;
	MojInt64 ver = MojStrToInt64(str.data(), &end, 0);
	if (*end != '\0' || ver < 0 || ver > MojUInt32Max)
		MojErrThrow(MojErrDbMalformedId);
	m_version = (MojUInt32) ver;
	m_id = id;

	return MojErrNone;
}
Exemple #25
0
MojErr MojDbKindEngine::getKind(const MojObject& obj, MojDbKind*& kind)
{
	MojLogTrace(s_log);

	MojString kindName;
	bool found = false;
	MojErr err = obj.get(MojDb::KindKey, kindName, found);
	MojErrCheck(err);
	if (!found)
		MojErrThrow(MojErrDbKindNotSpecified);
	err = getKind(kindName.data(), kind);
	MojErrCheck(err);

	return MojErrNone;
}
Exemple #26
0
MojErr MojDbQuotaEngine::quotaUsage(const MojChar* owner, MojInt64& sizeOut, MojInt64& usageOut)
{
    LOG_TRACE("Entering function %s", __FUNCTION__);

	sizeOut = 0;
	usageOut = 0;
	QuotaMap::ConstIterator iter = m_quotas.find(owner);
	if (iter == m_quotas.end()) {
		MojErrThrow(MojErrNotFound);
	}
	sizeOut = iter.value()->size();
	usageOut = iter.value()->usage();

	return MojErrNone;
}
Exemple #27
0
MojErr MojDbWatcher::handleCancel()
{
	MojThreadGuard guard(m_mutex);

	MojLogDebug(MojDb::s_log, _T("Watcher_handleCancel: state= %d; index name = %s; domain = %s\n"), (int)m_state,
				((m_index) ? m_index->name().data() : NULL), ((m_domain) ? m_domain.data() : NULL));

	if (m_index == NULL)
		MojErrThrow(MojErrDbWatcherNotRegistered);
	if (m_state != StateInvalid) {
		MojErr err = invalidate();
		MojErrCheck(err);
	}
	return MojErrNone;
}
Exemple #28
0
MojErr MojDbPutHandler::validateWildcard(const MojString& val, MojErr errToThrow)
{
    LOG_TRACE("Entering function %s", __FUNCTION__);

    if (val.empty())
        MojErrThrow(errToThrow);
    MojSize wildcardPos = val.find(_T('*'));
    if (wildcardPos != MojInvalidSize) {
        if (wildcardPos != val.length() - 1 ||
                (wildcardPos != 0 && val.at(wildcardPos - 1) != _T('.'))) {
            MojErrThrowMsg(errToThrow, _T("db: invalid wildcard in - '%s'"), val.data());
        }
    }
    return MojErrNone;
}
Exemple #29
0
MojErr MojSockAddr::fromPath(const MojChar* path)
{
    MojAssert(path);

    MojSockAddrUnT addr;
    MojZero(&addr, sizeof(addr));

    if (MojStrLen(path) > (sizeof(addr.sun_path) - 1))
        MojErrThrow(MojErrPathTooLong);
    MojStrCpy(addr.sun_path, path);

    addr.sun_family = MOJ_PF_LOCAL;
    fromAddr((MojSockAddrT*) &addr, sizeof(addr));

    return MojErrNone;
}
Exemple #30
0
MojErr MojDbUtils::collationFromString(const MojString& str, MojDbCollationStrength& collOut)
{
    LOG_TRACE("Entering function %s", __FUNCTION__);

	collOut = MojDbCollationInvalid;
	MojDbCollationStrInfo* info = s_collStrings;
	do {
		collOut = info->m_coll;
		if (str == info->m_str)
			break;
	} while ((info++)->m_coll != MojDbCollationInvalid);

	if (collOut == MojDbCollationInvalid)
		MojErrThrow(MojErrDbInvalidCollation);

	return MojErrNone;
}