]> jfr.im git - irc/quakenet/newserv.git/commitdiff
Fix up migration to use transactions, also start a commands module.
authorChris Porter <redacted>
Tue, 30 Sep 2008 18:43:41 +0000 (19:43 +0100)
committerChris Porter <redacted>
Tue, 30 Sep 2008 18:43:41 +0000 (19:43 +0100)
core/hooks.h
trusts/Makefile.in
trusts/db-migration.c
trusts/db.c
trusts/migration.c
trusts/trusts.c
trusts/trusts.h
trusts/trusts_commands.c [new file with mode: 0644]

index 12c30b7e899a0a59e8b7698b7963ca6b9f8e824e..8d456c5c26e4961676b50ca6639872dccb2f5560 100644 (file)
@@ -75,6 +75,8 @@
 #define HOOK_AUTH_FLAGSUPDATED     801 /* Argument is void*[2] (authname*, u_int64_t*) */
 #define HOOK_AUTH_LOSTAUTHNAME     802 /* Argument is authname* */
 
+#define HOOK_TRUSTS_DB_LOADED      901 /* No arg */
+
 #define PRIORITY_DEFAULT           0
 
 #define PRIORITY_MAX               LONG_MIN
index 3490f03c2c48a28e854e04ff7e655c3f4c9f8ac3..0f34ef1b895997464455d69cbee54d610141e9df 100644 (file)
@@ -1,6 +1,8 @@
 @include@ @includel@../build.mk@includel@
 
 .PHONY: all
-all: trusts.so
+all: trusts.so trusts_commands.so
 
 trusts.so: trusts.o migration.o db.o db-migration.o
+
+trusts_commands.so: trusts_commands.o
index 9ecdf473a1f83a6e210cf740c30cbbb20db32d32..694ce8259d3b09ee4231e5ddd9b0c0bb0a6805fa 100644 (file)
@@ -12,6 +12,7 @@ static void tm_final(void *, int);
 
 trustmigration *migration_start(TrustMigrationGroup, TrustMigrationHost, TrustMigrationFini, void *);
 void migration_stop(trustmigration *);
+void createtrusttables(int migration);
 
 struct callbackdata {
   void *tag;
@@ -22,12 +23,12 @@ int trusts_migration_start(TrustDBMigrationCallback callback, void *tag) {
   struct callbackdata *cbd;
 
   if(migration)
-    return 0;
+    return 1;
 
   if(callback) {
     cbd = malloc(sizeof(struct callbackdata));
     if(!cbd)
-      return 0;
+      return 2;
 
     cbd->callback = callback;
     cbd->tag = tag;
@@ -35,16 +36,17 @@ int trusts_migration_start(TrustDBMigrationCallback callback, void *tag) {
     cbd = NULL;
   }
 
-  trustsdb->squery(trustsdb, "DELETE FROM ?", "T", "groups");
-  trustsdb->squery(trustsdb, "DELETE FROM ?", "T", "hosts");
+  createtrusttables(1);
+  trustsdb->squery(trustsdb, "DELETE FROM ?", "T", "migration_groups");
+  trustsdb->squery(trustsdb, "DELETE FROM ?", "T", "migration_hosts");
 
   migration = migration_start(tm_group, tm_host, tm_final, cbd);
   if(!migration) {
     free(cbd);
-    return 0;
+    return 3;
   }
 
-  return 1;
+  return 0;
 }
 
 void trusts_migration_stop(void) {
@@ -60,29 +62,71 @@ static void tm_group(void *tag, unsigned int id, char *name, unsigned int truste
 
   trustsdb->squery(trustsdb, 
     "INSERT INTO ? (id, name, trustedfor, mode, maxperident, maxseen, expires, lastseen, lastmaxuserreset, createdby, contact, comment) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)",
-    "Tusuuuutttsss", "groups", id, name, trustedfor, mode, maxperident, maxseen, expires, lastseen, lastmaxuserreset, createdby, contact, comment
+    "Tusuuuutttsss", "migration_groups", id, name, trustedfor, mode, maxperident, maxseen, expires, lastseen, lastmaxuserreset, createdby, contact, comment
   );
 }
 
 static void tm_host(void *tag, unsigned int id, char *host, unsigned int max, time_t lastseen) {
   trustsdb->squery(trustsdb, 
     "INSERT INTO ? (groupid, host, max, lastseen) VALUES (?, ?, ?, ?)",
-    "Tusut", "hosts", id, host, max, lastseen
+    "Tusut", "migration_hosts", id, host, max, lastseen
   );
 }
 
-static void tm_final(void *tag, int errcode) {
+static void tm_complete(const DBAPIResult *r, void *tag) {
   struct callbackdata *cbd = tag;
-  migration = NULL;
+  int errcode = 0;
 
-  if(errcode) {
-    Error("trusts", ERR_ERROR, "Migration error: %d", errcode);
+  if(!r) {
+    errcode = MIGRATION_STOPPED;
   } else {
-    Error("trusts", ERR_INFO, "Migration completed.");
+    if(!r->success) {
+      Error("trusts", ERR_ERROR, "A error occured executing the rename table query.");
+      errcode = 100;
+    } else {
+      Error("trusts", ERR_INFO, "Migration table copying complete.");
+    }
+    r->clear(r);
   }
 
   if(cbd) {
-    cbd->callback(errcode, tag);
+    cbd->callback(errcode, cbd->tag);
     free(cbd);
   }
 }
+
+static void tm_final(void *tag, int errcode) {
+  struct callbackdata *cbd = tag;
+  migration = NULL;
+
+  if(errcode) {
+    Error("trusts", ERR_ERROR, "Migration error: %d", errcode);
+    if(cbd) {
+      cbd->callback(errcode, cbd->tag);
+      free(cbd);
+    }
+  } else {
+    Error("trusts", ERR_INFO, "Migration completed, copying tables...");
+/*
+    trustsdb->query(trustsdb, cbd?tm_complete:NULL, cbd,
+                    "BEGIN TRANSACTION; DROP TABLE ?; ALTER TABLE ? RENAME TO ?; DROP TABLE ?; ALTER TABLE ? RENAME TO ?; COMMIT;",
+                    "TTsTTs", "groups", "migration_groups", "groups", "hosts", "migration_hosts", "hosts");
+*/
+/*
+    trustsdb->query(trustsdb, cbd?tm_complete:NULL, cbd,
+                    "BEGIN TRANSACTION; DELETE FROM ?; INSERT INTO ? SELECT * FROM ?; DELETE FROM ?; INSERT INTO ? SELECT * FROM ?; COMMIT;",
+                    "TTTTTT", "groups", "groups", "migration_groups", "hosts", "hosts", "migration_hosts");
+*/
+/*
+    trustsdb->query(trustsdb, cbd?tm_complete:NULL, cbd,
+                    "DELETE FROM ?; INSERT INTO ? SELECT * FROM ?; DELETE FROM ?; INSERT INTO ? SELECT * FROM ?;",
+                    "TTTTTT", "groups", "groups", "migration_groups", "hosts", "hosts", "migration_hosts");
+*/
+    trustsdb->squery(trustsdb, "BEGIN TRANSACTION", "");
+    trustsdb->squery(trustsdb, "DROP TABLE ?", "T", "groups");
+    trustsdb->squery(trustsdb, "ALTER TABLE ? RENAME TO ?", "Ts", "migration_groups", "groups");
+    trustsdb->squery(trustsdb, "DROP TABLE ?", "T", "hosts");
+    trustsdb->squery(trustsdb, "ALTER TABLE ? RENAME TO ?", "Ts", "migration_hosts", "hosts");
+    trustsdb->query(trustsdb, tm_complete, cbd, "COMMIT", "");
+  }
+}
index da86d899d6d4582b76f840682efb39c00ce58e9d..46cddae25a9f5c326bce9e6678037b9be0522408 100644 (file)
@@ -1,12 +1,16 @@
 #include "../dbapi2/dbapi2.h"
 #include "../core/error.h"
 #include "../nick/nick.h"
+#include "../core/hooks.h"
 #include "trusts.h"
 
 DBAPIConn *trustsdb;
-extern trustgroup *tglist;
+static int tgmaxid;
+static int loaderror;
+int trustsdbloaded;
 
 void trusts_reloaddb(void);
+void createtrusttables(int migration);
 
 int trusts_loaddb(void) {
   trustsdb = dbapi2open(NULL, "trusts");
@@ -15,26 +19,191 @@ int trusts_loaddb(void) {
     return 0;
   }
 
-  trustsdb->createtable(trustsdb, NULL, NULL,
-    "CREATE TABLE ? (id INT PRIMARY KEY, name VARCHAR(100), trustedfor INT, mode INT, maxperident INT, maxseen INT, expires INT, lastseen INT, lastmaxuserreset INT, createdby VARCHAR(?), contact VARCHAR(?), comment VARCHAR(?))",
-    "Tddd", "groups", NICKLEN, CONTACTLEN, COMMENTLEN
-  );
-  trustsdb->createtable(trustsdb, NULL, NULL, "CREATE TABLE ? (groupid INT, host VARCHAR(100), max INT, lastseen INT, PRIMARY KEY (groupid, host))", "T", "hosts");
+  createtrusttables(0);
 
   trusts_reloaddb();
   return 1;
 }
 
+void createtrusttables(int migration) {
+  char *groups, *hosts;
+
+  if(migration) {
+    groups = "migration_groups";
+    hosts = "migration_hosts";
+  } else {
+    groups = "groups";
+    hosts = "hosts";
+  }
+
+  trustsdb->createtable(trustsdb, NULL, NULL,
+    "CREATE TABLE ? (id INT PRIMARY KEY, name VARCHAR(?), trustedfor INT, mode INT, maxperident INT, maxseen INT, expires INT, lastseen INT, lastmaxuserreset INT, createdby VARCHAR(?), contact VARCHAR(?), comment VARCHAR(?))",
+    "Tdddd", groups, TRUSTNAMELEN, NICKLEN, CONTACTLEN, COMMENTLEN
+  );
+  trustsdb->createtable(trustsdb, NULL, NULL, "CREATE TABLE ? (groupid INT, host VARCHAR(?), max INT, lastseen INT, PRIMARY KEY (groupid, host))", "Td", hosts, TRUSTHOSTLEN);
+}
+
 static void trusts_freedb(void) {
-/* do stuff */
+  trustgroup *tg, *ntg;
+  trusthost *th, *nth;
+
+  for(tg=tglist;tg;tg=ntg) {
+    ntg = tg->next;
+    for(th=tg->hosts;th;th=nth) {
+      nth = th->next;
+
+      freesstring(th->host);
+      free(th);
+    }
+
+    freesstring(tg->name);
+    freesstring(tg->createdby);
+    freesstring(tg->contact);
+    freesstring(tg->comment);
+    free(tg);
+  }
 
+  trustsdbloaded = 0;
   tglist = NULL;
+  tgmaxid = 0;
+}
+
+trustgroup *tg_getbyid(unsigned int id) {
+  trustgroup *tg;
+
+  for(tg=tglist;tg;tg=tg->next)
+    if(tg->id == id)
+      return tg;
+
+  return NULL;
+}
+
+static void loadhosts_data(const DBAPIResult *result, void *tag) {
+  if(!result) {
+    loaderror = 1;
+    return;
+  }
+
+  if(!result->success) {
+    Error("trusts", ERR_ERROR, "Error loading hosts table.");
+    loaderror = 1;
+
+    result->clear(result);
+    return;
+  }
+
+  if(result->fields != 4) {
+    Error("trusts", ERR_ERROR, "Wrong number of fields in hosts table.");
+    loaderror = 1;
+
+    result->clear(result);
+    return;
+  }
+
+  while(result->next(result)) {
+    unsigned int groupid;
+    trusthost *th;
+    trustgroup *tg;
+
+    groupid = strtoul(result->get(result, 0), NULL, 10);
+
+    tg = tg_getbyid(groupid);
+    if(!tg) {
+      Error("trusts", ERR_WARNING, "Orphaned trust group host: %d", groupid);
+      continue;
+    }
+
+    th = malloc(sizeof(trusthost));
+    if(!th)
+      continue;
+
+    th->host = getsstring(result->get(result, 1), TRUSTHOSTLEN);
+    th->maxseen = strtoul(result->get(result, 2), NULL, 10);
+    th->lastseen = (time_t)strtoul(result->get(result, 3), NULL, 10);
+
+    th->next = tg->hosts;
+    tg->hosts = th;
+  }
+
+  result->clear(result);
+
+  if(!loaderror) {
+    trustsdbloaded = 1;
+    triggerhook(HOOK_TRUSTS_DB_LOADED, NULL);
+  }
+}
+
+static void loadhosts_fini(const DBAPIResult *result, void *tag) {
+  Error("trusts", ERR_INFO, "Finished loading hosts.");
+}
+
+static void loadgroups_data(const DBAPIResult *result, void *tag) {
+  if(!result) {
+    loaderror = 1;
+    return;
+  }
+
+  if(!result->success) {
+    Error("trusts", ERR_ERROR, "Error loading group table.");
+    loaderror = 1;
+
+    result->clear(result);
+    return;
+  }
+
+  if(result->fields != 12) {
+    Error("trusts", ERR_ERROR, "Wrong number of fields in groups table.");
+    loaderror = 1;
+
+    result->clear(result);
+    return;
+  }
+
+  while(result->next(result)) {
+    unsigned int id;
+    trustgroup *tg;
+
+    id = strtoul(result->get(result, 0), NULL, 10);
+    if(id > tgmaxid)
+      tgmaxid = id;
+
+    tg = malloc(sizeof(trustgroup));
+    if(!tg)
+      continue;
+
+    tg->id = id;
+    tg->name = getsstring(result->get(result, 1), TRUSTNAMELEN);
+    tg->trustedfor = strtoul(result->get(result, 2), NULL, 10);
+    tg->mode = atoi(result->get(result, 3));
+    tg->maxperident = strtoul(result->get(result, 4), NULL, 10);
+    tg->maxseen = strtoul(result->get(result, 5), NULL, 10);
+    tg->expires = (time_t)strtoul(result->get(result, 6), NULL, 10);
+    tg->lastseen = (time_t)strtoul(result->get(result, 7), NULL, 10);
+    tg->lastmaxuserreset = (time_t)strtoul(result->get(result, 8), NULL, 10);
+    tg->createdby = getsstring(result->get(result, 9), NICKLEN);
+    tg->contact = getsstring(result->get(result, 10), CONTACTLEN);
+    tg->comment = getsstring(result->get(result, 11), COMMENTLEN);
+
+    tg->hosts = NULL;
+
+    tg->next = tglist;
+    tglist = tg;
+  }
+
+  result->clear(result);  
+}
+
+static void loadgroups_fini(const DBAPIResult *result, void *tag) {
+  Error("trusts", ERR_INFO, "Finished loading groups, maximum id: %d.", tgmaxid);
 }
 
 void trusts_reloaddb(void) {
   trusts_freedb();
 
+  loaderror = 0;
 
+  trustsdb->loadtable(trustsdb, NULL, loadgroups_data, loadgroups_fini, NULL, "groups");
+  trustsdb->loadtable(trustsdb, NULL, loadhosts_data, loadhosts_fini, NULL, "hosts");
 }
 
 void trusts_closedb(void) {
index a1dc496ef2a6dfbc688e9576933a27f2ee6b9346..ee5454dd6dae4499c5fdc220b46452293c4fd7aa 100644 (file)
@@ -1,5 +1,4 @@
 #include "../nterfacer/nterfacer.h"
-#include "../nick/nick.h"
 #include "../lib/strlfunc.h"
 #include "trusts.h"
 #include <stdio.h>
index 85e9ae32289f9310f1666a2e83c982b81db6e554..39c2e62e142d29d87194e04ee2651c0681c4bc07 100644 (file)
@@ -1,22 +1,15 @@
-#include "../core/error.h"
 #include "trusts.h"
 
 trustgroup *tglist;
 
 int trusts_loaddb(void);
 void trusts_closedb(void);
-void trusts_reloaddb(void);
-int trusts_migration_start(TrustDBMigrationCallback, void *);
-void trusts_migration_stop(void);
 
 void _init(void) {
   if(!trusts_loaddb())
     return;
-
-  trusts_migration_start(NULL, NULL);
 }
 
 void _fini(void) {
-  trusts_migration_stop();
   trusts_closedb();
 }
index 43afd6cc5484e0580da3afc1a90ea60332fa86bc..e2714efaf08010deec1460403312e44760befa4b 100644 (file)
@@ -8,6 +8,8 @@
 
 #define CONTACTLEN 100
 #define COMMENTLEN 300
+#define TRUSTNAMELEN 100
+#define TRUSTHOSTLEN 100
 
 struct trustmigration;
 
@@ -27,6 +29,14 @@ typedef struct trustmigration {
 
 typedef void (*TrustDBMigrationCallback)(int, void *);
 
+typedef struct trusthost {
+  sstring *host;
+  unsigned int maxseen;
+  time_t lastseen;
+
+  struct trusthost *next;
+} trusthost;
+
 typedef struct trustgroup {
   unsigned int id;
 
@@ -34,23 +44,20 @@ typedef struct trustgroup {
   unsigned int trustedfor;
   int mode;
   unsigned int maxperident;
+  unsigned int maxseen;
   time_t expires;
-  time_t latseeen;
+  time_t lastseen;
   time_t lastmaxuserreset;
-
   sstring *createdby, *contact, *comment;
 
+  trusthost *hosts;
+
   struct trustgroup *next;
 } trustgroup;
 
-typedef struct trusthost {
-  unsigned int id;
+void trusts_reloaddb(void);
 
-  sstring *mask;
-  unsigned int max;
-  time_t lastseen;
-
-  struct trusthost *next;
-} trusthost;
+extern int trustsdbloaded;
+extern trustgroup *tglist;
 
 #endif
diff --git a/trusts/trusts_commands.c b/trusts/trusts_commands.c
new file mode 100644 (file)
index 0000000..b925a43
--- /dev/null
@@ -0,0 +1,76 @@
+#include "../control/control.h"
+#include "../nick/nick.h"
+#include "trusts.h"
+
+int trusts_migration_start(TrustDBMigrationCallback, void *);
+void trusts_migration_stop(void);
+static void registercommands(void);
+static void deregistercommands(void);
+
+static int commandsregistered;
+
+static void migrate_status(int errcode, void *tag) {
+  long sender = (long)tag;
+  nick *np = getnickbynumeric(sender);
+
+  if(!np)
+    return;
+
+  if(!errcode) {
+    controlreply(np, "Migration complete.");
+    trusts_reloaddb();
+  } else {
+    controlreply(np, "Error %d occured during migration.", errcode);
+    registercommands();
+  }
+}
+
+static int trusts_cmdmigrate(void *source, int cargc, char **cargv) {
+  nick *sender = source;
+  int ret;
+
+  /* iffy but temporary */
+  ret = trusts_migration_start(migrate_status, (void *)(sender->numeric));
+  if(!ret) {
+    controlreply(sender, "Migration started.");
+    deregistercommands();
+  } else {
+    controlreply(sender, "Error %d starting migration.", ret);
+  }
+
+  return CMD_OK;
+}
+
+static void dbloaded(int hooknum, void *arg) {
+  registercommands();
+}
+
+void _init(void) {
+  registerhook(HOOK_TRUSTS_DB_LOADED, dbloaded);
+
+  if(trustsdbloaded)
+    registercommands();
+}
+
+void _fini(void) {
+  deregisterhook(HOOK_TRUSTS_DB_LOADED, dbloaded);
+  deregistercommands();
+
+  trusts_migration_stop();
+}
+
+static void registercommands(void) {
+  if(!trustsdbloaded || commandsregistered)
+    return;
+
+  commandsregistered = 1;
+  registercontrolhelpcmd("trustmigrate", NO_OPER, 0, trusts_cmdmigrate, "Usage: trustmigrate\nCopies trust data from O and reloads the database.");
+}
+
+static void deregistercommands(void) {
+  if(!commandsregistered)
+    return;
+
+  deregistercontrolcmd("trustmigrate", trusts_cmdmigrate);
+  commandsregistered = 0;
+}