/**
 * Delete the entry with the lowest expiration value
 * from the datacache right now.
 *
 * @param cls closure (our `struct Plugin`)
 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
 */
static int
postgres_plugin_del (void *cls)
{
  struct Plugin *plugin = cls;
  uint32_t size;
  uint32_t oid;
  struct GNUNET_HashCode key;
  PGresult *res;

  res = PQexecPrepared (plugin->dbh,
                        "getm",
                        0, NULL, NULL, NULL, 1);
  if (GNUNET_OK !=
      GNUNET_POSTGRES_check_result (plugin->dbh,
                                    res,
                                    PGRES_TUPLES_OK,
                                    "PQexecPrepared",
                                    "getm"))
  {
    LOG (GNUNET_ERROR_TYPE_DEBUG,
	 "Ending iteration (postgres error)\n");
    return 0;
  }
  if (0 == PQntuples (res))
  {
    /* no result */
    LOG (GNUNET_ERROR_TYPE_DEBUG,
	 "Ending iteration (no more results)\n");
    PQclear (res);
    return GNUNET_SYSERR;
  }
  if ((3 != PQnfields (res)) || (sizeof (size) != PQfsize (res, 0)) ||
      (sizeof (oid) != PQfsize (res, 1)) ||
      (sizeof (struct GNUNET_HashCode) != PQgetlength (res, 0, 2)))
  {
    GNUNET_break (0);
    PQclear (res);
    return 0;
  }
  size = ntohl (*(uint32_t *) PQgetvalue (res, 0, 0));
  oid = ntohl (*(uint32_t *) PQgetvalue (res, 0, 1));
  memcpy (&key, PQgetvalue (res, 0, 2), sizeof (struct GNUNET_HashCode));
  PQclear (res);
  if (GNUNET_OK !=
      GNUNET_POSTGRES_delete_by_rowid (plugin->dbh,
                                       "delrow",
                                       oid))
    return GNUNET_SYSERR;
  plugin->num_items--;
  plugin->env->delete_notify (plugin->env->cls,
                              &key,
                              size + OVERHEAD);
  return GNUNET_OK;
}
Esempio n. 2
0
/**
 * Function invoked to process the result and call the processor.
 *
 * @param plugin global plugin data
 * @param proc function to call the value (once only).
 * @param proc_cls closure for proc
 * @param res result from exec
 * @param filename filename for error messages
 * @param line line number for error messages
 */
static void
process_result (struct Plugin *plugin, 
		PluginDatumProcessor proc,
                void *proc_cls,
		PGresult * res,
		const char *filename, int line)
{
  int iret;
  uint32_t rowid;
  uint32_t utype;
  uint32_t anonymity;
  uint32_t priority;
  size_t size;
  void *data;
  struct GNUNET_TIME_Absolute expiration_time;
  struct GNUNET_HashCode key;
  struct GNUNET_PQ_ResultSpec rs[] = {
    GNUNET_PQ_result_spec_uint32 ("type", &utype),
    GNUNET_PQ_result_spec_uint32 ("prio", &priority),
    GNUNET_PQ_result_spec_uint32 ("anonLevel", &anonymity),
    GNUNET_PQ_result_spec_uint32 ("oid", &rowid),
    GNUNET_PQ_result_spec_absolute_time ("expire", &expiration_time),
    GNUNET_PQ_result_spec_auto_from_type ("hash", &key),
    GNUNET_PQ_result_spec_variable_size ("value", &data, &size),
    GNUNET_PQ_result_spec_end
  };

  if (GNUNET_OK !=
      GNUNET_POSTGRES_check_result_ (plugin->dbh, 
				     res, 
				     PGRES_TUPLES_OK, 
				     "PQexecPrepared",
				     "select",
				     filename, line))
  {
    GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG,
		     "datastore-postgres",
                     "Ending iteration (postgres error)\n");
    proc (proc_cls, NULL, 0, NULL, 0, 0, 0, 
	  GNUNET_TIME_UNIT_ZERO_ABS, 0);
    return;
  }

  if (0 == PQntuples (res))
  {
    /* no result */
    GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, 
		     "datastore-postgres",
                     "Ending iteration (no more results)\n");
    proc (proc_cls, NULL, 0, NULL, 0, 0, 0, 
	  GNUNET_TIME_UNIT_ZERO_ABS, 0);
    PQclear (res);
    return;
  }
  if (1 != PQntuples (res)) 
  {
    GNUNET_break (0);
    proc (proc_cls, NULL, 0, NULL, 0, 0, 0,
	  GNUNET_TIME_UNIT_ZERO_ABS, 0);
    PQclear (res);
    return;
  }
  if (GNUNET_OK !=
      GNUNET_PQ_extract_result (res,
				rs,
				0))
  {
    GNUNET_break (0);
    PQclear (res);
    GNUNET_POSTGRES_delete_by_rowid (plugin->dbh,
				     "delrow", 
				     rowid);
    proc (proc_cls, NULL, 0, NULL, 0, 0, 0, 
	  GNUNET_TIME_UNIT_ZERO_ABS, 0);
    return;
  }

  GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, 
		   "datastore-postgres",
                   "Found result of size %u bytes and type %u in database\n",
                   (unsigned int) size, 
		   (unsigned int) utype);
  iret = proc (proc_cls,
	       &key,
	       size,
	       data,
	       (enum GNUNET_BLOCK_Type) utype, 
	       priority,
	       anonymity,
	       expiration_time,
	       rowid);
  PQclear (res);
  if (iret == GNUNET_NO)
  {
    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
                "Processor asked for item %u to be removed.\n", 
		(unsigned int) rowid);
    if (GNUNET_OK == 
	GNUNET_POSTGRES_delete_by_rowid (plugin->dbh, 
					 "delrow", 
					 rowid))
    {
      GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, 
		       "datastore-postgres",
                       "Deleting %u bytes from database\n",
                       (unsigned int) size);
      plugin->env->duc (plugin->env->cls,
                        - (size + GNUNET_DATASTORE_ENTRY_OVERHEAD));
      GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, 
		       "datastore-postgres",
                       "Deleted %u bytes from database\n",
		       (unsigned int) size);
    }
  }
}