⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 kv_sqlite.c

📁 GNUnet是一个安全的点对点网络框架
💻 C
📖 第 1 页 / 共 2 页
字号:
/*     This file is part of GNUnet.     (C) 2006 Christian Grothoff (and other contributing authors)     GNUnet is free software; you can redistribute it and/or modify     it under the terms of the GNU General Public License as published     by the Free Software Foundation; either version 2, or (at your     option) any later version.     GNUnet is distributed in the hope that it will be useful, but     WITHOUT ANY WARRANTY; without even the implied warranty of     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU     General Public License for more details.     You should have received a copy of the GNU General Public License     along with GNUnet; see the file COPYING.  If not, write to the     Free Software Foundation, Inc., 59 Temple Place - Suite 330,     Boston, MA 02111-1307, USA.*//** * @file applications/kvstore_sqlite/kv_sqlite.c * @brief SQLite based implementation of the kvstore service * @author Nils Durner * @author Christian Grothoff * @todo Indexes, statistics * * Database: SQLite */#include "platform.h"#include "gnunet_util.h"#include "gnunet_directories.h"#include "gnunet_kvstore_service.h"#include <sqlite3.h>#define DEBUG_SQLITE GNUNET_NO/** * Die with an error message that indicates * a failure of the command 'cmd' with the message given * by strerror(errno). */#define DIE_SQLITE(dbh, cmd) do { GNUNET_GE_LOG(ectx, GNUNET_GE_FATAL | GNUNET_GE_ADMIN | GNUNET_GE_BULK, _("`%s' failed at %s:%d with error: %s\n"), cmd, __FILE__, __LINE__, sqlite3_errmsg(dbh)); abort(); } while(0);/** * Log an error message at log-level 'level' that indicates * a failure of the command 'cmd' on file 'filename' * with the message given by strerror(errno). */#define LOG_SQLITE(dbh, level, cmd) do { GNUNET_GE_LOG(ectx, GNUNET_GE_ERROR | GNUNET_GE_ADMIN | GNUNET_GE_BULK, _("`%s' failed at %s:%d with error: %s\n"), cmd, __FILE__, __LINE__, sqlite3_errmsg(dbh)); } while(0);/** * @brief Wrapper for SQLite */typedef struct{  /**   * Native SQLite database handle - may not be shared between threads!   */  sqlite3 *dbh;  /**   * Thread ID owning this handle   */  struct GNUNET_ThreadHandle *tid;} sqliteHandle;/** * @brief Information about the database */typedef struct{  /**   * bytes used   */  double payload;  /**   * name of the database   */  char *name;  /**   * filename of this database   */  char *fn;  /**   * List of open handles   */  sqliteHandle **handles;  /**   * Open handles (one per thread)   */  unsigned int handle_count;  unsigned int lastSync;} sqliteDatabase;static GNUNET_CoreAPIForPlugins *coreAPI;static struct GNUNET_GE_Context *ectx;static unsigned int databases;static sqliteDatabase **dbs;static struct GNUNET_Mutex *lock;/** * @brief Encode a binary buffer "in" of size n bytes so that it contains *        no instances of character '\000'. * @param in input * @param n size of in * @param out output */static intsqlite_encode_binary (const unsigned char *in, int n, unsigned char *out){  char c;  unsigned char *start = out;  n--;  for (; n > -1; n--)    {      c = *in;      in++;      if (c == 0 || c == 1)        {          *out = 1;          out++;          *out = c + 1;        }      else        {          *out = c;        }      out++;    }  return (int) (out - start);}/** * @brief Decode the string "in" into binary data and write it into "out". * @param in input * @param out output * @param num size of the output buffer * @return number of output bytes, -1 on error */static intsqlite_decode_binary_n (const unsigned char *in,                        unsigned char *out, unsigned int num){  unsigned char *start = out;  unsigned char *stop = (unsigned char *) (in + num);  while (in != stop)    {      if (*in == 1)        {          in++;          *out = *in - 1;        }      else        *out = *in;      in++;      out++;    }  return (int) (out - start);}/** * @brief Prepare a SQL statement */static intsq_prepare (sqliteHandle * dbh, const char *zSql,       /* SQL statement, UTF-8 encoded */            sqlite3_stmt ** ppStmt){                               /* OUT: Statement handle */  char *dummy;  return sqlite3_prepare (dbh->dbh,                          zSql,                          strlen (zSql), ppStmt, (const char **) &dummy);}/** * Get path to database file */static char *getDBFileName (const char *name){  char *dir;  char *fn;  size_t mem;  GNUNET_GC_get_configuration_value_filename (coreAPI->cfg,                                              "KEYVALUE_DATABASE",                                              "DIR",                                              GNUNET_DEFAULT_DAEMON_VAR_DIRECTORY                                              "/kvstore/", &dir);  GNUNET_disk_directory_create (ectx, dir);  mem = strlen (dir) + strlen (name) + 6;  fn = GNUNET_malloc (mem);  GNUNET_snprintf (fn, mem, "%s/%s.dat", dir, name);  GNUNET_free (dir);  return fn;}/** * @brief Get information about an open database * @param name the name of the database */static sqliteDatabase *getDB (const char *name){  unsigned int idx;  sqliteDatabase *db;  for (idx = 0; idx < databases; idx++)    if (0 == strcmp (dbs[idx]->name, name))      return dbs[idx];  db = GNUNET_malloc (sizeof (sqliteDatabase));  memset (db, 0, sizeof (sqliteDatabase));  db->fn = getDBFileName (name);  db->name = GNUNET_strdup (name);  GNUNET_array_append (dbs, databases, db);  return db;}/** * @brief Get a database handle for this thread. * @note SQLite handles may no be shared between threads - see *        http://permalink.gmane.org/gmane.network.gnunet.devel/1377 *       We therefore (re)open the database in each thread. * @return the native SQLite database handle */static sqliteHandle *getDBHandle (const char *name){  unsigned int idx;  sqliteHandle *dbh;  sqliteDatabase *db;  GNUNET_mutex_lock (lock);  db = getDB (name);  for (idx = 0; idx < db->handle_count; idx++)    if (GNUNET_thread_test_self (db->handles[idx]->tid))      {        sqliteHandle *ret = db->handles[idx];        GNUNET_mutex_unlock (lock);        return ret;      }  /* we haven't opened the DB for this thread yet */  dbh = GNUNET_malloc (sizeof (sqliteHandle));  dbh->tid = GNUNET_thread_get_self ();  if (sqlite3_open (db->fn, &dbh->dbh) != SQLITE_OK)    {      printf ("FN: %s\n", db->fn);      LOG_SQLITE (dbh->dbh, GNUNET_GE_ERROR | GNUNET_GE_BULK | GNUNET_GE_USER,                  "sqlite3_open");      sqlite3_close (dbh->dbh);      GNUNET_mutex_unlock (lock);      GNUNET_thread_release_self (dbh->tid);      GNUNET_free (dbh);      return NULL;    }  GNUNET_array_append (db->handles, db->handle_count, dbh);  sqlite3_exec (dbh->dbh, "PRAGMA temp_store=MEMORY", NULL, NULL, NULL);  sqlite3_exec (dbh->dbh, "PRAGMA synchronous=OFF", NULL, NULL, NULL);  sqlite3_exec (dbh->dbh, "PRAGMA count_changes=OFF", NULL, NULL, NULL);  sqlite3_exec (dbh->dbh, "PRAGMA page_size=4096", NULL, NULL, NULL);  GNUNET_mutex_unlock (lock);  return dbh;}static voidclose_database (sqliteDatabase * db){  unsigned int idx;  for (idx = 0; idx < db->handle_count; idx++)    {      sqliteHandle *dbh = db->handles[idx];      GNUNET_thread_release_self (dbh->tid);      if (sqlite3_close (dbh->dbh) != SQLITE_OK)        LOG_SQLITE (dbh->dbh, LOG_ERROR, "sqlite_close");      GNUNET_free (dbh);    }  GNUNET_array_grow (db->handles, db->handle_count, 0);  GNUNET_free (db->fn);  GNUNET_free (db->name);  GNUNET_free (db);}/** * @brief Delete the database. */static voiddropDatabase (const char *name){  sqliteDatabase *db;  unsigned int idx;  char *fn;  GNUNET_mutex_lock (lock);  for (idx = 0; idx < databases; idx++)    {      if (0 == strcmp (dbs[idx]->name, name))        {          db = dbs[idx];          close_database (db);          dbs[idx] = dbs[databases - 1];          GNUNET_array_grow (dbs, databases, databases - 1);          break;        }    }  fn = getDBFileName (name);  UNLINK (fn);  GNUNET_free (fn);  GNUNET_mutex_unlock (lock);}/** * @brief Open a Key/Value-Table * @param table the name of the Key/Value-Table * @return a handle */static GNUNET_KeyValueRecord *getTable (const char *database, const char *table){  sqlite3_stmt *stmt;  unsigned int len;  GNUNET_KeyValueRecord *ret;  sqliteHandle *dbh;  char *idx;  dbh = getDBHandle (database);  if (dbh == NULL)    return NULL;  sq_prepare (dbh, "Select 1 from sqlite_master where tbl_name = ?", &stmt);  len = strlen (table);  sqlite3_bind_text (stmt, 1, table, len, SQLITE_STATIC);  if (sqlite3_step (stmt) == SQLITE_DONE)    {      char *create = GNUNET_malloc (len + 58);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -