📄 kv_sqlite.c
字号:
sprintf (create, "CREATE TABLE %s (gn_key BLOB, gn_val BLOB, gn_age BIGINT)", table); if (sqlite3_exec (dbh->dbh, create, NULL, NULL, NULL) != SQLITE_OK) { LOG_SQLITE (dbh->dbh, LOG_ERROR, "sqlite_create"); sqlite3_finalize (stmt); GNUNET_free (create); return NULL; } GNUNET_free (create); } sqlite3_finalize (stmt); /* FIXME: more indexes */ idx = GNUNET_malloc (len + 34); sprintf (idx, "CREATE INDEX idx_key ON %s (gn_key)", table); sqlite3_exec (dbh->dbh, idx, NULL, NULL, NULL); GNUNET_free (idx); ret = GNUNET_malloc (sizeof (GNUNET_KeyValueRecord)); ret->table = GNUNET_strdup (table); ret->db = GNUNET_strdup (database); return ret;}/** * @brief Get data from a Key/Value-Table * @param kv handle to the table * @param key the key to retrieve * @param keylen length of the key * @param sort 0 = dont, sort, 1 = random, 2 = sort by age * @param limit limit result set to n rows * @param handler callback function to be called for every result (may be NULL) * @param closure optional parameter for handler */static void *get (GNUNET_KeyValueRecord * kv, void *key, int keylen, unsigned int sort, unsigned int limit, GNUNET_KeyValueProcessor handler, void *closure){ unsigned int len, enclen, retlen; char *sel, *order, *where, limit_spec[30]; sqlite3_stmt *stmt; void *ret; sqliteHandle *dbh; unsigned char *key_enc; void *ret_dec; dbh = getDBHandle (kv->db); if (dbh == NULL) return NULL; ret = NULL; ret_dec = NULL; len = strlen (kv->table); sel = GNUNET_malloc (len + 45); if (key) { where = "WHERE gn_key = ?"; key_enc = GNUNET_malloc (keylen * 2 + 1); enclen = sqlite_encode_binary (key, keylen, key_enc); } else { where = ""; key_enc = NULL; enclen = 0; /* make gcc happy */ } switch (sort) { case 1: order = "BY RANDOM()"; break; case 2: order = "BY gn_age desc"; break; default: order = ""; break; } if (limit != 0) sprintf (limit_spec, "LIMIT %u", limit); else *limit_spec = 0; sprintf (sel, "SELECT gn_val FROM %s %s %s %s", kv->table, where, order, limit_spec); sq_prepare (dbh, sel, &stmt); if (key) sqlite3_bind_blob (stmt, 1, key_enc, enclen, SQLITE_STATIC); while (sqlite3_step (stmt) == SQLITE_ROW) { retlen = sqlite3_column_bytes (stmt, 0); ret = (void *) sqlite3_column_blob (stmt, 0); /* free previous result, only the last in the result set is returned to the caller */ GNUNET_free_non_null (ret_dec); ret_dec = GNUNET_malloc (retlen); retlen = sqlite_decode_binary_n (ret, ret_dec, retlen); if (handler) if (handler (closure, ret, retlen) != GNUNET_OK) { GNUNET_free (sel); GNUNET_free_non_null (key_enc); GNUNET_free (ret_dec); sqlite3_finalize (stmt); return ret; } } sqlite3_finalize (stmt); GNUNET_free (sel); GNUNET_free_non_null (key_enc); return ret_dec;}/** * @brief Store Key/Value-Pair in a table * @param kv handle to the table * @param key key of the pair * @param keylen length of the key (int because of SQLite!) * @param val value of the pair * @param vallen length of the value (int because of SQLite!) * @param optional creation time * @return GNUNET_OK on success, GNUNET_SYSERR otherwise */static intput (GNUNET_KeyValueRecord * kv, void *key, int keylen, void *val, int vallen, unsigned long long age){ unsigned int len; char *ins; sqlite3_stmt *stmt; sqliteHandle *dbh; unsigned char *key_enc, *val_enc; unsigned int keyenc_len, valenc_len; dbh = getDBHandle (kv->db); if (dbh == NULL) return GNUNET_SYSERR; len = strlen (kv->table); ins = GNUNET_malloc (len + 68); sprintf (ins, "INSERT INTO %s(gn_key, gn_val, gn_age) values (?, ?, ?)", kv->table); key_enc = GNUNET_malloc (keylen * 2); keyenc_len = sqlite_encode_binary (key, keylen, key_enc); val_enc = GNUNET_malloc (vallen * 2); valenc_len = sqlite_encode_binary (val, vallen, val_enc); sq_prepare (dbh, ins, &stmt); sqlite3_bind_blob (stmt, 1, key_enc, keyenc_len, SQLITE_STATIC); sqlite3_bind_blob (stmt, 2, val_enc, valenc_len, SQLITE_STATIC); sqlite3_bind_int64 (stmt, 3, age); if (sqlite3_step (stmt) != SQLITE_DONE) { GNUNET_free (ins); GNUNET_free (key_enc); GNUNET_free (val_enc); LOG_SQLITE (dbh->dbh, LOG_ERROR, "put"); sqlite3_finalize (stmt); return GNUNET_SYSERR; } sqlite3_finalize (stmt); GNUNET_free (ins); GNUNET_free (key_enc); GNUNET_free (val_enc); return GNUNET_OK;}/** * @brief Delete values from a Key/Value-Table * @param key key to delete (may be NULL) * @param keylen length of the key * @param age age of the items to delete (may be 0) * @return GNUNET_OK on success, GNUNET_SYSERR otherwise */static intdel (GNUNET_KeyValueRecord * kv, void *key, int keylen, unsigned long long age){ unsigned int len; char *del, *key_where, *age_where; sqlite3_stmt *stmt; int bind; sqliteHandle *dbh; unsigned char *keyenc; unsigned int keyenc_len; dbh = getDBHandle (kv->db); if (dbh == NULL) return GNUNET_SYSERR; len = strlen (kv->table); del = GNUNET_malloc (len + 52); bind = 1; if (key) key_where = "gn_key = ?"; else key_where = ""; if (age) age_where = "gn_age = ?"; else age_where = ""; sprintf (del, "DELETE from %s where %s %s %s", kv->table, key_where, age ? "or" : "", age_where); sq_prepare (dbh, del, &stmt); if (key) { keyenc = GNUNET_malloc (keylen * 2); keyenc_len = sqlite_encode_binary (key, keylen, keyenc); sqlite3_bind_blob (stmt, 1, keyenc, keyenc_len, SQLITE_STATIC); bind++; } else { keyenc = NULL; } if (age) sqlite3_bind_int64 (stmt, bind, age); if (sqlite3_step (stmt) != SQLITE_DONE) { GNUNET_free (del); GNUNET_free_non_null (keyenc); LOG_SQLITE (dbh->dbh, LOG_ERROR, "delete"); sqlite3_finalize (stmt); return GNUNET_SYSERR; } sqlite3_finalize (stmt); GNUNET_free (del); GNUNET_free_non_null (keyenc); return GNUNET_OK;}/** * @brief Close a handle to a Key/Value-Table * @param kv the handle to close */static voidcloseTable (GNUNET_KeyValueRecord * kv){ GNUNET_free (kv->table); GNUNET_free (kv->db);}/** * @brief Drop a Key/Value-Table * @param the handle to the table * @return GNUNET_OK on success, GNUNET_SYSERR otherwise */static intdropTable (GNUNET_KeyValueRecord * kv){ sqlite3_stmt *stmt; sqliteHandle *dbh; char *drop; dbh = getDBHandle (kv->db); if (dbh == NULL) return GNUNET_SYSERR; drop = GNUNET_malloc (12 + strlen (kv->table)); sprintf (drop, "DROP TABLE %s", kv->table); sq_prepare (dbh, drop, &stmt); if (sqlite3_step (stmt) != SQLITE_DONE) { GNUNET_free (drop); LOG_SQLITE (dbh->dbh, LOG_ERROR, "drop"); sqlite3_finalize (stmt); return GNUNET_SYSERR; } sqlite3_finalize (stmt); GNUNET_free (drop); closeTable (kv); return GNUNET_OK;}GNUNET_KVstore_ServiceAPI *provide_module_kvstore_sqlite (GNUNET_CoreAPIForPlugins * capi){ static GNUNET_KVstore_ServiceAPI api; ectx = capi->ectx;#if DEBUG_SQLITE GNUNET_GE_LOG (ectx, GNUNET_GE_DEBUG | GNUNET_GE_REQUEST | GNUNET_GE_USER, "KV-SQLite: initializing database\n");#endif lock = GNUNET_mutex_create (GNUNET_NO); coreAPI = capi; api.closeTable = &closeTable; api.del = &del; api.get = &get; api.getTable = &getTable; api.put = &put; api.dropTable = dropTable; api.dropDatabase = dropDatabase; return &api;}/** * Shutdown the module. */voidrelease_module_kvstore_sqlite (){ unsigned int idx; for (idx = 0; idx < databases; idx++) close_database (dbs[idx]); GNUNET_array_grow (dbs, databases, 0);#if DEBUG_SQLITE GNUNET_GE_LOG (ectx, GNUNET_GE_DEBUG | GNUNET_GE_REQUEST | GNUNET_GE_USER, "SQLite KVStore: database shutdown\n");#endif GNUNET_mutex_destroy (lock); coreAPI = NULL;}/* end of kv_sqlite.c */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -