fixing issue pointed out by amatus
[oweals/gnunet.git] / src / datacache / plugin_datacache_postgres.c
index 5959d54a6df0da8fe6a552f80ecc60730b1f749e..c9d6deaaa565149fb0d530b352bbe5fd6aa0da33 100644 (file)
 
 #define DEBUG_POSTGRES GNUNET_NO
 
-
+/**
+ * Per-entry overhead estimate
+ */
+#define OVERHEAD (sizeof(GNUNET_HashCode) + 24)
 
 /**
  * Context for all functions in this plugin.
@@ -154,7 +157,7 @@ init_connection (struct Plugin *plugin)
       return GNUNET_SYSERR;
     }
   ret = PQexec (plugin->dbh,
-                "CREATE TEMPORARY `TABLE gn090dc ("
+                "CREATE TEMPORARY TABLE gn090dc ("
                 "  type INTEGER NOT NULL DEFAULT 0,"
                 "  discard_time BIGINT NOT NULL DEFAULT 0,"
                 "  key BYTEA NOT NULL DEFAULT '',"
@@ -177,7 +180,7 @@ init_connection (struct Plugin *plugin)
       if ((GNUNET_OK !=
            pq_exec (plugin, "CREATE INDEX idx_key ON gn090dc (key)", __LINE__)) ||
           (GNUNET_OK !=
-           pq_exec (plugin, "CREATE INDEX idx_dt ON gn090 (discard_time)",
+           pq_exec (plugin, "CREATE INDEX idx_dt ON gn090dc (discard_time)",
                     __LINE__)) )
         {
           PQclear (ret);
@@ -217,20 +220,20 @@ init_connection (struct Plugin *plugin)
        pq_prepare (plugin,
                   "getkt",
                    "SELECT discard_time,type,value FROM gn090dc "
-                   "WHERE hash=$1 type=$2 ",
+                   "WHERE key=$1 AND type=$2 ",
                    2,
                    __LINE__)) ||
       (GNUNET_OK !=
        pq_prepare (plugin,
                   "getk",
                    "SELECT discard_time,type,value FROM gn090dc "
-                   "WHERE hash=$1",
+                   "WHERE key=$1",
                    1,
                    __LINE__)) ||
       (GNUNET_OK !=
        pq_prepare (plugin,
                   "getm",
-                   "SELECT length(value),oid FROM gn090dc"
+                   "SELECT length(value),oid,key FROM gn090dc "
                    "ORDER BY discard_time ASC LIMIT 1",
                    0,
                    __LINE__)) ||
@@ -264,10 +267,11 @@ init_connection (struct Plugin *plugin)
  */
 static int
 delete_by_rowid (struct Plugin *plugin,
-                unsigned int rowid)
+                uint32_t rowid)
 {
-  const char *paramValues[] = { (const char *) &rowid };
-  int paramLengths[] = { sizeof (rowid) };
+  uint32_t brow = htonl (rowid);
+  const char *paramValues[] = { (const char *) &brow };
+  int paramLengths[] = { sizeof (brow) };
   const int paramFormats[] = { 1 };
   PGresult *ret;
 
@@ -297,10 +301,10 @@ delete_by_rowid (struct Plugin *plugin,
  * @param discard_time when to discard the value in any case
  * @return 0 on error, number of bytes used otherwise
  */
-static uint32_t 
+static size_t 
 postgres_plugin_put (void *cls,
                     const GNUNET_HashCode * key,
-                    uint32_t size,
+                    size_t size,
                     const char *data,
                     enum GNUNET_BLOCK_Type type,
                     struct GNUNET_TIME_Absolute discard_time)
@@ -330,7 +334,7 @@ postgres_plugin_put (void *cls,
                                  "PQexecPrepared", "put", __LINE__))
     return GNUNET_SYSERR;
   PQclear (ret);
-  return size;
+  return size + OVERHEAD;
 }
 
 
@@ -403,6 +407,11 @@ postgres_plugin_get (void *cls,
       PQclear (res);
       return 0; 
     }
+  if (iter == NULL)
+    {
+      PQclear (res);
+      return cnt;
+    }
   if ( (3 != PQnfields (res)) ||
        (sizeof (uint64_t) != PQfsize (res, 0)) ||
        (sizeof (uint32_t) != PQfsize (res, 1)))
@@ -455,9 +464,62 @@ postgres_plugin_get (void *cls,
 static int 
 postgres_plugin_del (void *cls)
 {
-  
-  GNUNET_break (0);
-  return GNUNET_SYSERR;
+  struct Plugin *plugin = cls;
+  uint32_t size;
+  uint32_t oid;
+  GNUNET_HashCode key;
+  PGresult *res;
+
+  res = PQexecPrepared (plugin->dbh,
+                       "getm",
+                       0, NULL, NULL, NULL,
+                       1);
+  if (GNUNET_OK != check_result (plugin,
+                                res,
+                                PGRES_TUPLES_OK,
+                                "PQexecPrepared",
+                                "getm",
+                                __LINE__))
+    {
+#if DEBUG_POSTGRES
+      GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG,
+                      "datacache-postgres",
+                      "Ending iteration (postgres error)\n");
+#endif
+      return 0;
+    }
+  if (0 == PQntuples (res))
+    {
+      /* no result */
+#if DEBUG_POSTGRES
+      GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG,
+                      "datacache-postgres",
+                      "Ending iteration (no more results)\n");
+#endif
+      PQclear (res);
+      return GNUNET_SYSERR; 
+    }
+  if ( (3 != PQnfields (res)) ||
+       (sizeof (size) != PQfsize (res, 0)) ||
+       (sizeof (oid) != PQfsize (res, 1)) ||
+       (sizeof (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 (GNUNET_HashCode));
+  PQclear (res);
+  if (GNUNET_OK != delete_by_rowid (plugin, oid))
+    return GNUNET_SYSERR;
+  plugin->env->delete_notify (plugin->env->cls,
+                             &key,
+                             size + OVERHEAD);  
+  return GNUNET_OK;
 }
 
 
@@ -508,6 +570,7 @@ libgnunet_plugin_datacache_postgres_done (void *cls)
   struct GNUNET_DATACACHE_PluginFunctions *api = cls;
   struct Plugin *plugin = api->cls;
 
+  PQfinish (plugin->dbh);
   GNUNET_free (plugin);
   GNUNET_free (api);
   return NULL;