fixed a looping error bug with the new transactions code
authorAndrew Tridgell <tridge@samba.org>
Thu, 7 Aug 2008 14:44:33 +0000 (00:44 +1000)
committerAndrew Tridgell <tridge@samba.org>
Thu, 7 Aug 2008 14:44:33 +0000 (00:44 +1000)
client/ctdb_client.c
server/ctdb_persistent.c

index cec16d1f9b295814e3a2b69cc90a807da6bd316b..3717096cb9165ac30c5d6ac4895aee9d53ccd6bb 100644 (file)
@@ -3028,7 +3028,6 @@ struct ctdb_transaction_handle *ctdb_transaction_start(struct ctdb_db_context *c
        struct ctdb_transaction_handle *h;
        int ret;
 
-       /* we have a good transaction */
        h = talloc_zero(mem_ctx, struct ctdb_transaction_handle);
        if (h == NULL) {
                DEBUG(DEBUG_ERR,(__location__ " oom for transaction handle\n"));                
@@ -3200,14 +3199,14 @@ int ctdb_transaction_commit(struct ctdb_transaction_handle *h)
        struct ctdb_context *ctdb = h->ctdb_db->ctdb;
        struct timeval timeout;
 
-       talloc_set_destructor(h, NULL);
-
        if (h->m_write == NULL) {
                /* no changes were made */
                talloc_free(h);
                return 0;
        }
 
+       talloc_set_destructor(h, NULL);
+
        /* our commit strategy is quite complex.
 
           - we first try to commit the changes to all other nodes
@@ -3258,7 +3257,7 @@ again:
        /* tell ctdbd that we are finished with our local commit */
        ctdb_control(ctdb, CTDB_CURRENT_NODE, h->ctdb_db->db_id, 
                     CTDB_CONTROL_TRANS2_FINISHED, CTDB_CTRL_FLAG_NOREPLY, 
-                    tdb_null, NULL, NULL, &status, NULL, NULL);
+                    tdb_null, NULL, NULL, NULL, NULL, NULL);
        talloc_free(h);
        return 0;
 }
index 6a8a10072c74a83be031433c61e4a1df22fc714a..5b88b4bbed97ae9079931b28b14d69c25ba91a31 100644 (file)
@@ -189,31 +189,39 @@ static int ctdb_persistent_store(struct ctdb_persistent_write_state *state)
        for (i=0;i<m->count;i++) {
                struct ctdb_ltdb_header oldheader;
                struct ctdb_ltdb_header header;
-               TDB_DATA key, data;
+               TDB_DATA key, data, olddata;
+               TALLOC_CTX *tmp_ctx = talloc_new(state);
 
                rec = ctdb_marshall_loop_next(m, rec, NULL, &header, &key, &data);
                
                if (rec == NULL) {
                        DEBUG(DEBUG_ERR,("Failed to get next record %d for db_id 0x%08x in ctdb_persistent_store\n",
                                         i, state->ctdb_db->db_id));
+                       talloc_free(tmp_ctx);
                        goto failed;                    
                }
 
                /* fetch the old header and ensure the rsn is less than the new rsn */
-               ret = ctdb_ltdb_fetch(state->ctdb_db, key, &oldheader, NULL, NULL);
+               ret = ctdb_ltdb_fetch(state->ctdb_db, key, &oldheader, tmp_ctx, &olddata);
                if (ret != 0) {
                        DEBUG(DEBUG_ERR,("Failed to fetch old record for db_id 0x%08x in ctdb_persistent_store\n",
                                         state->ctdb_db->db_id));
+                       talloc_free(tmp_ctx);
                        goto failed;
                }
 
-               if (oldheader.rsn >= header.rsn) {
+               if (oldheader.rsn >= header.rsn &&
+                   (olddata.dsize != data.dsize || 
+                    memcmp(olddata.dptr, data.dptr, data.dsize) != 0)) {
                        DEBUG(DEBUG_CRIT,("existing header for db_id 0x%08x has larger RSN %llu than new RSN %llu in ctdb_persistent_store\n",
                                          state->ctdb_db->db_id, 
                                          (unsigned long long)oldheader.rsn, (unsigned long long)header.rsn));
+                       talloc_free(tmp_ctx);
                        goto failed;
                }
 
+               talloc_free(tmp_ctx);
+
                ret = ctdb_ltdb_store(state->ctdb_db, key, &header, data);
                if (ret != 0) {
                        DEBUG(DEBUG_CRIT,("Failed to store record for db_id 0x%08x in ctdb_persistent_store\n",