예제 #1
0
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;
}
예제 #2
0
int SLNFilterCopyURI(SLNFilterRef const filter, uint64_t const fileID, bool const meta, DB_txn *const txn, str_t **const out) {
	DB_val fileID_key[1], file_val[1];
	SLNFileByIDKeyPack(fileID_key, txn, fileID);
	int rc = db_get(txn, fileID_key, file_val);
	if(rc < 0) return rc;

	strarg_t const hash = db_read_string(file_val, txn);
	db_assert(hash);

	str_t *URI = NULL;
	if(!meta) {
		URI = SLNFormatURI(SLN_INTERNAL_ALGO, hash);
		if(!URI) return DB_ENOMEM;
	} else {
		DB_val key[1], val[1];
		SLNMetaFileByIDKeyPack(key, txn, fileID);
		rc = db_get(txn, key, val);
		if(rc < 0) return rc;
		uint64_t f;
		strarg_t target = NULL;
		SLNMetaFileByIDValUnpack(val, txn, &f, &target);
		db_assert(target);
		URI = aasprintf("hash://%s/%s -> %s", SLN_INTERNAL_ALGO, hash, target);
		if(!URI) return DB_ENOMEM;
	}

	*out = URI; URI = NULL;
	return 0;
}
예제 #3
0
int SLNSubmissionStore(SLNSubmissionRef const sub, DB_txn *const txn) {
	assert(sub);
	assert(txn);
	assert(!sub->tmppath);
	// Session permissions were already checked when the sub was created.

	int64_t fileID = db_next_id(SLNFileByID, txn);
	int rc;

	DB_val dupFileID_val[1];
	SLNFileIDByInfoValPack(dupFileID_val, txn, fileID);

	DB_val fileInfo_key[1];
	SLNFileIDByInfoKeyPack(fileInfo_key, txn, sub->internalHash, sub->type);
	rc = db_put(txn, fileInfo_key, dupFileID_val, DB_NOOVERWRITE);
	if(rc >= 0) {
		DB_val fileID_key[1];
		SLNFileByIDKeyPack(fileID_key, txn, fileID);
		DB_val file_val[1];
		SLNFileByIDValPack(file_val, txn, sub->internalHash, sub->type, sub->size);
		rc = db_put(txn, fileID_key, file_val, DB_NOOVERWRITE_FAST);
		if(rc < 0) return rc;
	} else if(DB_KEYEXIST == rc) {
		fileID = db_read_uint64(dupFileID_val);
	} else return rc;

	for(size_t i = 0; sub->URIs[i]; ++i) {
		strarg_t const URI = sub->URIs[i];
		DB_val null = { 0, NULL };

		DB_val fwd[1];
		SLNFileIDAndURIKeyPack(fwd, txn, fileID, URI);
		rc = db_put(txn, fwd, &null, DB_NOOVERWRITE_FAST);
		if(rc < 0 && DB_KEYEXIST != rc) return rc;

		DB_val rev[1];
		SLNURIAndFileIDKeyPack(rev, txn, URI, fileID);
		rc = db_put(txn, rev, &null, DB_NOOVERWRITE_FAST);
		if(rc < 0 && DB_KEYEXIST != rc) return rc;
	}

	rc = SLNSubmissionParseMetaFile(sub, fileID, txn, &sub->metaFileID);
	if(rc < 0) {
		alogf("Submission meta-file error: %s\n", sln_strerror(rc));
		return rc;
	}

	return 0;
}