Restart recovery dameon if it looks like it hung.
[sahlberg/ctdb.git] / common / ctdb_ltdb.c
index 662ed7697265aa2db34e498d29dbedd31ab47d34..200cca41dc1c119fd866770607af463b8981f1a4 100644 (file)
@@ -5,7 +5,7 @@
 
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2 of the License, or
+   the Free Software Foundation; either version 3 of the License, or
    (at your option) any later version.
    
    This program is distributed in the hope that it will be useful,
    GNU General Public License for more details.
    
    You should have received a copy of the GNU General Public License
-   along with this program; if not, write to the Free Software
-   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+   along with this program; if not, see <http://www.gnu.org/licenses/>.
 */
 
 #include "includes.h"
-#include "lib/events/events.h"
+#include "lib/tevent/tevent.h"
 #include "lib/tdb/include/tdb.h"
 #include "system/network.h"
 #include "system/filesys.h"
@@ -63,11 +62,9 @@ static void ltdb_initial_header(struct ctdb_db_context *ctdb_db,
                                TDB_DATA key,
                                struct ctdb_ltdb_header *header)
 {
-       header->rsn = 0;
+       ZERO_STRUCTP(header);
        /* initial dmaster is the lmaster */
        header->dmaster = ctdb_lmaster(ctdb_db->ctdb, &key);
-       header->laccessor = header->dmaster;
-       header->lacount = 0;
 }
 
 
@@ -122,9 +119,7 @@ int ctdb_ltdb_fetch(struct ctdb_db_context *ctdb_db,
 
 
 /*
-  fetch a record from the ltdb, separating out the header information
-  and returning the body of the record. A valid (initial) header is
-  returned if the record is not present
+  write a record to a normal database
 */
 int ctdb_ltdb_store(struct ctdb_db_context *ctdb_db, TDB_DATA key, 
                    struct ctdb_ltdb_header *header, TDB_DATA data)
@@ -132,13 +127,14 @@ int ctdb_ltdb_store(struct ctdb_db_context *ctdb_db, TDB_DATA key,
        struct ctdb_context *ctdb = ctdb_db->ctdb;
        TDB_DATA rec;
        int ret;
+       bool seqnum_suppressed = false;
 
        if (ctdb->flags & CTDB_FLAG_TORTURE) {
                struct ctdb_ltdb_header *h2;
                rec = tdb_fetch(ctdb_db->ltdb->tdb, key);
                h2 = (struct ctdb_ltdb_header *)rec.dptr;
                if (rec.dptr && rec.dsize >= sizeof(h2) && h2->rsn > header->rsn) {
-                       DEBUG(0,("RSN regression! %llu %llu\n",
+                       DEBUG(DEBUG_CRIT,("RSN regression! %llu %llu\n",
                                 (unsigned long long)h2->rsn, (unsigned long long)header->rsn));
                }
                if (rec.dptr) free(rec.dptr);
@@ -151,13 +147,34 @@ int ctdb_ltdb_store(struct ctdb_db_context *ctdb_db, TDB_DATA key,
        memcpy(rec.dptr, header, sizeof(*header));
        memcpy(rec.dptr + sizeof(*header), data.dptr, data.dsize);
 
+       /* Databases with seqnum updates enabled only get their seqnum
+          changes when/if we modify the data */
+       if (ctdb_db->seqnum_update != NULL) {
+               TDB_DATA old;
+               old = tdb_fetch(ctdb_db->ltdb->tdb, key);
+
+               if ( (old.dsize == rec.dsize)
+               && !memcmp(old.dptr+sizeof(struct ctdb_ltdb_header),
+                         rec.dptr+sizeof(struct ctdb_ltdb_header),
+                         rec.dsize-sizeof(struct ctdb_ltdb_header)) ) {
+                       tdb_remove_flags(ctdb_db->ltdb->tdb, TDB_SEQNUM);
+                       seqnum_suppressed = true;
+               }
+               if (old.dptr) free(old.dptr);
+       }
        ret = tdb_store(ctdb_db->ltdb->tdb, key, rec, TDB_REPLACE);
+       if (ret != 0) {
+               DEBUG(DEBUG_ERR, (__location__ " Failed to store dynamic data\n"));
+       }
+       if (seqnum_suppressed) {
+               tdb_add_flags(ctdb_db->ltdb->tdb, TDB_SEQNUM);
+       }
+
        talloc_free(rec.dptr);
 
        return ret;
 }
 
-
 /*
   lock a record in the ltdb, given a key
  */
@@ -173,7 +190,26 @@ int ctdb_ltdb_unlock(struct ctdb_db_context *ctdb_db, TDB_DATA key)
 {
        int ret = tdb_chainunlock(ctdb_db->ltdb->tdb, key);
        if (ret != 0) {
-               DEBUG(0,("tdb_chainunlock failed\n"));
+               DEBUG(DEBUG_ERR,("tdb_chainunlock failed on db %s [%s]\n", ctdb_db->db_name, tdb_errorstr(ctdb_db->ltdb->tdb)));
        }
        return ret;
 }
+
+
+/*
+  delete a record from a normal database
+*/
+int ctdb_ltdb_delete(struct ctdb_db_context *ctdb_db, TDB_DATA key)
+{
+       struct ctdb_context *ctdb = ctdb_db->ctdb;
+
+       if (ctdb_db->persistent != 0) {
+               DEBUG(DEBUG_ERR,("Trying to delete emty record in persistent database\n"));
+               return 0;
+       }
+       if (tdb_delete(ctdb_db->ltdb->tdb, key) != 0) {
+               DEBUG(DEBUG_ERR,("Failed to delete empty record."));
+               return -1;
+       }
+       return 0;
+}