/**
 * Get a random item for replication.  Returns a single, not expired,
 * random item from those with the highest replication counters.  The
 * item's replication counter is decremented by one IF it was positive
 * before.  Call 'proc' with all values ZERO or NULL if the datastore
 * is empty.
 *
 * @param cls closure
 * @param proc function to call the value (once only).
 * @param proc_cls closure for proc
 */
static void
mysql_plugin_get_replication (void *cls, PluginDatumProcessor proc,
                              void *proc_cls)
{
  struct Plugin *plugin = cls;
  struct ReplCtx rc;
  unsigned long long rvalue;
  unsigned long repl;
  MYSQL_BIND results;

  rc.plugin = plugin;
  rc.proc = proc;
  rc.proc_cls = proc_cls;
  memset (&results, 0, sizeof (results));
  results.buffer_type = MYSQL_TYPE_LONG;
  results.buffer = &repl;
  results.is_unsigned = GNUNET_YES;

  if (1 !=
      GNUNET_MYSQL_statement_run_prepared_select (plugin->mc, plugin->max_repl, 1, &results, NULL, NULL, -1))
  {
    proc (proc_cls, NULL, 0, NULL, 0, 0, 0, GNUNET_TIME_UNIT_ZERO_ABS, 0);
    return;
  }

  rvalue =
      (unsigned long long) GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_WEAK,
                                                     UINT64_MAX);
  execute_select (plugin, plugin->select_replication, &repl_proc, &rc,
                  MYSQL_TYPE_LONG, &repl, GNUNET_YES, MYSQL_TYPE_LONGLONG,
                  &rvalue, GNUNET_YES, MYSQL_TYPE_LONG, &repl, GNUNET_YES,
                  MYSQL_TYPE_LONGLONG, &rvalue, GNUNET_YES, -1);

}
/**
 * Get a zero-anonymity datum from the datastore.
 *
 * @param cls our "struct Plugin*"
 * @param offset offset of the result
 * @param type entries of which type should be considered?
 *        Use 0 for any type.
 * @param proc function to call on a matching value or NULL
 * @param proc_cls closure for iter
 */
static void
mysql_plugin_get_zero_anonymity (void *cls, uint64_t offset,
                                 enum GNUNET_BLOCK_Type type,
                                 PluginDatumProcessor proc, void *proc_cls)
{
  struct Plugin *plugin = cls;
  unsigned long long rvalue =
      (unsigned long long) GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_WEAK,
                                                     UINT64_MAX);

  execute_select (plugin, plugin->zero_iter, proc, proc_cls, MYSQL_TYPE_LONG,
                  &type, GNUNET_YES, MYSQL_TYPE_LONGLONG, &rvalue, GNUNET_YES,
                  MYSQL_TYPE_LONG, &type, GNUNET_YES, MYSQL_TYPE_LONGLONG,
                  &rvalue, GNUNET_YES, -1);
}
/**
 * Store an item in the datastore.
 *
 * @param cls closure
 * @param key key for the item
 * @param size number of bytes in data
 * @param data content stored
 * @param type type of the content
 * @param priority priority of the content
 * @param anonymity anonymity-level for the content
 * @param replication replication-level for the content
 * @param expiration expiration time for the content
 * @param msg set to error message
 * @return GNUNET_OK on success
 */
static int
mysql_plugin_put (void *cls, const struct GNUNET_HashCode * key, uint32_t size,
                  const void *data, enum GNUNET_BLOCK_Type type,
                  uint32_t priority, uint32_t anonymity, uint32_t replication,
                  struct GNUNET_TIME_Absolute expiration, char **msg)
{
  struct Plugin *plugin = cls;
  unsigned int irepl = replication;
  unsigned int ipriority = priority;
  unsigned int ianonymity = anonymity;
  unsigned long long lexpiration = expiration.abs_value_us;
  unsigned long long lrvalue =
      (unsigned long long) GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_WEAK,
                                                     UINT64_MAX);
  unsigned long hashSize;
  unsigned long hashSize2;
  unsigned long lsize;
  struct GNUNET_HashCode vhash;

  if (size > MAX_DATUM_SIZE)
  {
    GNUNET_break (0);
    return GNUNET_SYSERR;
  }
  hashSize = sizeof (struct GNUNET_HashCode);
  hashSize2 = sizeof (struct GNUNET_HashCode);
  lsize = size;
  GNUNET_CRYPTO_hash (data, size, &vhash);
  if (GNUNET_OK !=
      GNUNET_MYSQL_statement_run_prepared (plugin->mc, plugin->insert_entry, NULL,
                              MYSQL_TYPE_LONG, &irepl, GNUNET_YES,
                              MYSQL_TYPE_LONG, &type, GNUNET_YES,
                              MYSQL_TYPE_LONG, &ipriority, GNUNET_YES,
                              MYSQL_TYPE_LONG, &ianonymity, GNUNET_YES,
                              MYSQL_TYPE_LONGLONG, &lexpiration, GNUNET_YES,
                              MYSQL_TYPE_LONGLONG, &lrvalue, GNUNET_YES,
                              MYSQL_TYPE_BLOB, key, hashSize, &hashSize,
                              MYSQL_TYPE_BLOB, &vhash, hashSize2, &hashSize2,
                              MYSQL_TYPE_BLOB, data, lsize, &lsize, -1))
    return GNUNET_SYSERR;
  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
              "Inserted value `%s' with size %u into gn090 table\n",
              GNUNET_h2s (key), (unsigned int) size);
  if (size > 0)
    plugin->env->duc (plugin->env->cls, size);
  return GNUNET_OK;
}
Exemple #4
0
/**
 * Initialize the connection with the DHT service.
 *
 * @param cfg configuration to use
 * @param ht_len size of the internal hash table to use for
 *               processing multiple GET/FIND requests in parallel
 * @return handle to the DHT service, or NULL on error
 */
struct GNUNET_DHT_Handle *
GNUNET_DHT_connect (const struct GNUNET_CONFIGURATION_Handle *cfg,
                    unsigned int ht_len)
{
  struct GNUNET_DHT_Handle *handle;

  handle = GNUNET_new (struct GNUNET_DHT_Handle);
  handle->cfg = cfg;
  handle->uid_gen =
      GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_WEAK, UINT64_MAX);
  handle->active_requests = GNUNET_CONTAINER_multihashmap_create (ht_len, GNUNET_YES);
  if (GNUNET_NO == try_connect (handle))
  {
    GNUNET_DHT_disconnect (handle);
    return NULL;
  }
  return handle;
}
Exemple #5
0
/**
 * Get the transmission delay that should be applied for a
 * particular round.
 *
 * @param round_offset -1 for the previous round (random delay between 0 and 50ms)
 *                      0 for the current round (based on our proximity to time key)
 * @return delay that should be applied
 */
static struct GNUNET_TIME_Relative
get_transmit_delay (int round_offset)
{
  struct GNUNET_TIME_Relative ret;
  struct GNUNET_TIME_Absolute tgt;
  double dist_delay;
  uint32_t matching_bits;

  switch (round_offset)
  {
  case -1:
    /* previous round is randomized between 0 and 50 ms */
#if USE_RANDOM_DELAYS
    ret.rel_value_us = GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_WEAK,
						 50);
#else
    ret = GNUNET_TIME_UNIT_ZERO;
#endif
    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
                "Transmitting previous round behind schedule in %s\n",
                GNUNET_STRINGS_relative_time_to_string (ret,
							GNUNET_YES));
    return ret;
  case 0:
    /* current round is based on best-known matching_bits */
    matching_bits =
        ntohl (size_estimate_messages[estimate_index].matching_bits);
    dist_delay = get_matching_bits_delay (matching_bits);
    dist_delay += get_delay_randomization (matching_bits).rel_value_us;
    ret.rel_value_us = (uint64_t) dist_delay;
    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
                "For round %s, delay for %u matching bits is %s\n",
                GNUNET_STRINGS_absolute_time_to_string (current_timestamp),
                (unsigned int) matching_bits,
                GNUNET_STRINGS_relative_time_to_string (ret,
							GNUNET_YES));
    /* now consider round start time and add delay to it */
    tgt = GNUNET_TIME_absolute_add (current_timestamp,
				    ret);
    return GNUNET_TIME_absolute_get_remaining (tgt);
  }
  GNUNET_break (0);
  return GNUNET_TIME_UNIT_FOREVER_REL;
}
/**
 * Get a random item for replication.  Returns a single random item
 * from those with the highest replication counters.  The item's
 * replication counter is decremented by one IF it was positive before.
 * Call 'proc' with all values ZERO or NULL if the datastore is empty.
 *
 * @param cls closure
 * @param proc function to call the value (once only).
 * @param proc_cls closure for proc
 */
static void
sqlite_plugin_get_replication (void *cls, PluginDatumProcessor proc,
                               void *proc_cls)
{
  struct Plugin *plugin = cls;
  struct ReplCtx rc;
  uint64_t rvalue;
  uint32_t repl;
  sqlite3_stmt *stmt;

  GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "sqlite",
                   "Getting random block based on replication order.\n");
  rc.have_uid = GNUNET_NO;
  rc.proc = proc;
  rc.proc_cls = proc_cls;
  stmt = plugin->maxRepl;
  if (SQLITE_ROW != sqlite3_step (stmt))
  {
    if (SQLITE_OK != sqlite3_reset (stmt))
      LOG_SQLITE (plugin, NULL,
                  GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
                  "sqlite3_reset");
    /* DB empty */
    proc (proc_cls, NULL, 0, NULL, 0, 0, 0, GNUNET_TIME_UNIT_ZERO_ABS, 0);
    return;
  }
  repl = sqlite3_column_int (stmt, 0);
  if (SQLITE_OK != sqlite3_reset (stmt))
    LOG_SQLITE (plugin, NULL, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
                "sqlite3_reset");
  stmt = plugin->selRepl;
  rvalue = GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_WEAK, UINT64_MAX);
  if (SQLITE_OK != sqlite3_bind_int64 (stmt, 1, rvalue))
  {
    LOG_SQLITE (plugin, NULL, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
                "sqlite3_bind_XXXX");
    if (SQLITE_OK != sqlite3_reset (stmt))
      LOG_SQLITE (plugin, NULL,
                  GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
                  "sqlite3_reset");
    proc (proc_cls, NULL, 0, NULL, 0, 0, 0, GNUNET_TIME_UNIT_ZERO_ABS, 0);
    return;
  }
  if (SQLITE_OK != sqlite3_bind_int (stmt, 2, repl))
  {
    LOG_SQLITE (plugin, NULL, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
                "sqlite3_bind_XXXX");
    if (SQLITE_OK != sqlite3_reset (stmt))
      LOG_SQLITE (plugin, NULL,
                  GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
                  "sqlite3_reset");
    proc (proc_cls, NULL, 0, NULL, 0, 0, 0, GNUNET_TIME_UNIT_ZERO_ABS, 0);
    return;
  }
  execute_get (plugin, stmt, &repl_proc, &rc);
  if (GNUNET_YES == rc.have_uid)
  {
    if (SQLITE_OK != sqlite3_bind_int64 (plugin->updRepl, 1, rc.uid))
    {
      LOG_SQLITE (plugin, NULL,
                  GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
                  "sqlite3_bind_XXXX");
      if (SQLITE_OK != sqlite3_reset (plugin->updRepl))
        LOG_SQLITE (plugin, NULL,
                    GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
                    "sqlite3_reset");
      return;
    }
    if (SQLITE_DONE != sqlite3_step (plugin->updRepl))
      LOG_SQLITE (plugin, NULL,
                  GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
                  "sqlite3_step");
    if (SQLITE_OK != sqlite3_reset (plugin->updRepl))
      LOG_SQLITE (plugin, NULL,
                  GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
                  "sqlite3_reset");
  }
}
/**
 * Store an item in the datastore.
 *
 * @param cls closure
 * @param key key for the item
 * @param size number of bytes in data
 * @param data content stored
 * @param type type of the content
 * @param priority priority of the content
 * @param anonymity anonymity-level for the content
 * @param replication replication-level for the content
 * @param expiration expiration time for the content
 * @param msg set to an error message
 * @return GNUNET_OK on success
 */
static int
sqlite_plugin_put (void *cls, const GNUNET_HashCode * key, uint32_t size,
                   const void *data, enum GNUNET_BLOCK_Type type,
                   uint32_t priority, uint32_t anonymity, uint32_t replication,
                   struct GNUNET_TIME_Absolute expiration, char **msg)
{
  struct Plugin *plugin = cls;
  int n;
  int ret;
  sqlite3_stmt *stmt;
  GNUNET_HashCode vhash;
  uint64_t rvalue;

  if (size > MAX_ITEM_SIZE)
    return GNUNET_SYSERR;
  GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "sqlite",
                   "Storing in database block with type %u/key `%s'/priority %u/expiration in %llu ms (%lld).\n",
                   type, GNUNET_h2s (key), priority,
                   (unsigned long long)
                   GNUNET_TIME_absolute_get_remaining (expiration).rel_value,
                   (long long) expiration.abs_value);
  GNUNET_CRYPTO_hash (data, size, &vhash);
  stmt = plugin->insertContent;
  rvalue = GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_WEAK, UINT64_MAX);
  if ((SQLITE_OK != sqlite3_bind_int (stmt, 1, replication)) ||
      (SQLITE_OK != sqlite3_bind_int (stmt, 2, type)) ||
      (SQLITE_OK != sqlite3_bind_int (stmt, 3, priority)) ||
      (SQLITE_OK != sqlite3_bind_int (stmt, 4, anonymity)) ||
      (SQLITE_OK != sqlite3_bind_int64 (stmt, 5, expiration.abs_value)) ||
      (SQLITE_OK != sqlite3_bind_int64 (stmt, 6, rvalue)) ||
      (SQLITE_OK !=
       sqlite3_bind_blob (stmt, 7, key, sizeof (GNUNET_HashCode),
                          SQLITE_TRANSIENT)) ||
      (SQLITE_OK !=
       sqlite3_bind_blob (stmt, 8, &vhash, sizeof (GNUNET_HashCode),
                          SQLITE_TRANSIENT)) ||
      (SQLITE_OK != sqlite3_bind_blob (stmt, 9, data, size, SQLITE_TRANSIENT)))
  {
    LOG_SQLITE (plugin, msg, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
                "sqlite3_bind_XXXX");
    if (SQLITE_OK != sqlite3_reset (stmt))
      LOG_SQLITE (plugin, NULL,
                  GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
                  "sqlite3_reset");
    return GNUNET_SYSERR;
  }
  n = sqlite3_step (stmt);
  switch (n)
  {
  case SQLITE_DONE:
    plugin->env->duc (plugin->env->cls, size + GNUNET_DATASTORE_ENTRY_OVERHEAD);
    GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "sqlite",
                     "Stored new entry (%u bytes)\n",
                     size + GNUNET_DATASTORE_ENTRY_OVERHEAD);
    ret = GNUNET_OK;
    break;
  case SQLITE_BUSY:
    GNUNET_break (0);
    LOG_SQLITE (plugin, msg, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
                "sqlite3_step");
    ret = GNUNET_SYSERR;
    break;
  default:
    LOG_SQLITE (plugin, msg, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
                "sqlite3_step");
    if (SQLITE_OK != sqlite3_reset (stmt))
      LOG_SQLITE (plugin, NULL,
                  GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
                  "sqlite3_reset");
    database_shutdown (plugin);
    database_setup (plugin->env->cfg, plugin);
    return GNUNET_SYSERR;
  }
  if (SQLITE_OK != sqlite3_reset (stmt))
    LOG_SQLITE (plugin, NULL, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
                "sqlite3_reset");
  return ret;
}