34 #include <sys/types.h>
55 #define MAX_ACCESSION_LENGTH 64
57 #define MAX_READERS 1024
58 #define MAP_SIZE_INIT (256L * 1024 * 1024 * 1024)
59 #define MAP_SIZE_DELTA (16L * 1024 * 1024 * 1024)
60 #define GI_DBI "#GI_DBI"
61 #define META_DBI "#META_DBI"
62 #define MAX_ROWS_PER_TRANSACTION 128
63 #define SYNC_PERIOD_SEC 5
82 static void LOG(
int severity,
char* fmt, ...)
84 __attribute__ ((
format (printf, 2, 3)))
95 static void LOG(
int severity,
char* fmt, ...)
102 if (
n >=
sizeof(
msg) - 1)
126 if (data_index && data_index->
m_txn) {
157 if (data_index->
m_txn)
159 if (data_index->
m_env) {
200 fstat_err =
xFindFile(data_index, &fstat);
201 if (fstat_err != 0 || fstat.st_size == 0) {
205 snprintf(logmsg,
sizeof(logmsg),
"GI_CACHE: failed to access file (%.256s): %s\n", data_index->
m_FileName,
strerror(rc));
212 snprintf(logmsg,
sizeof(logmsg),
"GI_CACHE: failed to init LMDB environment: %s\n",
mdb_strerror(rc));
218 snprintf(logmsg,
sizeof(logmsg),
"GI_CACHE: failed to update max dbs to %d: %s\n",
MAX_DBS,
mdb_strerror(rc));
224 snprintf(logmsg,
sizeof(logmsg),
"GI_CACHE: failed to update max readers to %d: %s\n",
MAX_READERS,
mdb_strerror(rc));
234 snprintf(logmsg,
sizeof(logmsg),
"GI_CACHE: failed to set map size of %" PRId64 ": %s\n", mapsize,
mdb_strerror(rc));
240 snprintf(logmsg,
sizeof(logmsg),
"GI_CACHE: failed to open LMDB db (%.256s): %s\n", data_index->
m_FileName,
mdb_strerror(rc));
246 snprintf(logmsg,
sizeof(logmsg),
"GI_CACHE: failed to start transaction: %s\n",
mdb_strerror(rc));
252 snprintf(logmsg,
sizeof(logmsg),
"GI_CACHE: failed to open dbi (%s): %s\n",
GI_DBI,
mdb_strerror(rc));
257 snprintf(logmsg,
sizeof(logmsg),
"GI_CACHE: failed to open dbi (%s): %s\n",
META_DBI,
mdb_strerror(rc));
264 snprintf(logmsg,
sizeof(logmsg),
"GI_CACHE: failed to commit transaction: %s\n",
mdb_strerror(rc));
270 snprintf(logmsg,
sizeof(logmsg),
"GI_CACHE: failed to check readers: %s\n",
mdb_strerror(rc));
291 int gi_len_bytes =
flags & 0x7;
292 int gi_len_neg =
flags & 0x8;
294 char* pacc = (
char*)
data->mv_data + gi_len_bytes + 2;
313 if (acc_buf_len <= acclen) {
314 LOG(
SEV_ERROR,
"GI_CACHE: accession length buffer length (%d) is too small, actual accession length is %d for gi: %" PRId64 "\n", acc_buf_len, acclen, gi);
317 memcpy(acc_buf, pacc, acclen);
334 if (acc_buf && acc_buf_len > 0)
337 if (!data_index || !data_index->
m_env) {
338 snprintf(logmsg,
sizeof(logmsg),
"GI_CACHE: DB is not open\n");
344 snprintf(logmsg,
sizeof(logmsg),
"GI_CACHE: failed to start transaction: %s\n",
mdb_strerror(rc));
349 key.mv_size =
sizeof(gi64);
357 snprintf(logmsg,
sizeof(logmsg),
"GI_CACHE: failed to get data for gi=%" PRId64 ": %s\n", gi,
mdb_strerror(rc));
368 snprintf(logmsg,
sizeof(logmsg),
"GI_CACHE: failed to close transaction: %s\n",
mdb_strerror(rc));
395 snprintf(logmsg,
sizeof(logmsg),
"GI_CACHE: failed to start transaction: %s\n",
mdb_strerror(rc));
401 snprintf(logmsg,
sizeof(logmsg),
"GI_CACHE: failed to open cursor: %s\n",
mdb_strerror(rc));
409 snprintf(logmsg,
sizeof(logmsg),
"GI_CACHE: failed to position cursor to last record: %s\n",
mdb_strerror(rc));
413 if (!
key.mv_data ||
key.mv_size !=
sizeof(gi64)) {
414 snprintf(logmsg,
sizeof(logmsg),
"GI_CACHE: last record contains no valid gi\n");
425 snprintf(logmsg,
sizeof(logmsg),
"GI_CACHE: failed to close transaction: %s\n",
mdb_strerror(rc));
452 int gi_len_bytes = 0;
457 acclen = strlen(acc);
459 snprintf(logmsg,
sizeof(logmsg),
"GI_CACHE: failed to put, provided accession is too long: %d (max supported length is %d)\n", acclen,
MAX_ACCESSION_LENGTH);
463 if (is_incremental) {
466 rc =
x_GetGiData(data_index, gi, lacc,
sizeof(lacc), &lgi_len);
470 changed_acc =
strcmp(lacc, acc) != 0;
471 changed_len = lgi_len != gi_len;
472 if (!changed_acc && !changed_len)
475 snprintf(logmsg,
sizeof(logmsg),
"GI_CACHE: gi %" PRId64 " changed accession from %s to %s\n", gi, lacc, acc);
477 snprintf(logmsg,
sizeof(logmsg),
"GI_CACHE: gi %" PRId64 " changed len from %" PRId64 " to %" PRId64 "\n", gi, lgi_len, gi_len);
481 if (!data_index->
m_txn) {
485 snprintf(logmsg,
sizeof(logmsg),
"GI_CACHE: failed to start transaction: %s\n",
mdb_strerror(rc));
491 key.mv_size =
sizeof(gi64);
493 gi_len_neg = gi_len < 0;
494 if (gi_len != 0 && gi_len != -1) {
504 flags = (gi_len_bytes & 0x7) | ((gi_len_neg ? 1 : 0) << 3);
512 memcpy(gidata + 1, &gi_len, gi_len_bytes);
513 gidata[1 + gi_len_bytes] = acclen;
514 memcpy(gidata + 1 + gi_len_bytes + 1, acc, acclen);
515 data.mv_size = datalen;
516 data.mv_data = gidata;
519 snprintf(logmsg,
sizeof(logmsg),
"GI_CACHE: failed to start transaction: %s\n",
mdb_strerror(rc));
536 if (data_index->
m_txn) {
567 if (!cache_found && !prefix) {
586 if (acc && buf_len > 0)
590 LOG(
SEV_ERROR,
"GICache_GetAccession: GI Cache is not initialized, call GICache_ReadData() first");
641 snprintf(accbuf,
sizeof(accbuf),
"%s.%d", acc,
version);
643 snprintf(accbuf,
sizeof(accbuf),
"%s", acc);
665 void GICache_Dump(
const char* cache_prefix,
const char* filename,
volatile int * quitting) {
680 f = fopen(filename,
"w");
682 snprintf(logmsg,
sizeof(logmsg),
"Failed to open file %s, error: %d", filename, errno);
685 setvbuf(
f,
NULL, _IOFBF, 128 * 1024);
689 snprintf(logmsg,
sizeof(logmsg),
"GI_CACHE: failed to start transaction: %s\n",
mdb_strerror(rc));
695 snprintf(logmsg,
sizeof(logmsg),
"GI_CACHE: failed to open cursor: %s\n",
mdb_strerror(rc));
707 if (!
key.mv_data ||
key.mv_size !=
sizeof(gi64)) {
708 LOG(
SEV_ERROR,
"GI_CACHE: last record contains no valid gi\n");
714 snprintf(line,
sizeof(line),
"%" PRId64 " %s %" PRId64 "\n", gi64, acc_buf, gi_len);
717 if (quitting && *quitting)
727 snprintf(logmsg,
sizeof(logmsg),
"GI_CACHE: failed to close transaction: %s\n",
mdb_strerror(rc));
763 snprintf(logmsg,
sizeof(logmsg),
"GICache_DropDb: failed to drop DB, database is not open");
767 snprintf(logmsg,
sizeof(logmsg),
"GICache_DropDb: failed to drop DB, database is open in readonly mode");
771 snprintf(logmsg,
sizeof(logmsg),
"GICache_DropDb: failed to drop DB, database has an active transaction");
776 snprintf(logmsg,
sizeof(logmsg),
"GI_CACHE: failed to start transaction: %s\n",
mdb_strerror(rc));
782 snprintf(logmsg,
sizeof(logmsg),
"GICache_DropDb: failed to drop DB: %s\n",
mdb_strerror(rc));
787 snprintf(logmsg,
sizeof(logmsg),
"GICache_DropDb: failed to drop meta DB: %s\n",
mdb_strerror(rc));
793 snprintf(logmsg,
sizeof(logmsg),
"GI_CACHE: failed to close transaction: %s\n",
mdb_strerror(rc));
812 key.mv_data = (
char*)Name;
813 key.mv_size = strlen(Name);
833 char meta[512], stime[128];
837 snprintf(logmsg,
sizeof(logmsg),
"GICache_SetMeta: failed to update META, database is not open");
841 snprintf(logmsg,
sizeof(logmsg),
"GICache_SetMeta: failed to update META, database is open in readonly mode");
845 snprintf(logmsg,
sizeof(logmsg),
"GICache_SetMeta: failed to update META, database has an active transaction");
850 snprintf(logmsg,
sizeof(logmsg),
"GI_CACHE: failed to start transaction: %s\n",
mdb_strerror(rc));
859 snprintf(logmsg,
sizeof(logmsg),
"GI_CACHE: failed to commit transaction: %s\n",
mdb_strerror(rc));
878 char meta[512], stime[128];
881 if (gethostname(meta,
sizeof(meta)) != 0)
889 snprintf(stime,
sizeof(stime),
"%" PRId64, (
int64_t)starttime);
911 snprintf(logmsg,
sizeof(logmsg),
"GICache_GetMeta: failed to read META, database is not open");
916 snprintf(logmsg,
sizeof(logmsg),
"GI_CACHE: failed to start transaction: %s\n",
mdb_strerror(rc));
919 key.mv_size = strlen(Name);
920 key.mv_data = (
char*)Name;
927 snprintf(logmsg,
sizeof(logmsg),
"GICache_GetMeta: failed to read meta: %s\n",
mdb_strerror(rc));
930 snprintf(
Value, ValueSz,
"%.*s", (
int)
data.mv_size, (
const char*)
data.mv_data);
935 snprintf(logmsg,
sizeof(logmsg),
"GI_CACHE: failed to close transaction: %s\n",
mdb_strerror(rc));
959 int64_t totlen = 0, totcomprlen = 0;
961 memset(tab, 0,
sizeof(*tab));
964 snprintf(logmsg,
sizeof(logmsg),
"GICache_GetAccFreqTab: failed to get frequency table, database is not open");
970 snprintf(logmsg,
sizeof(logmsg),
"GI_CACHE: failed to start transaction: %s\n",
mdb_strerror(rc));
976 snprintf(logmsg,
sizeof(logmsg),
"GI_CACHE: failed to open cursor: %s\n",
mdb_strerror(rc));
988 if (!
key.mv_data ||
key.mv_size !=
sizeof(gi64)) {
989 LOG(
SEV_ERROR,
"GI_CACHE: record contains no valid gi\n");
1001 int bits = tablen->
Count[(
unsigned int)(*p)];
1016 totcomprlen += (compr + 7) / 8;
1026 snprintf(logmsg,
sizeof(logmsg),
"GI_CACHE: failed to close transaction: %s\n",
mdb_strerror(rc));
1032 return (totcomprlen * 100L) / totlen;
int64_t GICache_GetLength(int64_t gi)
static int64_t x_GetMaxGi(SGiDataIndex *data_index)
static void(* __LogFuncEx)(int severity, char *msg)
static void LOG(int severity, char *fmt,...)
#define MAX_ACCESSION_LENGTH
static int x_PutData(SGiDataIndex *data_index, int64_t gi, int64_t gi_len, const char *acc, int overwrite, int is_incremental)
static void(* __LogFunc)(char *)
static int x_GetGiData(SGiDataIndex *data_index, int64_t gi, char *acc_buf, int acc_buf_len, int64_t *gi_len)
int x_Commit(SGiDataIndex *data_index, int force_sync)
static int x_DataToGiData(int64_t gi, MDB_val *data, char *acc_buf, int acc_buf_len, int64_t *gi_len)
void GICache_Dump(const char *cache_prefix, const char *filename, volatile int *quitting)
static int xFindFile(SGiDataIndex *data_index, struct stat *fstat)
static void GiDataIndex_Free(SGiDataIndex *data_index)
int GICache_ReadData(const char *prefix)
void GICache_SetLogEx(void(*logfunc)(int severity, char *msg))
static SGiDataIndex * gi_cache
int GICache_GetAccessionLen(int64_t gi, char *acc, int buf_len, int64_t *gi_len)
static SGiDataIndex * GiDataIndex_New(const char *prefix, Uint1 readonly)
static int x_mdb_txn_begin(MDB_env *env, MDB_txn *parent, unsigned int flags, MDB_txn **txn)
int GICache_SetMeta(const char *Name, const char *Value)
static int x_GICacheInit(const char *prefix, Uint1 readonly)
static int x_PutMeta(const char *Name, const char *Value)
int GICache_GetAccession(int64_t gi, char *acc, int buf_len)
int GICache_GetAccFreqTab(FreqTab *tab, const FreqTab *tablen)
int GICache_UpdateMeta(int is_incremental, const char *DB, time_t starttime)
int GiDataIndex_Commit(int force_sync)
int GICache_GetMeta(const char *Name, char *Value, size_t ValueSz)
int GICache_LoadStart(const char *cache_prefix)
int GICache_LoadAdd(int64_t gi, int64_t gi_len, const char *acc, int version, int is_incremental)
#define MAX_ROWS_PER_TRANSACTION
static Nlm_Boolean data_index_notfound
void GICache_SetLog(void(*logfunc)(char *))
int64_t GICache_GetMaxGi(void)
#define META_INCREMENTAL_HOST
#define RC_ALREADY_EXISTS
#define META_INCREMENTAL_TIME
#define DEFAULT_GI_CACHE_PATH
#define META_INCREMENTAL_DB
#define DEFAULT_GI_CACHE_PREFIX
uint8_t Uint1
1-byte (8-bit) unsigned integer
#define MDB_NOTFOUND
key/data pair not found (EOF)
#define MDB_SUCCESS
Successful result.
#define MDB_READERS_FULL
Environment maxreaders reached.
unsigned int
A callback function used to compare two keys in a database.
int mdb_env_open(MDB_env *env, const char *path, unsigned int flags, mdb_mode_t mode)
Open an environment handle.
int mdb_reader_check(MDB_env *env, int *dead)
Check for stale entries in the reader lock table.
void mdb_env_close(MDB_env *env)
Close the environment and release the memory map.
int mdb_cursor_get(MDB_cursor *cursor, MDB_val *key, MDB_val *data, MDB_cursor_op op)
Retrieve by cursor.
int mdb_put(MDB_txn *txn, MDB_dbi dbi, MDB_val *key, MDB_val *data, unsigned int flags)
Store items into a database.
void mdb_dbi_close(MDB_env *env, MDB_dbi dbi)
Close a database handle.
void mdb_txn_abort(MDB_txn *txn)
Abandon all the operations of the transaction instead of saving them.
int mdb_txn_commit(MDB_txn *txn)
Commit all the operations of a transaction into the database.
int mdb_env_sync(MDB_env *env, int force)
Flush the data buffers to disk.
int mdb_get(MDB_txn *txn, MDB_dbi dbi, MDB_val *key, MDB_val *data)
Get items from a database.
char * mdb_strerror(int err)
Return a string describing a given error code.
int mdb_cursor_open(MDB_txn *txn, MDB_dbi dbi, MDB_cursor **cursor)
Create a cursor handle.
int mdb_env_set_mapsize(MDB_env *env, size_t size)
Set the size of the memory map to use for this environment.
int mdb_env_set_maxdbs(MDB_env *env, MDB_dbi dbs)
Set the maximum number of named databases for the environment.
int mdb_env_create(MDB_env **env)
Create an LMDB environment handle.
int mdb_del(MDB_txn *txn, MDB_dbi dbi, MDB_val *key, MDB_val *data)
Delete items from a database.
int mdb_drop(MDB_txn *txn, MDB_dbi dbi, int del)
Empty or delete+close a database.
int mdb_dbi_open(MDB_txn *txn, const char *name, unsigned int flags, MDB_dbi *dbi)
Open a database in the environment.
void mdb_cursor_close(MDB_cursor *cursor)
Close a cursor handle.
int mdb_txn_begin(MDB_env *env, MDB_txn *parent, unsigned int flags, MDB_txn **txn)
Create a transaction for use with the environment.
int mdb_env_set_maxreaders(MDB_env *env, unsigned int readers)
Set the maximum number of threads/reader slots for the environment.
@ MDB_LAST
Position at last key/data item.
@ MDB_NEXT
Position at next data item.
#define MDB_INTEGERKEY
numeric keys in native byte order: either unsigned int or size_t.
#define MDB_CREATE
create DB if not already existing
#define MDB_NOMETASYNC
don't fsync metapage after commit
#define MDB_NOSYNC
don't fsync after commit
#define MDB_NOSUBDIR
no environment directory
#define MDB_RDONLY
read only
#define MDB_NOOVERWRITE
For put: Don't write if the key already exists.
unsigned int MDB_dbi
A handle for an individual database in the DB environment.
if(yy_accept[yy_current_state])
const string version
version string
const struct ncbi::grid::netcache::search::fields::KEY key
GenericValue< UTF8<> > Value
GenericValue with UTF8 encoding.
int strcmp(const char *str1, const char *str2)
Uint1 Boolean
bool replacment for C
#define TRUE
bool replacment for C indicating true.
#define FALSE
bool replacment for C indicating false.
#define NULLB
terminating byte of a char* string.
static SLJIT_INLINE sljit_ins msg(sljit_gpr r, sljit_s32 d, sljit_gpr x, sljit_gpr b)
Cursors are used for all DB operations.
The database environment.
Generic structure used for passing keys and data in and out of the database.
char m_FileName[PATH_MAX]