gnunet-svn
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[GNUnet-SVN] r3609 - in GNUnet: . src/applications/sqstore_mysql


From: grothoff
Subject: [GNUnet-SVN] r3609 - in GNUnet: . src/applications/sqstore_mysql
Date: Thu, 2 Nov 2006 06:10:58 -0800 (PST)

Author: grothoff
Date: 2006-11-02 06:10:51 -0800 (Thu, 02 Nov 2006)
New Revision: 3609

Modified:
   GNUnet/ChangeLog
   GNUnet/src/applications/sqstore_mysql/mysql.c
   GNUnet/src/applications/sqstore_mysql/mysqltest2.c
Log:
mysql fixes

Modified: GNUnet/ChangeLog
===================================================================
--- GNUnet/ChangeLog    2006-11-01 21:14:26 UTC (rev 3608)
+++ GNUnet/ChangeLog    2006-11-02 14:10:51 UTC (rev 3609)
@@ -1,3 +1,6 @@
+Wed Nov  1 20:58:44 MST 2006
+       Fixed MySQL database size underreporting.
+
 Wed Nov  1 13:09:53 MST 2006
        Fixed some problems with index creation in sqlite
        datastore (discovered with new sqlite benchmarking

Modified: GNUnet/src/applications/sqstore_mysql/mysql.c
===================================================================
--- GNUnet/src/applications/sqstore_mysql/mysql.c       2006-11-01 21:14:26 UTC 
(rev 3608)
+++ GNUnet/src/applications/sqstore_mysql/mysql.c       2006-11-02 14:10:51 UTC 
(rev 3609)
@@ -85,7 +85,7 @@
  *    works. First, login as $USER. Then use,
  *
  *    <pre>
- *    $ mysql -u $USER
+ *    $ mysql -u $USER -p $the_password_you_like
  *    mysql> use gnunet;
  *    </pre>
  *
@@ -124,6 +124,7 @@
 #include "gnunet_util.h"
 #include "gnunet_sqstore_service.h"
 #include "gnunet_stats_service.h"
+#include "gnunet_state_service.h"
 #include <mysql/mysql.h>
 
 #define DEBUG_MYSQL NO
@@ -144,9 +145,21 @@
 #define LOG_MYSQL(level, cmd, dbh) do { GE_LOG(ectx, level, _("`%s' failed at 
%s:%d with error: %s\n"), cmd, __FILE__, __LINE__, mysql_error((dbh)->dbf)); } 
while(0);
 
 static Stats_ServiceAPI * stats;
+
 static CoreAPIForApplication * coreAPI;
+
 static unsigned int stat_size;
 
+/**
+ * Size of the mysql database on disk.
+ */
+static unsigned long long content_size;
+
+/**
+ * Lock for updating content_size
+ */
+static struct MUTEX * lock;
+
 static struct GE_Context * ectx;
 
 /**
@@ -154,33 +167,56 @@
  */
 typedef struct {
   MYSQL * dbf;
-  int avgLength_ID;       /* which column contains the Avg_row_length
-                            * in SHOW TABLE STATUS resultset */
+
   char * cnffile;
+
   int prepare;
+
   MYSQL_STMT * insert;
+
   MYSQL_BIND bind[7];
+
   MYSQL_STMT * select;
+
   MYSQL_STMT * selectc;
+
   MYSQL_STMT * selects;
+
   MYSQL_STMT * selectsc;
+
   MYSQL_BIND sbind[2];
+
   MYSQL_STMT * deleteh;
+
   MYSQL_STMT * deleteg;
+
   MYSQL_BIND dbind[7];
+
   MYSQL_STMT * update;
+
   MYSQL_BIND ubind[3];
+
   struct MUTEX * DATABASE_Lock_;
+
 } mysqlHandle;
 
+#define SELECT_SIZE "SELECT sum(size) FROM gn070"
+
 #define INSERT_SAMPLE "INSERT INTO gn070 
(size,type,prio,anonLevel,expire,hash,value) VALUES (?,?,?,?,?,?,?)"
 
 #define SELECT_SAMPLE "SELECT * FROM gn070 WHERE hash=?"
+
 #define SELECT_SAMPLE_COUNT "SELECT count(*) FROM gn070 WHERE hash=?"
+
 #define SELECT_TYPE_SAMPLE "SELECT * FROM gn070 WHERE hash=? AND type=?"
+
 #define SELECT_TYPE_SAMPLE_COUNT "SELECT count(*) FROM gn070 WHERE hash=? AND 
type=?"
 
-#define DELETE_HASH_SAMPLE "DELETE FROM gn070 WHERE hash=? ORDER BY prio ASC 
LIMIT 1"
+/**
+ * Select to prepare for key-based deletion.
+ */
+#define SELECT_HASH_SAMPLE "SELECT * FROM gn070 WHERE hash=? ORDER BY prio ASC 
LIMIT 1"
+
 #define DELETE_GENERIC_SAMPLE "DELETE FROM gn070 WHERE hash=? AND size=? AND 
type=? AND prio=? AND anonLevel=? AND expire=? AND value=? ORDER BY prio ASC 
LIMIT 1"
 
 #define UPDATE_SAMPLE "UPDATE gn070 SET prio=prio+? WHERE hash=? AND value=?"
@@ -219,9 +255,10 @@
         (lens[6] != contentSize) ) {
       char scratch[512];
 
-      GE_LOG(ectx, GE_WARNING | GE_BULK | GE_USER,
-         _("Invalid data in %s.  Trying to fix (by deletion).\n"),
-         _("mysql datastore"));
+      GE_LOG(ectx, 
+            GE_WARNING | GE_BULK | GE_USER,
+            _("Invalid data in %s.  Trying to fix (by deletion).\n"),
+            _("mysql datastore"));
       SNPRINTF(scratch,
               512,
               "DELETE FROM gn070 WHERE NOT ((LENGTH(hash)=%u) AND (size=%u + 
LENGTH(value)))",
@@ -232,10 +269,8 @@
     } else {
       GE_BREAK(ectx, 0); /* should really never happen */
     }
-
     return NULL;
   }
-
   datum = MALLOC(sizeof(Datastore_Datum) + contentSize);
   datum->value.size = htonl(contentSize + sizeof(Datastore_Value));
   datum->value.type = htonl(type);
@@ -327,7 +362,6 @@
       dbhI->dbf = NULL;
       return SYSERR;
     }
-
     dbhI->insert = mysql_stmt_init(dbhI->dbf);
     dbhI->select = mysql_stmt_init(dbhI->dbf);
     dbhI->selectc = mysql_stmt_init(dbhI->dbf);
@@ -380,8 +414,8 @@
                           UPDATE_SAMPLE,
                           strlen(UPDATE_SAMPLE)) ||
        mysql_stmt_prepare(dbhI->deleteh,
-                          DELETE_HASH_SAMPLE,
-                          strlen(DELETE_HASH_SAMPLE)) ||
+                          SELECT_HASH_SAMPLE,
+                          strlen(SELECT_HASH_SAMPLE)) ||
        mysql_stmt_prepare(dbhI->deleteg,
                           DELETE_GENERIC_SAMPLE,
                           strlen(DELETE_GENERIC_SAMPLE)) ) {
@@ -403,8 +437,8 @@
       return SYSERR;
     }
     memset(dbhI->bind,
-        0,
-        sizeof(dbhI->bind));
+          0,
+          sizeof(dbhI->bind));
     dbhI->bind[0].buffer_type = MYSQL_TYPE_LONG; /* size */
     dbhI->bind[1].buffer_type = MYSQL_TYPE_LONG; /* type */
     dbhI->bind[2].buffer_type = MYSQL_TYPE_LONG; /* prio */
@@ -436,7 +470,7 @@
     dbhI->prepare = YES;
   } else
     dbhI->prepare = NO;
-  dbhI->DATABASE_Lock_ = MUTEX_CREATE(NO);
+  dbhI->DATABASE_Lock_ = MUTEX_CREATE(NO);  
   return OK;
 }
 
@@ -499,7 +533,6 @@
 
   mysql_query(dbhI.dbf,
              "SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED");
-
   if (type==0) {
     typestr[0] = '\0';
   } else {
@@ -508,7 +541,6 @@
              "WHERE type=%u ",
             type);
   }
-
   scratch = MALLOC(256);
   SNPRINTF(scratch,
           256, // SQL_BIG_RESULT SQL_BUFFER_RESULT
@@ -520,18 +552,18 @@
              scratch);
   FREE(scratch);
   if (mysql_error(dbhI.dbf)[0]) {
-    LOG_MYSQL(GE_ERROR | GE_ADMIN | GE_BULK, "mysql_query", &dbhI);
+    LOG_MYSQL(GE_ERROR | GE_ADMIN | GE_BULK, 
+             "mysql_query",
+             &dbhI);
     MUTEX_UNLOCK(dbhI.DATABASE_Lock_);
     iclose(&dbhI);
     return SYSERR;
   }
-
   if (!(sql_res=mysql_use_result(dbhI.dbf))) {
     MUTEX_UNLOCK(dbhI.DATABASE_Lock_);
     iclose(&dbhI);
     return SYSERR;
   }
-
   while ((sql_row=mysql_fetch_row(sql_res))) {
     datum = assembleDatum(sql_res,
                          sql_row,
@@ -548,11 +580,12 @@
       break;
     }
     FREE(datum);
-
     count++;
   }
   if (mysql_error(dbhI.dbf)[0]) {
-    LOG_MYSQL(GE_ERROR | GE_ADMIN | GE_BULK, "mysql_query", &dbhI);
+    LOG_MYSQL(GE_ERROR | GE_ADMIN | GE_BULK, 
+             "mysql_query", 
+             &dbhI);
     mysql_free_result(sql_res);
     MUTEX_UNLOCK(dbhI.DATABASE_Lock_);
     iclose(&dbhI);
@@ -564,9 +597,6 @@
   return count;
 }
 
-
-
-
 /**
  * Iterate over the items in the datastore in ascending
  * order of expiration time.
@@ -591,12 +621,9 @@
   dbhI.cnffile = dbh->cnffile; /* shared */
   if (OK != iopen(&dbhI, NO))
     return SYSERR;
-
   MUTEX_LOCK(dbhI.DATABASE_Lock_);
-
   mysql_query(dbhI.dbf,
              "SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED");
-
   if (type==0) {
     typestr[0] = 0;
   } else {
@@ -604,7 +631,6 @@
              32,
             "WHERE type=%u", type);
   }
-
   scratch = MALLOC(256);
   SNPRINTF(scratch, //SQL_BIG_RESULT SQL_BUFFER_RESULT SQL_NO_CACHE
           256,
@@ -616,18 +642,18 @@
              scratch);
   FREE(scratch);
   if (mysql_error(dbhI.dbf)[0]) {
-    LOG_MYSQL(GE_ERROR | GE_ADMIN | GE_BULK, "mysql_query", &dbhI);
+    LOG_MYSQL(GE_ERROR | GE_ADMIN | GE_BULK, 
+             "mysql_query", 
+             &dbhI);
     MUTEX_UNLOCK(dbhI.DATABASE_Lock_);
     iclose(&dbhI);
     return SYSERR;
   }
-
   if (!(sql_res=mysql_use_result(dbhI.dbf))) {
     MUTEX_UNLOCK(dbhI.DATABASE_Lock_);
     iclose(&dbhI);
     return SYSERR;
   }
-
   while ((sql_row=mysql_fetch_row(sql_res))) {
     datum = assembleDatum(sql_res,
                          sql_row,
@@ -638,7 +664,9 @@
       return count;
     }
     if ( (iter != NULL) &&
-        (SYSERR == iter(&datum->key, &datum->value, closure) ) ) {
+        (SYSERR == iter(&datum->key, 
+                        &datum->value, 
+                        closure) ) ) {
       count = SYSERR;
       FREE(datum);
       break;
@@ -647,7 +675,9 @@
     count++;
   }            
   if (mysql_error(dbhI.dbf)[0]) {
-    LOG_MYSQL(GE_ERROR | GE_ADMIN | GE_BULK, "mysql_query", &dbhI);
+    LOG_MYSQL(GE_ERROR | GE_ADMIN | GE_BULK, 
+             "mysql_query", 
+             &dbhI);
     mysql_free_result(sql_res);
     MUTEX_UNLOCK(dbhI.DATABASE_Lock_);
     iclose(&dbhI);
@@ -697,13 +727,15 @@
     return iterateLowPriority(type, iter, closure);
 
 #if DEBUG_MYSQL
-  IF_GELOG(ectx, GE_DEBUG | GE_REQUEST | GE_USER,
-       hash2enc(query,
-                &enc));
-  GE_LOG(ectx, GE_DEBUG | GE_REQUEST | GE_USER,
-      "MySQL looks for `%s' of type %u\n",
-      &enc,
-      type);
+  IF_GELOG(ectx, 
+          GE_DEBUG | GE_REQUEST | GE_USER,
+          hash2enc(query,
+                   &enc));
+  GE_LOG(ectx, 
+        GE_DEBUG | GE_REQUEST | GE_USER,
+        "MySQL looks for `%s' of type %u\n",
+        &enc,
+        type);
 #endif
   MUTEX_LOCK(dbh->DATABASE_Lock_);
   if (type != 0) {
@@ -724,11 +756,12 @@
   GE_ASSERT(ectx, mysql_stmt_param_count(stmt) <= 2);
   sql_res = mysql_stmt_result_metadata(stmt);
   if (! sql_res) {
-    GE_LOG(ectx, GE_ERROR | GE_BULK | GE_USER,
-       _("`%s' failed at %s:%d with error: %s\n"),
-       "mysql_stmt_result_metadata",
-       __FILE__, __LINE__,
-       mysql_stmt_error(stmt));
+    GE_LOG(ectx, 
+          GE_ERROR | GE_BULK | GE_USER,
+          _("`%s' failed at %s:%d with error: %s\n"),
+          "mysql_stmt_result_metadata",
+          __FILE__, __LINE__,
+          mysql_stmt_error(stmt));
     MUTEX_UNLOCK(dbh->DATABASE_Lock_);
     return SYSERR;
   }
@@ -739,20 +772,22 @@
   }
   if (mysql_stmt_bind_param(stmt,
                            dbh->sbind)) {
-    GE_LOG(ectx, GE_ERROR | GE_BULK | GE_USER,
-       _("`%s' failed at %s:%d with error: %s\n"),
-       "mysql_stmt_bind_param",
-       __FILE__, __LINE__,
-       mysql_stmt_error(stmt));
+    GE_LOG(ectx, 
+          GE_ERROR | GE_BULK | GE_USER,
+          _("`%s' failed at %s:%d with error: %s\n"),
+          "mysql_stmt_bind_param",
+          __FILE__, __LINE__,
+          mysql_stmt_error(stmt));
     MUTEX_UNLOCK(dbh->DATABASE_Lock_);
     return SYSERR;
   }
   if (mysql_stmt_execute(stmt)) {
-    GE_LOG(ectx, GE_ERROR | GE_BULK | GE_USER,
-       _("`%s' failed at %s:%d with error: %s\n"),
-       "mysql_stmt_execute",
-       __FILE__, __LINE__,
-       mysql_stmt_error(stmt));
+    GE_LOG(ectx, 
+          GE_ERROR | GE_BULK | GE_USER,
+          _("`%s' failed at %s:%d with error: %s\n"),
+          "mysql_stmt_execute",
+          __FILE__, __LINE__,
+          mysql_stmt_error(stmt));
     MUTEX_UNLOCK(dbh->DATABASE_Lock_);
     return SYSERR;
   }
@@ -772,21 +807,23 @@
   dbh->bind[6].buffer_length = MAX_DATUM_SIZE;
   if (mysql_stmt_bind_result(stmt,
                             dbh->bind)) {
-    GE_LOG(ectx, GE_ERROR | GE_BULK | GE_USER,
-       _("`%s' failed at %s:%d with error: %s\n"),
-       "mysql_stmt_bind_result",
-       __FILE__, __LINE__,
-       mysql_stmt_error(stmt));
+    GE_LOG(ectx,
+          GE_ERROR | GE_BULK | GE_USER,
+          _("`%s' failed at %s:%d with error: %s\n"),
+          "mysql_stmt_bind_result",
+          __FILE__, __LINE__,
+          mysql_stmt_error(stmt));
     MUTEX_UNLOCK(dbh->DATABASE_Lock_);
     FREE(datum);
     return SYSERR;
   }
   if (mysql_stmt_store_result(stmt)) {
-    GE_LOG(ectx, GE_ERROR | GE_BULK | GE_USER,
-       _("`%s' failed at %s:%d with error: %s\n"),
-       "mysql_stmt_store_result",
-       __FILE__, __LINE__,
-       mysql_stmt_error(stmt));
+    GE_LOG(ectx, 
+          GE_ERROR | GE_BULK | GE_USER,
+          _("`%s' failed at %s:%d with error: %s\n"),
+          "mysql_stmt_store_result",
+          __FILE__, __LINE__,
+          mysql_stmt_error(stmt));
     MUTEX_UNLOCK(dbh->DATABASE_Lock_);
     FREE(datum);
     return SYSERR;
@@ -799,9 +836,10 @@
       char scratch[512];
 
       mysql_free_result(sql_res);
-      GE_LOG(ectx, GE_WARNING | GE_BULK | GE_USER,
-         _("Invalid data in %s.  Trying to fix (by deletion).\n"),
-         _("mysql datastore"));
+      GE_LOG(ectx, 
+            GE_WARNING | GE_BULK | GE_USER,
+            _("Invalid data in %s.  Trying to fix (by deletion).\n"),
+            _("mysql datastore"));
       SNPRINTF(scratch,
               512,
               "DELETE FROM gn070 WHERE NOT ((LENGTH(hash)=%u) AND (size=%u + 
LENGTH(value)))",
@@ -822,9 +860,10 @@
       datum->anonymityLevel = htonl(level);
       datum->expirationTime = htonll(expiration);
 #if DEBUG_MYSQL
-      GE_LOG(ectx, GE_DEBUG | GE_REQUEST | GE_USER,
-         "Found in database block with type %u.\n",
-         ntohl(*(int*)&datum[1]));
+      GE_LOG(ectx, 
+            GE_DEBUG | GE_REQUEST | GE_USER,
+            "Found in database block with type %u.\n",
+            ntohl(*(int*)&datum[1]));
 #endif
       if( SYSERR == iter(&key,
                         datum,
@@ -836,34 +875,37 @@
     datasize = MAX_DATUM_SIZE;
   }
   if (mysql_stmt_errno(stmt)) {
-    GE_LOG(ectx, GE_ERROR | GE_BULK | GE_USER,
-       _("`%s' failed at %s:%d with error: %s\n"),
-       "mysql_stmt_fetch",
-       __FILE__, __LINE__,
-       mysql_stmt_error(stmt));
+    GE_LOG(ectx, 
+          GE_ERROR | GE_BULK | GE_USER,
+          _("`%s' failed at %s:%d with error: %s\n"),
+          "mysql_stmt_fetch",
+          __FILE__, __LINE__,
+          mysql_stmt_error(stmt));
   }
   mysql_free_result(sql_res);
   FREE(datum);
   MUTEX_UNLOCK(dbh->DATABASE_Lock_);
 
 #if DEBUG_MYSQL
-  IF_GELOG(ectx, GE_DEBUG | GE_REQUEST | GE_USER,
-       hash2enc(query,
-                &enc));
+  IF_GELOG(ectx, 
+          GE_DEBUG | GE_REQUEST | GE_USER,
+          hash2enc(query,
+                   &enc));
   if (count > 0) {
-    GE_LOG(ectx, GE_DEBUG | GE_REQUEST | GE_USER,
-       "MySQL found %d results for `%s' of type %u.\n",
-       count,
-       &enc,
-       type);
+    GE_LOG(ectx, 
+          GE_DEBUG | GE_REQUEST | GE_USER,
+          "MySQL found %d results for `%s' of type %u.\n",
+          count,
+          &enc,
+          type);
   } else {
-    GE_LOG(ectx, GE_DEBUG | GE_REQUEST | GE_USER,
-       "MySQL iteration aborted looking for `%s' of type %u.\n",
-       &enc,
-       type);
+    GE_LOG(ectx, 
+          GE_DEBUG | GE_REQUEST | GE_USER,
+          "MySQL iteration aborted looking for `%s' of type %u.\n",
+          &enc,
+          type);
   }
 #endif
-
   return count;
 }
 
@@ -890,24 +932,23 @@
     return SYSERR;
   }
   MUTEX_LOCK(dbh->DATABASE_Lock_);
-
   contentSize = ntohl(value->size)-sizeof(Datastore_Value);
   hashSize = sizeof(HashCode512);
-
   size = ntohl(value->size);
   type = ntohl(value->type);
   prio = ntohl(value->prio);
   level = ntohl(value->anonymityLevel);
   expiration = ntohll(value->expirationTime);
-
 #if DEBUG_MYSQL
-  IF_GELOG(ectx, GE_DEBUG | GE_REQUEST | GE_USER,
-       hash2enc(key,
-                &enc));
-  GE_LOG(ectx, GE_DEBUG | GE_REQUEST | GE_USER,
-      "Storing in database block with type %u and key %s.\n",
-      type,
-      &enc);
+  IF_GELOG(ectx, 
+          GE_DEBUG | GE_REQUEST | GE_USER,
+          hash2enc(key,
+                   &enc));
+  GE_LOG(ectx, 
+        GE_DEBUG | GE_REQUEST | GE_USER,
+        "Storing in database block with type %u and key %s.\n",
+        type,
+        &enc);
 #endif
   dbh->bind[0].buffer = (char*) &size;
   dbh->bind[1].buffer = (char*) &type;
@@ -921,25 +962,30 @@
 
   if (mysql_stmt_bind_param(dbh->insert,
                            dbh->bind)) {
-    GE_LOG(ectx, GE_ERROR | GE_BULK | GE_USER,
-       _("`%s' failed at %s:%d with error: %s\n"),
-       "mysql_stmt_bind_param",
-       __FILE__, __LINE__,
-       mysql_stmt_error(dbh->insert));
+    GE_LOG(ectx, 
+          GE_ERROR | GE_BULK | GE_USER,
+          _("`%s' failed at %s:%d with error: %s\n"),
+          "mysql_stmt_bind_param",
+          __FILE__, __LINE__,
+          mysql_stmt_error(dbh->insert));
     MUTEX_UNLOCK(dbh->DATABASE_Lock_);
     return SYSERR;
   }
 
   if (mysql_stmt_execute(dbh->insert)) {
-    GE_LOG(ectx, GE_ERROR | GE_BULK | GE_USER,
-       _("`%s' failed at %s:%d with error: %s\n"),
-       "mysql_stmt_execute",
-       __FILE__, __LINE__,
-       mysql_stmt_error(dbh->insert));
+    GE_LOG(ectx, 
+          GE_ERROR | GE_BULK | GE_USER,
+          _("`%s' failed at %s:%d with error: %s\n"),
+          "mysql_stmt_execute",
+          __FILE__, __LINE__,
+          mysql_stmt_error(dbh->insert));
     MUTEX_UNLOCK(dbh->DATABASE_Lock_);
     return SYSERR;
   }
   MUTEX_UNLOCK(dbh->DATABASE_Lock_);
+  MUTEX_LOCK(lock);
+  content_size += ntohl(value->size);
+  MUTEX_UNLOCK(lock);
   return OK;
 }
 
@@ -962,78 +1008,213 @@
   unsigned int anon;
   unsigned long long expiration;
   unsigned long datasize;
+  Datastore_Value * svalue;
+  MYSQL_RES * sql_res;
+  unsigned int rtype;
+  unsigned int level;
+  HashCode512 skey;
 #if DEBUG_MYSQL
   EncName enc;
 
-  IF_GELOG(ectx, GE_DEBUG | GE_REQUEST | GE_USER,
-       hash2enc(key,
-                &enc));
-  GE_LOG(ectx, GE_DEBUG | GE_REQUEST | GE_USER,
-      "MySQL is executing deletion request for content of query `%s' and type 
%u\n",
-      &enc,
-      value == NULL ? 0 : ntohl(value->type));
+  IF_GELOG(ectx, 
+          GE_DEBUG | GE_REQUEST | GE_USER,
+          hash2enc(key,
+                   &enc));
+  GE_LOG(ectx,
+        GE_DEBUG | GE_REQUEST | GE_USER,
+        "MySQL is executing deletion request for content of query `%s' and 
type %u\n",
+        &enc,
+        value == NULL ? 0 : ntohl(value->type));
 #endif
   MUTEX_LOCK(dbh->DATABASE_Lock_);
-
   twenty = sizeof(HashCode512);
-
-  if(value == NULL) {
+  svalue = NULL;
+  if (value == NULL) {    
     stmt = dbh->deleteh;
     dbh->dbind[0].buffer = (char*) key;
     dbh->dbind[0].length = &twenty;
     GE_ASSERT(ectx, mysql_stmt_param_count(stmt) <= 1);
-  } else {
-    stmt = dbh->deleteg;
-    type = ntohl(value->type);
-    size = ntohl(value->size);
-    prio = ntohl(value->prio);
-    anon = ntohl(value->anonymityLevel);
-    expiration = ntohll(value->expirationTime);
-    datasize = ntohl(value->size) - sizeof(Datastore_Value);
-    dbh->dbind[0].buffer = (char*) key;
-    dbh->dbind[0].length = &twenty;
-    dbh->dbind[1].buffer = (char*) &size;
-    dbh->dbind[2].buffer = (char*) &type;
-    dbh->dbind[3].buffer = (char*) &prio;
-    dbh->dbind[4].buffer = (char*) &anon;
-    dbh->dbind[5].buffer = (char*) &expiration;
-    dbh->dbind[6].buffer = (char*) &value[1];
-    dbh->dbind[6].length = &datasize;
-    GE_ASSERT(ectx, mysql_stmt_param_count(stmt) <= 7);
+      
+    sql_res = mysql_stmt_result_metadata(stmt);
+    if (! sql_res) {
+      GE_LOG(ectx, 
+            GE_ERROR | GE_BULK | GE_USER,
+            _("`%s' failed at %s:%d with error: %s\n"),
+            "mysql_stmt_result_metadata",
+            __FILE__, __LINE__,
+            mysql_stmt_error(stmt));
+      MUTEX_UNLOCK(dbh->DATABASE_Lock_);
+      return SYSERR;
+    }
+    if (7 != mysql_num_fields(sql_res)) {
+      GE_BREAK(ectx, 0);
+      MUTEX_UNLOCK(dbh->DATABASE_Lock_);
+      return SYSERR;
+    }
+    if (mysql_stmt_bind_param(stmt,
+                             dbh->dbind)) {
+      GE_LOG(ectx, 
+            GE_ERROR | GE_BULK | GE_USER,
+            _("`%s' failed at %s:%d with error: %s\n"),
+            "mysql_stmt_bind_param",
+            __FILE__, __LINE__,
+            mysql_stmt_error(stmt));
+      MUTEX_UNLOCK(dbh->DATABASE_Lock_);
+      return SYSERR;
+    }
+    if (mysql_stmt_execute(stmt)) {
+      GE_LOG(ectx, 
+            GE_ERROR | GE_BULK | GE_USER,
+            _("`%s' failed at %s:%d with error: %s\n"),
+            "mysql_stmt_execute",
+            __FILE__, __LINE__,
+            mysql_stmt_error(stmt));
+      MUTEX_UNLOCK(dbh->DATABASE_Lock_);
+      return SYSERR;
+    }
+    svalue = MALLOC(sizeof(Datastore_Value) + MAX_DATUM_SIZE);
+    twenty = sizeof(HashCode512);
+    dbh->bind[0].buffer = (char*) &size;
+    dbh->bind[1].buffer = (char*) &rtype;
+    dbh->bind[2].buffer = (char*) &prio;
+    dbh->bind[3].buffer = (char*) &level;
+    dbh->bind[4].buffer = (char*) &expiration;
+    dbh->bind[5].buffer = (char*) &skey;
+    dbh->bind[6].buffer = (char*) &svalue[1];
+    dbh->bind[5].length = &twenty;
+    dbh->bind[6].length = &datasize;
+    dbh->bind[5].buffer_length = sizeof(HashCode512);
+    dbh->bind[6].buffer_length = MAX_DATUM_SIZE;
+    if (mysql_stmt_bind_result(stmt,
+                              dbh->bind)) {
+      GE_LOG(ectx,
+            GE_ERROR | GE_BULK | GE_USER,
+            _("`%s' failed at %s:%d with error: %s\n"),
+            "mysql_stmt_bind_result",
+            __FILE__, __LINE__,
+            mysql_stmt_error(stmt));
+      MUTEX_UNLOCK(dbh->DATABASE_Lock_);
+      FREE(svalue);
+      return SYSERR;
+    }
+    if (mysql_stmt_store_result(stmt)) {
+      GE_LOG(ectx, 
+            GE_ERROR | GE_BULK | GE_USER,
+            _("`%s' failed at %s:%d with error: %s\n"),
+            "mysql_stmt_store_result",
+            __FILE__, __LINE__,
+            mysql_stmt_error(stmt));
+      MUTEX_UNLOCK(dbh->DATABASE_Lock_);
+      FREE(svalue);
+      return SYSERR;
+    }
+    datasize = MAX_DATUM_SIZE;
+    if (0 != mysql_stmt_fetch(stmt)) {
+      GE_LOG(ectx, 
+            GE_ERROR | GE_BULK | GE_USER,
+            _("`%s' failed at %s:%d with error: %s\n"),
+            "mysql_stmt_fetch",
+            __FILE__, __LINE__,
+            mysql_stmt_error(stmt));
+      MUTEX_UNLOCK(dbh->DATABASE_Lock_);
+      FREE(svalue);
+      return SYSERR;
+    }
+    if ( (twenty != sizeof(HashCode512)) ||
+        (datasize != size - sizeof(Datastore_Value)) ) {
+      char scratch[512];
+
+      mysql_free_result(sql_res);
+      GE_LOG(ectx, 
+            GE_WARNING | GE_BULK | GE_USER,
+            _("Invalid data in %s.  Trying to fix (by deletion).\n"),
+            _("mysql datastore"));
+      SNPRINTF(scratch,
+              512,
+              "DELETE FROM gn070 WHERE NOT ((LENGTH(hash)=%u) AND (size=%u + 
LENGTH(value)))",
+              sizeof(HashCode512),
+              sizeof(Datastore_Value));
+      if (0 != mysql_query(dbh->dbf, scratch))
+       LOG_MYSQL(GE_ERROR | GE_ADMIN | GE_BULK, 
+                 "mysql_query", dbh);
+      FREE(svalue);
+      MUTEX_UNLOCK(dbh->DATABASE_Lock_);
+      return 1;
+    }
+    mysql_free_result(sql_res);
+    svalue->size = htonl(size);
+    svalue->type = htonl(rtype);
+    svalue->prio = htonl(prio);
+    svalue->anonymityLevel = htonl(level);
+    svalue->expirationTime = htonll(expiration);
+    value = svalue;
   }
+
+  stmt = dbh->deleteg;
+  type = ntohl(value->type);
+  size = ntohl(value->size);
+  prio = ntohl(value->prio);
+  anon = ntohl(value->anonymityLevel);
+  expiration = ntohll(value->expirationTime);
+  datasize = ntohl(value->size) - sizeof(Datastore_Value);
+  dbh->dbind[0].buffer = (char*) key;
+  dbh->dbind[0].length = &twenty;
+  dbh->dbind[1].buffer = (char*) &size;
+  dbh->dbind[2].buffer = (char*) &type;
+  dbh->dbind[3].buffer = (char*) &prio;
+  dbh->dbind[4].buffer = (char*) &anon;
+  dbh->dbind[5].buffer = (char*) &expiration;
+  dbh->dbind[6].buffer = (char*) &value[1];
+  dbh->dbind[6].length = &datasize;
+#if 0
+  dbh->dbind[0].buffer_length = sizeof(HashCode512);
+  dbh->dbind[6].buffer_length = size - sizeof(Datastore_Value);
+#endif
+  GE_ASSERT(ectx, mysql_stmt_param_count(stmt) <= 7);
   if (mysql_stmt_bind_param(stmt,
                            dbh->dbind)) {
-    GE_LOG(ectx, GE_ERROR | GE_BULK | GE_USER,
-       _("`%s' failed at %s:%d with error: %s\n"),
-       "mysql_stmt_bind_param",
-       __FILE__, __LINE__,
-       mysql_stmt_error(stmt));
+    GE_LOG(ectx, 
+          GE_ERROR | GE_BULK | GE_USER,
+          _("`%s' failed at %s:%d with error: %s\n"),
+          "mysql_stmt_bind_param",
+          __FILE__, __LINE__,
+          mysql_stmt_error(stmt));
     MUTEX_UNLOCK(dbh->DATABASE_Lock_);
+    if (svalue != NULL)
+      FREE(svalue);
     return SYSERR;
   }
   if (mysql_stmt_execute(stmt)) {
-    GE_LOG(ectx, GE_ERROR | GE_BULK | GE_USER,
-       _("`%s' failed at %s:%d with error: %s\n"),
-       "mysql_stmt_execute",
-       __FILE__, __LINE__,
-       mysql_stmt_error(stmt));
+    GE_LOG(ectx, 
+          GE_ERROR | GE_BULK | GE_USER,
+          _("`%s' failed at %s:%d with error: %s\n"),
+          "mysql_stmt_execute",
+          __FILE__, __LINE__,
+          mysql_stmt_error(stmt));
     MUTEX_UNLOCK(dbh->DATABASE_Lock_);
+    if (svalue != NULL)
+      FREE(svalue);
     return SYSERR;
   }
   count = mysql_stmt_affected_rows(stmt);
   MUTEX_UNLOCK(dbh->DATABASE_Lock_);
 #if DEBUG_MYSQL
-  GE_LOG(ectx, GE_DEBUG | GE_REQUEST | GE_USER,
-      "MySQL DELETE operation affected %d rows.\n",
-      count);
+  GE_LOG(ectx, 
+        GE_DEBUG | GE_REQUEST | GE_USER,
+        "MySQL DELETE operation affected %d rows.\n",
+        count);
 #endif
+  MUTEX_LOCK(lock);
+  content_size -= ntohl(value->size);
+  MUTEX_UNLOCK(lock);
+  if (svalue != NULL)
+    FREE(svalue);
   return count;
 }
 
 /**
  * Update the priority for a particular key
  * in the datastore.
- *
  */
 static int update(const HashCode512 * key,
                  const Datastore_Value * value,
@@ -1052,11 +1233,12 @@
   GE_ASSERT(ectx, mysql_stmt_param_count(dbh->update) <= 3);
   if (mysql_stmt_bind_param(dbh->update,
                            dbh->ubind)) {
-    GE_LOG(ectx, GE_ERROR | GE_BULK | GE_USER,
-       _("`%s' failed at %s:%d with error: %s\n"),
-       "mysql_stmt_bind_param",
-       __FILE__, __LINE__,
-       mysql_stmt_error(dbh->update));
+    GE_LOG(ectx,
+          GE_ERROR | GE_BULK | GE_USER,
+          _("`%s' failed at %s:%d with error: %s\n"),
+          "mysql_stmt_bind_param",
+          __FILE__, __LINE__,
+          mysql_stmt_error(dbh->update));
     MUTEX_UNLOCK(dbh->DATABASE_Lock_);
     return SYSERR;
   }
@@ -1066,11 +1248,12 @@
    * at all in this context.)
    */
   if (mysql_stmt_execute(dbh->update)) {
-    GE_LOG(ectx, GE_ERROR | GE_BULK | GE_USER,
-       _("`%s' failed at %s:%d with error: %s\n"),
-       "mysql_stmt_execute",
-       __FILE__, __LINE__,
-       mysql_stmt_error(dbh->update));
+    GE_LOG(ectx, 
+          GE_ERROR | GE_BULK | GE_USER,
+          _("`%s' failed at %s:%d with error: %s\n"),
+          "mysql_stmt_execute",
+          __FILE__, __LINE__,
+          mysql_stmt_error(dbh->update));
     MUTEX_UNLOCK(dbh->DATABASE_Lock_);
     return SYSERR;
   }
@@ -1078,7 +1261,6 @@
   return OK;
 }
 
-
 /**
  * Get the current on-disk size of the SQ store.
  * Estimates are fine, if that's the only thing
@@ -1086,69 +1268,14 @@
  * @return number of bytes used on disk
  */
 static unsigned long long getSize() {
-  MYSQL_RES * sql_res;
-  MYSQL_ROW sql_row;
-  long long avgRowLen = -1;
-  long long rowsInTable = 0;
-  unsigned long long bytesUsed;
-
-  MUTEX_LOCK(dbh->DATABASE_Lock_);
-
-  /* find out average row length in bytes */
-  mysql_query(dbh->dbf,
-             "SHOW TABLE STATUS LIKE 'gn070'");
-  if (mysql_error(dbh->dbf)[0]) {
-    DIE_MYSQL("mysql_query", dbh); /* this MUST not fail... */
-    MUTEX_UNLOCK(dbh->DATABASE_Lock_);
-    return SYSERR;     /* shouldn't get here */
-  }
-  if ((sql_res=mysql_store_result(dbh->dbf))) {
-    int rows = mysql_num_fields(sql_res);
-    sql_row = mysql_fetch_row(sql_res);
-    if (sql_row == NULL) {
-      GE_LOG(ectx, GE_WARNING | GE_BULK | GE_USER,
-         _("Query `%s' had no results.\n"),
-         "SHOW TABLE STATUS LIKE 'gn070'");
-      MUTEX_UNLOCK(dbh->DATABASE_Lock_);
-      GE_BREAK(ectx, 0);
-      return 0;        /* shouldn't get here */
-    }
-    GE_ASSERT(ectx,  (dbh->avgLength_ID < rows) &&
-                  (dbh->avgLength_ID >= 0) );
-    if (sql_row[dbh->avgLength_ID] != NULL)
-      avgRowLen = atoll(sql_row[dbh->avgLength_ID]);
-    else
-      avgRowLen = -1;
-
-    mysql_free_result(sql_res);
-  }
-  GE_ASSERT(ectx, avgRowLen >= 0);
-  /* find number of entries (rows) */
-  mysql_query(dbh->dbf,
-             "SELECT COUNT(*) FROM gn070");
-  if (!(sql_res=mysql_store_result(dbh->dbf))) {
-    MUTEX_UNLOCK(dbh->DATABASE_Lock_);
-    DIE_MYSQL("mysql_store_result", dbh);
-  }
-
-  if ((sql_row=mysql_fetch_row(sql_res))) {
-    int cols = mysql_num_fields(sql_res);
-    GE_ASSERT(ectx, cols > 0);
-    if (sql_row[0] != NULL)
-      rowsInTable = atoll(sql_row[0]);
-    else
-      rowsInTable = 0;
-  }
-  mysql_free_result(sql_res);
-
-  MUTEX_UNLOCK(dbh->DATABASE_Lock_);
-
-  bytesUsed = rowsInTable * avgRowLen;
-
+  unsigned long long ret;
+  
+  MUTEX_LOCK(lock);
+  ret = content_size;
   if (stats)
-    stats->set(stat_size, bytesUsed);
-
-  return bytesUsed;
+    stats->set(stat_size, ret);
+  MUTEX_UNLOCK(lock);
+  return ret * 2; /* common overhead seems to be 100%! */
 }
 
 /**
@@ -1158,21 +1285,26 @@
 static void drop() {
   mysql_query(dbh->dbf,
              "DROP TABLE gn070");
+  if (mysql_error(dbh->dbf)[0]) {
+    LOG_MYSQL(GE_ERROR | GE_ADMIN | GE_BULK, 
+             "mysql_query",
+             dbh);
+  } else
+    content_size = 0;
 }
 
-
-
-
 SQstore_ServiceAPI *
 provide_module_sqstore_mysql(CoreAPIForApplication * capi) {
   static SQstore_ServiceAPI api;
-
-  MYSQL_RES * sql_res;
+  State_ServiceAPI * state;
   char * cnffile;
   FILE * fp;
   struct passwd * pw;
   size_t nX;
   char * home_dir;
+  unsigned long long * sb;
+  MYSQL_RES *sql_res;
+  MYSQL_ROW sql_row;
 
   ectx = capi->ectx;
   coreAPI = capi;
@@ -1213,7 +1345,12 @@
         cnffile);
   fp = FOPEN(cnffile, "r");
   if (!fp) {
-    GE_LOG_STRERROR_FILE(ectx, GE_ERROR | GE_ADMIN | GE_BULK, "fopen", 
cnffile);
+    GE_LOG_STRERROR_FILE(ectx, 
+                        GE_ERROR | GE_ADMIN | GE_BULK, 
+                        "fopen", 
+                        cnffile);
+    if (stats != NULL)
+      coreAPI->releaseService(stats);
     FREE(cnffile);
     return NULL;
   } else {
@@ -1222,78 +1359,51 @@
 
   dbh = MALLOC(sizeof(mysqlHandle));
   dbh->cnffile = cnffile;
-
   if (OK != iopen(dbh, YES)) {
     FREE(cnffile);
     FREE(dbh);
-    GE_LOG(ectx, GE_ERROR | GE_BULK | GE_USER,
-       _("Failed to load MySQL database module.  Check that MySQL is running 
and configured properly!\n"));
+    GE_LOG(ectx, 
+          GE_ERROR | GE_BULK | GE_USER,
+          _("Failed to load MySQL database module.  Check that MySQL is 
running and configured properly!\n"));
     dbh = NULL;
+    if (stats != NULL)
+      coreAPI->releaseService(stats);
     return NULL;
   }
 
-  /* Find out which column contains the avg row length field and assume
-   * that mysqld always gives it in the same order across calls :) */
-  mysql_query(dbh->dbf,
-             "SHOW TABLE STATUS LIKE 'gn070'");
-  if (mysql_error(dbh->dbf)[0]) {
-    LOG_MYSQL(GE_ERROR | GE_ADMIN | GE_BULK,
-             "mysql_query",
-             dbh);
-    iclose(dbh);
-    FREE(dbh);
-    FREE(cnffile);
-    return NULL;
-  }
-  if((sql_res=mysql_store_result(dbh->dbf))) {
-    MYSQL_FIELD * sql_fields;
-    int num_fields;
-    int j;
-    int found = NO;
+  lock = MUTEX_CREATE(NO);
+  state = coreAPI->requestService("state");
+  sb = NULL;
+  if (sizeof(unsigned long long)
+      != state->read(ectx,
+                    "mysql-size",
+                    (void*) &sb)) {
 
-    num_fields=mysql_num_fields(sql_res);
-    if(num_fields<=0) {
-      GE_BREAK(ectx, 0);
-      iclose(dbh);
-      FREE(dbh);
-      FREE(cnffile);
-      return NULL;
+    /* need to recompute! */
+    sql_res = NULL;
+    mysql_query(dbh->dbf,
+               SELECT_SIZE);
+    if ( (mysql_error(dbh->dbf)[0]) ||
+        (!(sql_res=mysql_use_result(dbh->dbf))) ||
+        (!(sql_row=mysql_fetch_row(sql_res))) ) {
+      LOG_MYSQL(GE_ERROR | GE_ADMIN | GE_BULK, 
+               "mysql_query",
+               dbh);
+      content_size = 0;
+    } else {
+      SSCANF(sql_row[1], "%llu", &content_size);
     }
-    sql_fields=mysql_fetch_fields(sql_res);
-    if(sql_fields==NULL) {
-      GE_BREAK(ectx, 0);
-      iclose(dbh);
-      FREE(dbh);
-      FREE(cnffile);
-      return NULL;
-    }
-    dbh->avgLength_ID = -1;
-    for(j=0;j<num_fields;j++) {
-      if (strcmp(sql_fields[j].name,
-                "Avg_row_length")==0) {
-        found = YES;
-        dbh->avgLength_ID = j;
-       break;
-      }
-    }
-    GE_ASSERT(ectx, dbh->avgLength_ID != -1);
-    mysql_free_result(sql_res);
-    if (found == NO) {
-      GE_BREAK(ectx, 0);
-      /* avg_row_length not found in SHOW TABLE STATUS */
-      iclose(dbh);
-      FREE(dbh);
-      FREE(cnffile);
-      return NULL;
-    }
+    if (sql_res != NULL)
+      mysql_free_result(sql_res);
   } else {
-    GE_BREAK(ectx, 0);
-    iclose(dbh);
-    FREE(dbh);
-    FREE(cnffile);
-    return NULL;
+    content_size = *sb;
+    FREE(sb);
+    /* no longer valid! remember it by deleting 
+       the outdated state file! */
+    state->unlink(ectx,
+                 "mysql-size");
   }
-
+  coreAPI->releaseService(state);
   api.getSize = &getSize;
   api.put = &put;
   api.get = &get;
@@ -1309,6 +1419,7 @@
  * Shutdown the module.
  */
 void release_module_sqstore_mysql() {
+  State_ServiceAPI * state;
   iclose(dbh);
   FREE(dbh->cnffile);
   FREE(dbh);
@@ -1316,7 +1427,15 @@
 
   if (stats != NULL)
     coreAPI->releaseService(stats);
+  MUTEX_DESTROY(lock);
+  state = coreAPI->requestService("state");
+  state->write(ectx,
+              "mysql-size",
+              sizeof(unsigned long long),
+              &content_size);
+  coreAPI->releaseService(state);
   ectx = NULL;
+  coreAPI = NULL;
 }
 
 /* end of mysql.c */

Modified: GNUnet/src/applications/sqstore_mysql/mysqltest2.c
===================================================================
--- GNUnet/src/applications/sqstore_mysql/mysqltest2.c  2006-11-01 21:14:26 UTC 
(rev 3608)
+++ GNUnet/src/applications/sqstore_mysql/mysqltest2.c  2006-11-02 14:10:51 UTC 
(rev 3609)
@@ -39,12 +39,6 @@
  * shrinks.  The scanning of the entire mysql directory during
  * each report is also likely to be the cause of a minor
  * slowdown compared to sqlite.<p>
- *
- *
- * Note: the MySQL API *dramatically* under-reports the stored
- * content (19k vs. 84k for some test-run).  So there MUST BE
- * a bug in our mysql code that avoids counting some data or
- * over-estimates the size of deletions.
  */
 
 #include "platform.h"





reply via email to

[Prev in Thread] Current Thread [Next in Thread]