libctdb: test: add readrecordlock support
authorRusty Russell <rusty@rustcorp.com.au>
Mon, 21 Jun 2010 06:36:00 +0000 (16:06 +0930)
committerRusty Russell <rusty@rustcorp.com.au>
Mon, 21 Jun 2010 06:36:00 +0000 (16:06 +0930)
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
libctdb/test/attachdb.c
libctdb/test/ctdb-test.h
libctdb/test/readrecordlock.c [new file with mode: 0644]
libctdb/test/tests/lockrecord1.txt [new file with mode: 0644]
libctdb/test/tests/lockrecord2.txt [new file with mode: 0644]

index bb4ce2d0bf226b258d261368eac26405c9da3e0a..9235785f95a7cd0f53b9e283ea1bfa1f5f39926d 100644 (file)
@@ -20,6 +20,17 @@ struct db {
        uint32_t tdb_flags;
 };
 
+struct ctdb_db *find_db_by_id(unsigned int id)
+{
+       struct db *db;
+
+       for (db = dbs; db; db = db->next) {
+               if (db->num == id)
+                       return db->db;
+       }
+       return NULL;
+}
+
 static void attachdb_help(int agc, char **argv)
 {
 #include "generated-attachdb-help:attachdb"
index ba8fbe147a02c10dded8e9d84cfc5f08f77e30a1..c3e548bfaad812ded044e1cda82c73813b7d2855 100644 (file)
@@ -23,4 +23,6 @@ void check_databases(void);
 void *save_databases(void);
 void restore_databases(void *);
 
+struct ctdb_db *find_db_by_id(unsigned int id);
+
 #endif /* __HAVE_CTDB_TEST_H */
diff --git a/libctdb/test/readrecordlock.c b/libctdb/test/readrecordlock.c
new file mode 100644 (file)
index 0000000..e277f55
--- /dev/null
@@ -0,0 +1,197 @@
+#include "utils.h"
+#include "log.h"
+#include "tui.h"
+#include "ctdb-test.h"
+#include <ctdb.h>
+#include <tdb.h>
+#include <talloc.h>
+#include <dlinklist.h>
+#include <errno.h>
+
+struct lock {
+       struct lock *next, *prev;
+       struct ctdb_db *db;
+       struct ctdb_lock *lock;
+       unsigned int id;
+};
+
+static unsigned int lock_id;
+static struct lock *locks;
+
+static void readrecordlock_help(int argc, char **argv)
+{
+#include "generated-readrecordlock-help:readrecordlock"
+/*** XML Help:
+    <section id="c:readrecordlock">
+     <title><command>readrecordlock</command></title>
+     <para>Read and lock a record in a ctdb database</para>
+     <cmdsynopsis>
+      <command>readrecordlock</command>
+      <arg choice="req"><replaceable>db-id</replaceable></arg>
+      <arg choice="req"><replaceable>key</replaceable></arg>
+     </cmdsynopsis>
+
+     <para>Read and lock a record.  Prints the record, and a 1-based
+     sequential handle on success, which should be handed to
+     <command>releaselock</command>
+     </para>
+     </section>
+*/
+}
+
+static void releaselock_help(int argc, char **argv)
+{
+#include "generated-readrecordlock-help:releaselock"
+/*** XML Help:
+    <section id="c:releaselock">
+     <title><command>releaselock</command></title>
+     <para>Unlock a record in a ctdb database</para>
+     <cmdsynopsis>
+      <command>releaselock</command>
+      <arg choice="req"><replaceable>db-id</replaceable></arg>
+      <arg choice="req"><replaceable>lock-id</replaceable></arg>
+     </cmdsynopsis>
+
+     <para>Unlock a record successfully locked by
+     <command>readrecordlock</command>.  </para>
+
+     </section>
+*/
+}
+
+static void writerecord_help(int argc, char **argv)
+{
+#include "generated-readrecordlock-help:writerecord"
+/*** XML Help:
+    <section id="c:writerecord">
+     <title><command>writerecord</command></title>
+     <para>Write to a locked record in a ctdb database</para>
+     <cmdsynopsis>
+      <command>writerecord</command>
+      <arg choice="req"><replaceable>db-id</replaceable></arg>
+      <arg choice="req"><replaceable>lock-id</replaceable></arg>
+      <arg choice="req"><replaceable>data</replaceable></arg>
+     </cmdsynopsis>
+
+     <para>Once a record is locked with
+     <command>readrecordlock</command>, you can write to it. </para>
+     </section>
+*/
+}
+
+static int lock_destructor(struct lock *lock)
+{
+       ctdb_release_lock(lock->db, lock->lock);
+       DLIST_REMOVE(locks, lock);
+       return 0;
+}
+
+static bool releaselock(int argc, char **argv)
+{
+       struct ctdb_db *db;
+       struct lock *lock;
+
+       if (argc != 3) {
+               log_line(LOG_ALWAYS, "Need database number and lock number");
+               return false;
+       }
+
+       db = find_db_by_id(atoi(argv[1]));
+       if (!db) {
+               log_line(LOG_ALWAYS, "Unknown db number %s", argv[1]);
+               return false;
+       }
+
+       for (lock = locks; lock; lock = lock->next) {
+               if (lock->id == atoi(argv[2]))
+                       break;
+       }
+       if (!lock) {
+               log_line(LOG_ALWAYS, "Unknown lock number %s", argv[2]);
+               return false;
+       }
+       talloc_free(lock);
+       return true;
+}
+
+static bool writerecord(int argc, char **argv)
+{
+       struct ctdb_db *db;
+       struct lock *lock;
+       TDB_DATA data;
+
+       if (argc != 4) {
+               log_line(LOG_ALWAYS, "Need db-id, lock-id and data");
+               return false;
+       }
+
+       db = find_db_by_id(atoi(argv[1]));
+       if (!db) {
+               log_line(LOG_ALWAYS, "Unknown db number %s", argv[1]);
+               return false;
+       }
+
+       for (lock = locks; lock; lock = lock->next) {
+               if (lock->id == atoi(argv[2]))
+                       break;
+       }
+       if (!lock) {
+               log_line(LOG_ALWAYS, "Unknown lock number %s", argv[2]);
+               return false;
+       }
+
+       data.dptr = (unsigned char *)argv[3];
+       data.dsize = strlen(argv[3]);
+
+       if (!ctdb_writerecord(db, lock->lock, data)) {
+               log_line(LOG_UI, "writerecordlock: failed %s", strerror(errno));
+               return false;
+       }
+       return true;
+}
+
+static bool readrecordlock(int argc, char **argv)
+{
+       struct lock *lock = talloc(working, struct lock);
+       TDB_DATA key, data;
+
+       if (!get_ctdb()) {
+               log_line(LOG_ALWAYS, "No ctdb connection");
+               return false;
+       }
+       if (argc != 3) {
+               log_line(LOG_ALWAYS, "Need db-id and key");
+               return false;
+       }
+
+       lock->db = find_db_by_id(atoi(argv[1]));
+       if (!lock->db) {
+               log_line(LOG_ALWAYS, "Unknown db number %s", argv[1]);
+               return false;
+       }
+
+       key.dptr = (unsigned char *)argv[2];
+       key.dsize = strlen(argv[2]);
+
+       lock->lock = ctdb_readrecordlock(get_ctdb(), lock->db, key, &data);
+       if (!lock->lock) {
+               log_line(LOG_UI, "readrecordlock: failed %s", strerror(errno));
+               return false;
+       }
+       lock->id = ++lock_id;
+       DLIST_ADD(locks, lock);
+       talloc_set_destructor(lock, lock_destructor);
+
+       log_line(LOG_UI, "lock %u: data '%.*s'",
+                lock->id, data.dsize, (char *)data.dptr);
+       return true;
+}
+
+static void readrecordlock_init(void)
+{
+       tui_register_command("readrecordlock",
+                            readrecordlock, readrecordlock_help);
+       tui_register_command("releaselock", releaselock, releaselock_help);
+       tui_register_command("writerecord", writerecord, writerecord_help);
+}
+init_call(readrecordlock_init);
diff --git a/libctdb/test/tests/lockrecord1.txt b/libctdb/test/tests/lockrecord1.txt
new file mode 100644 (file)
index 0000000..b719cc2
--- /dev/null
@@ -0,0 +1,8 @@
+connect
+# This is just a sanity check
+expect attachdb attached: 1
+attachdb test.tdb false
+# This is just a sanity check
+expect readrecordlock lock 1: data ''
+readrecordlock 1 testkey
+releaselock 1 1
diff --git a/libctdb/test/tests/lockrecord2.txt b/libctdb/test/tests/lockrecord2.txt
new file mode 100644 (file)
index 0000000..6ad27fd
--- /dev/null
@@ -0,0 +1,13 @@
+connect
+# This is just a sanity check
+expect attachdb attached: 1
+attachdb test.tdb false
+# This is just a sanity check
+expect readrecordlock lock 1: data ''
+readrecordlock 1 testkey
+writerecord 1 1 test-contents
+releaselock 1 1
+
+expect readrecordlock lock 2: data 'test-contents'
+readrecordlock 1 testkey
+releaselock 1 2