Esempio n. 1
0
int SLNSessionGetValueForField(SLNSessionRef const session, str_t value[], size_t const max, strarg_t const fileURI, strarg_t const field) {
	if(!SLNSessionHasPermission(session, SLN_RDONLY)) return DB_EACCES;
	if(!field) return DB_EINVAL;

	if(max) value[0] = '\0';
	int rc = 0;
	DB_cursor *metafiles = NULL;
	DB_cursor *values = NULL;

	SLNRepoRef const repo = SLNSessionGetRepo(session);
	DB_env *db = NULL;
	SLNRepoDBOpen(repo, &db);
	DB_txn *txn = NULL;
	rc = db_txn_begin(db, NULL, DB_RDONLY, &txn);
	if(rc < 0) goto done;

	rc = db_cursor_open(txn, &metafiles);
	if(rc < 0) goto done;
	rc = db_cursor_open(txn, &values);
	if(rc < 0) goto done;

	DB_range metaFileIDs[1];
	SLNTargetURIAndMetaFileIDRange1(metaFileIDs, txn, fileURI);
	DB_val metaFileID_key[1];
	rc = db_cursor_firstr(metafiles, metaFileIDs, metaFileID_key, NULL, +1);
	if(rc < 0 && DB_NOTFOUND != rc) goto done;
	for(; rc >= 0; rc = db_cursor_nextr(metafiles, metaFileIDs, metaFileID_key, NULL, +1)) {
		strarg_t u;
		uint64_t metaFileID;
		SLNTargetURIAndMetaFileIDKeyUnpack(metaFileID_key, txn, &u, &metaFileID);
		assert(0 == strcmp(fileURI, u));
		DB_range vrange[1];
		SLNMetaFileIDFieldAndValueRange2(vrange, txn, metaFileID, field);
		DB_val value_val[1];
		rc = db_cursor_firstr(values, vrange, value_val, NULL, +1);
		if(rc < 0 && DB_NOTFOUND != rc) goto done;
		for(; rc >= 0; rc = db_cursor_nextr(values, vrange, value_val, NULL, +1)) {
			uint64_t m;
			strarg_t f, v;
			SLNMetaFileIDFieldAndValueKeyUnpack(value_val, txn, &m, &f, &v);
			assert(metaFileID == m);
			assert(0 == strcmp(field, f));
			if(!v) continue;
			if(0 == strcmp("", v)) continue;
			size_t const len = strlen(v);
			memcpy(value, v, MIN(len, max-1));
			value[MIN(len, max-1)] = '\0';
			goto done;
		}
	}

done:
	db_cursor_close(values); values = NULL;
	db_cursor_close(metafiles); metafiles = NULL;

	db_txn_abort(txn); txn = NULL;
	SLNRepoDBClose(repo, &db);
	return rc;
}
Esempio n. 2
0
int SLNSessionGetValueForField(SLNSessionRef const session, DB_txn *const txn, strarg_t const fileURI, strarg_t const field, str_t *out, size_t const max) {
	int rc = 0;
	DB_cursor *metafiles = NULL;
	DB_cursor *values = NULL;

	rc = db_cursor_open(txn, &metafiles);
	if(rc < 0) goto done;
	rc = db_cursor_open(txn, &values);
	if(rc < 0) goto done;

	DB_range metaFileIDs[1];
	SLNTargetURIAndMetaFileIDRange1(metaFileIDs, txn, fileURI);
	DB_val metaFileID_key[1];
	rc = db_cursor_firstr(metafiles, metaFileIDs, metaFileID_key, NULL, +1);
	if(rc < 0 && DB_NOTFOUND != rc) goto done;
	for(; rc >= 0; rc = db_cursor_nextr(metafiles, metaFileIDs, metaFileID_key, NULL, +1)) {
		strarg_t u;
		uint64_t metaFileID;
		SLNTargetURIAndMetaFileIDKeyUnpack(metaFileID_key, txn, &u, &metaFileID);
		assert(0 == strcmp(fileURI, u));
		DB_range vrange[1];
		SLNMetaFileIDFieldAndValueRange2(vrange, txn, metaFileID, field);
		DB_val value_val[1];
		rc = db_cursor_firstr(values, vrange, value_val, NULL, +1);
		if(rc < 0 && DB_NOTFOUND != rc) goto done;
		for(; rc >= 0; rc = db_cursor_nextr(values, vrange, value_val, NULL, +1)) {
			uint64_t m;
			strarg_t f, v;
			SLNMetaFileIDFieldAndValueKeyUnpack(value_val, txn, &m, &f, &v);
			assert(metaFileID == m);
			assert(0 == strcmp(field, f));
			if(!v || '\0' == v[0]) continue;
			strlcpy(out, v, max);
			goto done;
		}
	}

done:
	db_cursor_close(values); values = NULL;
	db_cursor_close(metafiles); metafiles = NULL;
	return rc;
}
Esempio n. 3
0
int SLNSessionGetNextMetaMapURI(SLNSessionRef const session, strarg_t const targetURI, uint64_t *const metaMapID, str_t *out, size_t const max) {
	// TODO: We should handle URI synonyms.
	// That might mean accepting a fileID instead of targetURI...

	assert(metaMapID);
	assert(out);

	uint64_t const sessionID = SLNSessionGetID(session);
	DB_env *db = NULL;
	DB_txn *txn = NULL;
	DB_cursor *cursor = NULL;
	int rc = 0;
	size_t count = 0;

	rc = SLNSessionDBOpen(session, SLN_RDONLY, &db);
	if(rc < 0) goto cleanup;
	rc = db_txn_begin(db, NULL, DB_RDONLY, &txn);
	if(rc < 0) goto cleanup;

	rc = db_cursor_open(txn, &cursor);
	if(rc < 0) goto cleanup;

	DB_range range[1];
	DB_val key[1];
	SLNTargetURISessionIDAndMetaMapIDRange2(range, txn, targetURI, sessionID);
	SLNTargetURISessionIDAndMetaMapIDKeyPack(key, txn, targetURI, sessionID, *metaMapID);
	rc = db_cursor_seekr(cursor, range, key, NULL, +1);
	if(rc < 0) goto cleanup;

	strarg_t u;
	uint64_t s;
	SLNTargetURISessionIDAndMetaMapIDKeyUnpack(key, txn, &u, &s, metaMapID);

	DB_val row[1], val[1];
	SLNSessionIDAndMetaMapIDToMetaURIAndTargetURIKeyPack(row, txn, sessionID, *metaMapID);
	rc = db_get(txn, row, val);
	if(rc < 0) goto cleanup;

	strarg_t metaURI, t;
	SLNSessionIDAndMetaMapIDToMetaURIAndTargetURIValUnpack(val, txn, &metaURI, &t);
	db_assert(metaURI);

	strlcpy(out, metaURI, max); // TODO: Handle err

cleanup:
	db_cursor_close(cursor); cursor = NULL;
	db_txn_abort(txn); txn = NULL;
	SLNSessionDBClose(session, &db);
	if(rc < 0) return rc;
	return count;
}
Esempio n. 4
0
static void add_fulltext(DB_txn *const txn, uint64_t const metaFileID, strarg_t const str, size_t const len) {
	if(0 == len) return;
	assert(str);

	int rc;

	sqlite3_tokenizer_module const *fts = NULL;
	sqlite3_tokenizer *tokenizer = NULL;
	fts_get(&fts, &tokenizer);

	sqlite3_tokenizer_cursor *tcur = NULL;
	rc = fts->xOpen(tokenizer, str, len, &tcur);
	assert(SQLITE_OK == rc);

	DB_cursor *cursor = NULL;
	rc = db_cursor_open(txn, &cursor);
	assert(rc >= 0);

	for(;;) {
		strarg_t token;
		int tlen;
		int tpos; // TODO
		int ignored1, ignored2;
		rc = fts->xNext(tcur, &token, &tlen, &ignored1, &ignored2, &tpos);
		if(SQLITE_OK != rc) break;

		assert('\0' == token[tlen]); // Assumption
		DB_val token_val[1];
		SLNTermMetaFileIDAndPositionKeyPack(token_val, txn, token, metaFileID, 0);
		// TODO: Record tpos. Requires changes to SLNFulltextFilter so that each document only gets returned once, no matter how many times the token appears within it.
		DB_val null = { 0, NULL };
		rc = db_cursor_put(cursor, token_val, &null, DB_NOOVERWRITE_FAST);
		assert(rc >= 0 || DB_KEYEXIST == rc);
	}

	db_cursor_close(cursor); cursor = NULL;

	fts->xClose(tcur); tcur = NULL;
}