ReadOnly: add a readonly flag to the getdbmap control and show the readonly setting...
[sahlberg/ctdb.git] / tools / ctdb.c
index 56188331604aa94828f3e07c45e2a88b84a84c64..1770fe4e8055c38ed810326a4a8deab9c22e0091 100644 (file)
@@ -123,7 +123,7 @@ static int db_exists(struct ctdb_context *ctdb, const char *db_name, bool *persi
                ctdb_ctrl_getdbname(ctdb, TIMELIMIT(), options.pnn, dbmap->dbs[i].dbid, ctdb, &name);
                if (!strcmp(name, db_name)) {
                        if (persistent) {
-                               *persistent = dbmap->dbs[i].persistent;
+                               *persistent = dbmap->dbs[i].flags & CTDB_DB_FLAGS_PERSISTENT;
                        }
                        return 0;
                }
@@ -3012,6 +3012,62 @@ static int control_catdb(struct ctdb_context *ctdb, int argc, const char **argv)
        return 0;
 }
 
+struct cattdb_data {
+       struct ctdb_context *ctdb;
+       uint32_t count;
+};
+
+static int cattdb_traverse(struct tdb_context *tdb, TDB_DATA key, TDB_DATA data, void *private_data)
+{
+       struct cattdb_data *d = private_data;
+
+       d->count++;
+       
+       return ctdb_dumpdb_record(d->ctdb, key, data, stdout);
+}
+
+/*
+  cat the local tdb database using same format as catdb
+ */
+static int control_cattdb(struct ctdb_context *ctdb, int argc, const char **argv)
+{
+       const char *db_name;
+       struct ctdb_db_context *ctdb_db;
+       struct cattdb_data d;
+       bool persistent;
+
+       if (argc < 1) {
+               usage();
+       }
+
+       db_name = argv[0];
+
+
+       if (db_exists(ctdb, db_name, &persistent)) {
+               DEBUG(DEBUG_ERR,("Database '%s' does not exist\n", db_name));
+               return -1;
+       }
+
+       ctdb_db = ctdb_attach(ctdb, db_name, false, 0);
+
+       if (ctdb_db == NULL) {
+               DEBUG(DEBUG_ERR,("Unable to attach to database '%s'\n", db_name));
+               return -1;
+       }
+
+       /* traverse the local tdb */
+       d.count = 0;
+       d.ctdb  = ctdb;
+       if (tdb_traverse_read(ctdb_db->ltdb->tdb, cattdb_traverse, &d) == -1) {
+               printf("Failed to cattdb data\n");
+               exit(10);
+       }
+       talloc_free(ctdb_db);
+
+       printf("Dumped %d records\n", d.count);
+       return 0;
+}
+
 /*
   display the content of a database key
  */
@@ -3348,6 +3404,47 @@ static int control_pstore(struct ctdb_context *ctdb, int argc, const char **argv
        return 0;
 }
 
+/*
+  check if a service is bound to a port or not
+ */
+static int control_chktcpport(struct ctdb_context *ctdb, int argc, const char **argv)
+{
+       int s, ret;
+       unsigned v;
+       int port;
+        struct sockaddr_in sin;
+
+       if (argc != 1) {
+               printf("Use: ctdb chktcport <port>\n");
+               return EINVAL;
+       }
+
+       port = atoi(argv[0]);
+
+       s = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
+       if (s == -1) {
+               printf("Failed to open local socket\n");
+               return errno;
+       }
+
+       v = fcntl(s, F_GETFL, 0);
+        fcntl(s, F_SETFL, v | O_NONBLOCK);
+
+       bzero(&sin, sizeof(sin));
+       sin.sin_family = PF_INET;
+       sin.sin_port   = htons(port);
+       ret = bind(s, (struct sockaddr *)&sin, sizeof(sin));
+       close(s);
+       if (ret == -1) {
+               printf("Failed to bind to local socket: %d %s\n", errno, strerror(errno));
+               return errno;
+       }
+
+       return 0;
+}
+
+
+
 static void log_handler(struct ctdb_context *ctdb, uint64_t srvid, 
                             TDB_DATA data, void *private_data)
 {
@@ -3457,12 +3554,13 @@ static int control_getdbmap(struct ctdb_context *ctdb, int argc, const char **ar
        }
 
        if(options.machinereadable){
-               printf(":ID:Name:Path:Persistent:Unhealthy:\n");
+               printf(":ID:Name:Path:Persistent:Unhealthy:ReadOnly:\n");
                for(i=0;i<dbmap->num;i++){
                        const char *path;
                        const char *name;
                        const char *health;
                        bool persistent;
+                       bool readonly;
 
                        ctdb_ctrl_getdbpath(ctdb, TIMELIMIT(), options.pnn,
                                            dbmap->dbs[i].dbid, ctdb, &path);
@@ -3470,10 +3568,11 @@ static int control_getdbmap(struct ctdb_context *ctdb, int argc, const char **ar
                                            dbmap->dbs[i].dbid, ctdb, &name);
                        ctdb_ctrl_getdbhealth(ctdb, TIMELIMIT(), options.pnn,
                                              dbmap->dbs[i].dbid, ctdb, &health);
-                       persistent = dbmap->dbs[i].persistent;
-                       printf(":0x%08X:%s:%s:%d:%d:\n",
+                       persistent = dbmap->dbs[i].flags & CTDB_DB_FLAGS_PERSISTENT;
+                       readonly   = dbmap->dbs[i].flags & CTDB_DB_FLAGS_READONLY;
+                       printf(":0x%08X:%s:%s:%d:%d:%d:\n",
                               dbmap->dbs[i].dbid, name, path,
-                              !!(persistent), !!(health));
+                              !!(persistent), !!(health), !!(readonly));
                }
                return 0;
        }
@@ -3484,14 +3583,17 @@ static int control_getdbmap(struct ctdb_context *ctdb, int argc, const char **ar
                const char *name;
                const char *health;
                bool persistent;
+               bool readonly;
 
                ctdb_ctrl_getdbpath(ctdb, TIMELIMIT(), options.pnn, dbmap->dbs[i].dbid, ctdb, &path);
                ctdb_ctrl_getdbname(ctdb, TIMELIMIT(), options.pnn, dbmap->dbs[i].dbid, ctdb, &name);
                ctdb_ctrl_getdbhealth(ctdb, TIMELIMIT(), options.pnn, dbmap->dbs[i].dbid, ctdb, &health);
-               persistent = dbmap->dbs[i].persistent;
-               printf("dbid:0x%08x name:%s path:%s%s%s\n",
+               persistent = dbmap->dbs[i].flags & CTDB_DB_FLAGS_PERSISTENT;
+               readonly   = dbmap->dbs[i].flags & CTDB_DB_FLAGS_READONLY;
+               printf("dbid:0x%08x name:%s path:%s%s%s%s\n",
                       dbmap->dbs[i].dbid, name, path,
                       persistent?" PERSISTENT":"",
+                      readonly?" READONLY":"",
                       health?" UNHEALTHY":"");
        }
 
@@ -3524,6 +3626,7 @@ static int control_getdbstatus(struct ctdb_context *ctdb, int argc, const char *
                const char *name;
                const char *health;
                bool persistent;
+               bool readonly;
 
                ctdb_ctrl_getdbname(ctdb, TIMELIMIT(), options.pnn, dbmap->dbs[i].dbid, ctdb, &name);
                if (strcmp(name, db_name) != 0) {
@@ -3532,10 +3635,12 @@ static int control_getdbstatus(struct ctdb_context *ctdb, int argc, const char *
 
                ctdb_ctrl_getdbpath(ctdb, TIMELIMIT(), options.pnn, dbmap->dbs[i].dbid, ctdb, &path);
                ctdb_ctrl_getdbhealth(ctdb, TIMELIMIT(), options.pnn, dbmap->dbs[i].dbid, ctdb, &health);
-               persistent = dbmap->dbs[i].persistent;
-               printf("dbid: 0x%08x\nname: %s\npath: %s\nPERSISTENT: %s\nHEALTH: %s\n",
+               persistent = dbmap->dbs[i].flags & CTDB_DB_FLAGS_PERSISTENT;
+               readonly   = dbmap->dbs[i].flags & CTDB_DB_FLAGS_READONLY;
+               printf("dbid: 0x%08x\nname: %s\npath: %s\nPERSISTENT: %s\nREADONLY: %s\nHEALTH: %s\n",
                       dbmap->dbs[i].dbid, name, path,
                       persistent?"yes":"no",
+                      readonly?"yes":"no",
                       health?health:"OK");
                return 0;
        }
@@ -4126,7 +4231,7 @@ static int control_backupdb(struct ctdb_context *ctdb, int argc, const char **ar
                                     allow_unhealthy));
        }
 
-       ctdb_db = ctdb_attach(ctdb, argv[0], dbmap->dbs[i].persistent, 0);
+       ctdb_db = ctdb_attach(ctdb, argv[0], dbmap->dbs[i].flags & CTDB_DB_FLAGS_PERSISTENT, 0);
        if (ctdb_db == NULL) {
                DEBUG(DEBUG_ERR,("Unable to attach to database '%s'\n", argv[0]));
                talloc_free(tmp_ctx);
@@ -4178,7 +4283,7 @@ static int control_backupdb(struct ctdb_context *ctdb, int argc, const char **ar
 
        dbhdr.version = DB_VERSION;
        dbhdr.timestamp = time(NULL);
-       dbhdr.persistent = dbmap->dbs[i].persistent;
+       dbhdr.persistent = dbmap->dbs[i].flags & CTDB_DB_FLAGS_PERSISTENT;
        dbhdr.size = bd->len;
        if (strlen(argv[0]) >= MAX_DB_NAME) {
                DEBUG(DEBUG_ERR,("Too long dbname\n"));
@@ -4525,7 +4630,7 @@ static int control_wipedb(struct ctdb_context *ctdb, int argc,
                return -1;
        }
 
-       ctdb_db = ctdb_attach(ctdb, argv[0], dbmap->dbs[i].persistent, 0);
+       ctdb_db = ctdb_attach(ctdb, argv[0], dbmap->dbs[i].flags & CTDB_DB_FLAGS_PERSISTENT, 0);
        if (ctdb_db == NULL) {
                DEBUG(DEBUG_ERR, ("Unable to attach to database '%s'\n",
                                  argv[0]));
@@ -4901,6 +5006,7 @@ static const struct {
        { "getdbmap",        control_getdbmap,          true,   false,  "show the database map" },
        { "getdbstatus",     control_getdbstatus,       true,   false,  "show the status of a database", "<dbname>" },
        { "catdb",           control_catdb,             true,   false,  "dump a database" ,                     "<dbname>"},
+       { "cattdb",          control_cattdb,            true,   false,  "dump a database" ,                     "<dbname>"},
        { "getmonmode",      control_getmonmode,        true,   false,  "show monitoring mode" },
        { "getcapabilities", control_getcapabilities,   true,   false,  "show node capabilities" },
        { "pnn",             control_pnn,               true,   false,  "show the pnn of the currnet node" },
@@ -4974,6 +5080,7 @@ static const struct {
        { "tfetch",          control_tfetch,            false,  true,  "fetch a record from a [c]tdb-file", "<tdb-file> <key> [<file>]" },
        { "readkey",         control_readkey,           true,   false,  "read the content off a database key", "<tdb-file> <key>" },
        { "writekey",        control_writekey,          true,   false,  "write to a database key", "<tdb-file> <key> <value>" },
+       { "checktcpport",    control_chktcpport,        false,  true,  "check if a service is bound to a specific tcp port or not", "<port>" },
 };
 
 /*