コード例 #1
0
ファイル: db_schema.c プロジェクト: nkatsaros/stronglink
int db_schema_verify(DB_txn *const txn) {
	char const magic[] = "DBDB schema layer v1";
	size_t const len = sizeof(magic)-1;

	DB_val key[1];
	DB_VAL_STORAGE(key, DB_VARINT_MAX*2);
	db_bind_uint64(key, DBSchema);
	db_bind_uint64(key, 0);
	DB_val val[1];

	DB_cursor *cur;
	int rc = db_txn_cursor(txn, &cur);
	if(rc < 0) return rc;
	rc = db_cursor_first(cur, NULL, NULL, +1);
	if(rc < 0 && DB_NOTFOUND != rc) return rc;

	// If the database is completely empty
	// we can assume it's ours to play with
	if(DB_NOTFOUND == rc) {
		*val = (DB_val){ len, (char *)magic };
		rc = db_put(txn, key, val, 0);
		if(rc < 0) return rc;
		return 0;
	}

	rc = db_get(txn, key, val);
	if(DB_NOTFOUND == rc) return DB_VERSION_MISMATCH;
	if(rc < 0) return rc;
	if(len != val->size) return DB_VERSION_MISMATCH;
	if(0 != memcmp(val->data, magic, len)) return DB_VERSION_MISMATCH;
	return 0;
}
コード例 #2
0
ファイル: SLNSession.c プロジェクト: seclu/stronglink
int SLNSessionGetFileInfo(SLNSessionRef const session, strarg_t const URI, SLNFileInfo *const info) {
	DB_env *db = NULL;
	int rc = SLNSessionDBOpen(session, SLN_RDONLY, &db);
	if(rc < 0) return rc;
	DB_txn *txn = NULL;
	rc = db_txn_begin(db, NULL, DB_RDONLY, &txn);
	if(rc < 0) {
		SLNSessionDBClose(session, &db);
		return rc;
	}

	DB_cursor *cursor;
	rc = db_txn_cursor(txn, &cursor);
	assert(!rc);

	DB_range fileIDs[1];
	SLNURIAndFileIDRange1(fileIDs, txn, URI);
	DB_val URIAndFileID_key[1];
	rc = db_cursor_firstr(cursor, fileIDs, URIAndFileID_key, NULL, +1);
	DB_val file_val[1];
	if(rc >= 0) {
		strarg_t URI2;
		uint64_t fileID;
		SLNURIAndFileIDKeyUnpack(URIAndFileID_key, txn, &URI2, &fileID);
		assert(0 == strcmp(URI, URI2));
		if(info) {
			DB_val fileID_key[1];
			SLNFileByIDKeyPack(fileID_key, txn, fileID);
			rc = db_get(txn, fileID_key, file_val);
		}
	}
	if(rc < 0) {
		db_txn_abort(txn); txn = NULL;
		SLNSessionDBClose(session, &db);
		return rc;
	}

	if(info) {
		// Clear padding for later assert_zeroed.
		memset(info, 0, sizeof(*info));

		strarg_t const internalHash = db_read_string(file_val, txn);
		strarg_t const type = db_read_string(file_val, txn);
		uint64_t const size = db_read_uint64(file_val);
		info->hash = strdup(internalHash);
		info->path = SLNRepoCopyInternalPath(SLNSessionGetRepo(session), internalHash);
		info->type = strdup(type);
		info->size = size;
		if(!info->hash || !info->path || !info->type) {
			SLNFileInfoCleanup(info);
			db_txn_abort(txn); txn = NULL;
			SLNSessionDBClose(session, &db);
			return DB_ENOMEM;
		}
	}

	db_txn_abort(txn); txn = NULL;
	SLNSessionDBClose(session, &db);
	return 0;
}
コード例 #3
0
ファイル: db_schema.c プロジェクト: nkatsaros/stronglink
uint64_t db_next_id(dbid_t const table, DB_txn *const txn) {
	DB_cursor *cur = NULL;
	if(db_txn_cursor(txn, &cur) < 0) return 0;
	DB_range range[1];
	DB_RANGE_STORAGE(range, DB_VARINT_MAX);
	db_bind_uint64(range->min, table+0);
	db_bind_uint64(range->max, table+1);
	DB_val prev[1];
	int rc = db_cursor_firstr(cur, range, prev, NULL, -1);
	if(DB_NOTFOUND == rc) return 1;
	if(rc < 0) return 0;
	uint64_t const t = db_read_uint64(prev);
	assert(table == t);
	return db_read_uint64(prev)+1;
}
コード例 #4
0
ファイル: SLNFilterExt.c プロジェクト: sofian86/stronglink
int SLNFilterSeekToPosition(SLNFilterRef const filter, SLNFilterPosition const *const pos, DB_txn *const txn) {
	if(!pos->URI) {
		SLNFilterSeek(filter, pos->dir, pos->sortID, pos->fileID);
		if(valid(pos->fileID)) SLNFilterStep(filter, pos->dir);
		return 0;
	}

	DB_cursor *cursor = NULL;
	int rc = db_txn_cursor(txn, &cursor);
	if(rc < 0) return rc;

	DB_range range[1];
	DB_val key[1];
	SLNURIAndFileIDRange1(range, txn, pos->URI);
	rc = db_cursor_firstr(cursor, range, key, NULL, +1);
	if(rc < 0) return rc;

	// Test that this URI gives us a unique, unambiguous position.
	// This is guaranteed for the internal hash and effectively
	// guaranteed for other cryptographic hashes, but may not be
	// true for other hash algorithms.
	rc = db_cursor_nextr(cursor, range, NULL, NULL, +1);
	if(rc >= 0) return DB_KEYEXIST;
	if(DB_NOTFOUND != rc) return rc;

	strarg_t u;
	uint64_t fileID;
	SLNURIAndFileIDKeyUnpack(key, txn, &u, &fileID);
	assert(0 == strcmp(pos->URI, u));

	SLNAgeRange const ages = SLNFilterFullAge(filter, fileID);
	if(!valid(ages.min) || ages.min > ages.max) return DB_NOTFOUND;
	uint64_t const sortID = ages.min;

	SLNFilterSeek(filter, pos->dir, sortID, fileID);
	SLNFilterStep(filter, pos->dir); // Start just before/after the URI.
	// TODO: Stepping is almost assuredly wrong if the URI doesn't match
	// the filter. We should check if our seek was a direct hit, and
	// only step if it was.
	return 0;
}
コード例 #5
0
static uint64_t add_metafile(DB_txn *const txn, uint64_t const fileID, strarg_t const targetURI) {
	uint64_t const metaFileID = fileID;
	uint64_t const latestMetaFileID = db_next_id(SLNMetaFileByID, txn);
	if(metaFileID < latestMetaFileID) return 0;
	// If it's not a new file, then it's not a new meta-file.
	// Note that ordinary files can't be "promoted" to meta-files later
	// because that would break the ordering.

	DB_val null = { 0, NULL };
	DB_cursor *cursor = NULL;
	int rc = db_txn_cursor(txn, &cursor);
	assert(rc >= 0);

	DB_val metaFileID_key[1];
	SLNMetaFileByIDKeyPack(metaFileID_key, txn, metaFileID);
	DB_val metaFile_val[1];
	SLNMetaFileByIDValPack(metaFile_val, txn, fileID, targetURI);
	rc = db_put(txn, metaFileID_key, metaFile_val, DB_NOOVERWRITE_FAST);
	assert(rc >= 0);

	DB_range alts[1];
	SLNTargetURIAndMetaFileIDRange1(alts, txn, targetURI);
	rc = db_cursor_firstr(cursor, alts, NULL, NULL, +1);
	assert(rc >= 0 || DB_NOTFOUND == rc);
	if(DB_NOTFOUND == rc) {
		DB_val unique[1];
		SLNFirstUniqueMetaFileIDKeyPack(unique, txn, metaFileID);
		rc = db_put(txn, unique, &null, DB_NOOVERWRITE_FAST);
		assert(rc >= 0);
	}

	DB_val targetURI_key[1];
	SLNTargetURIAndMetaFileIDKeyPack(targetURI_key, txn, targetURI, metaFileID);
	rc = db_put(txn, targetURI_key, &null, DB_NOOVERWRITE_FAST);
	assert(rc >= 0);

	return metaFileID;
}
コード例 #6
0
ファイル: SLNSession.c プロジェクト: seclu/stronglink
int SLNSessionGetSubmittedFile(SLNSessionRef const session, DB_txn *const txn, strarg_t const URI) {
	uint64_t const sessionID = SLNSessionGetID(session);
	DB_cursor *cursor = NULL;
	int rc = db_txn_cursor(txn, &cursor);
	if(rc < 0) return rc;
	DB_range range[1];
	DB_val filekey[1];
	SLNURIAndFileIDRange1(range, txn, URI);
	rc = db_cursor_firstr(cursor, range, filekey, NULL, +1);
	if(rc < 0) return rc;
	for(; rc >= 0; rc = db_cursor_nextr(cursor, range, filekey, NULL, +1)) {
		strarg_t u;
		uint64_t fileID;
		SLNURIAndFileIDKeyUnpack(filekey, txn, &u, &fileID);

		DB_val sessionkey[1];
		SLNFileIDAndSessionIDKeyPack(sessionkey, txn, fileID, sessionID);
		rc = db_cursor_seek(cursor, sessionkey, NULL, 0);
		if(DB_NOTFOUND == rc) continue;
		return rc;
	}
	return SLN_NOSESSION;
}
コード例 #7
0
ファイル: SLNSession.c プロジェクト: seclu/stronglink
int SLNSessionSetSubmittedFile(SLNSessionRef const session, DB_txn *const txn, strarg_t const URI) {
	uint64_t const sessionID = SLNSessionGetID(session);
	DB_cursor *cursor = NULL;
	int rc = db_txn_cursor(txn, &cursor);
	if(rc < 0) return rc;

	DB_range range[1];
	DB_val filekey[1];
	SLNURIAndFileIDRange1(range, txn, URI);
	rc = db_cursor_firstr(cursor, range, filekey, NULL, +1);
	if(rc < 0) return rc;

	strarg_t u;
	uint64_t fileID;
	SLNURIAndFileIDKeyUnpack(filekey, txn, &u, &fileID);

	DB_val sessionkey[1], null[1];
	SLNFileIDAndSessionIDKeyPack(sessionkey, txn, fileID, sessionID);
	db_nullval(null);
	rc = db_put(txn, sessionkey, null, 0);
	if(rc < 0) return rc;

	return rc;
}
コード例 #8
0
ファイル: db_ext.c プロジェクト: nkatsaros/stronglink
int db_get(DB_txn *const txn, DB_val *const key, DB_val *const data) {
	DB_cursor *cursor;
	int rc = db_txn_cursor(txn, &cursor);
	if(rc < 0) return rc;
	return db_cursor_seek(cursor, key, data, 0);
}
コード例 #9
0
ファイル: db_ext.c プロジェクト: nkatsaros/stronglink
int db_put(DB_txn *const txn, DB_val *const key, DB_val *const data, unsigned const flags) {
	DB_cursor *cursor;
	int rc = db_txn_cursor(txn, &cursor);
	if(rc < 0) return rc;
	return db_cursor_put(cursor, key, data, flags);
}