client: Remove old persistent transaction code
authorAmitay Isaacs <amitay@gmail.com>
Wed, 25 Sep 2013 09:16:53 +0000 (19:16 +1000)
committerAmitay Isaacs <amitay@gmail.com>
Fri, 4 Oct 2013 05:47:11 +0000 (15:47 +1000)
Signed-off-by: Amitay Isaacs <amitay@gmail.com>
client/ctdb_client.c

index 3d9c6ed5ffc74faa7951722756f956d3135fcdba..9c1c27d0f4bb08376feb51fd8d6daf5807bd74fb 100644 (file)
@@ -4282,451 +4282,6 @@ int ctdb_transaction_cancel(struct ctdb_transaction_handle *h)
        return 0;
 }
 
-#if 0
-/**
- * check whether a transaction is active on a given db on a given node
- */
-int32_t ctdb_ctrl_transaction_active(struct ctdb_context *ctdb,
-                                    uint32_t destnode,
-                                    uint32_t db_id)
-{
-       int32_t status;
-       int ret;
-       TDB_DATA indata;
-
-       indata.dptr = (uint8_t *)&db_id;
-       indata.dsize = sizeof(db_id);
-
-       ret = ctdb_control(ctdb, destnode, 0,
-                          CTDB_CONTROL_TRANS2_ACTIVE,
-                          0, indata, NULL, NULL, &status,
-                          NULL, NULL);
-
-       if (ret != 0) {
-               DEBUG(DEBUG_ERR, (__location__ " ctdb control for transaction_active failed\n"));
-               return -1;
-       }
-
-       return status;
-}
-
-
-struct ctdb_transaction_handle {
-       struct ctdb_db_context *ctdb_db;
-       bool in_replay;
-       /*
-        * we store the reads and writes done under a transaction:
-        * - one list stores both reads and writes (m_all),
-        * - the other just writes (m_write)
-        */
-       struct ctdb_marshall_buffer *m_all;
-       struct ctdb_marshall_buffer *m_write;
-};
-
-/* start a transaction on a database */
-static int ctdb_transaction_destructor(struct ctdb_transaction_handle *h)
-{
-       tdb_transaction_cancel(h->ctdb_db->ltdb->tdb);
-       return 0;
-}
-
-/* start a transaction on a database */
-static int ctdb_transaction_fetch_start(struct ctdb_transaction_handle *h)
-{
-       struct ctdb_record_handle *rh;
-       TDB_DATA key;
-       TDB_DATA data;
-       struct ctdb_ltdb_header header;
-       TALLOC_CTX *tmp_ctx;
-       const char *keyname = CTDB_TRANSACTION_LOCK_KEY;
-       int ret;
-       struct ctdb_db_context *ctdb_db = h->ctdb_db;
-       pid_t pid;
-       int32_t status;
-
-       key.dptr = discard_const(keyname);
-       key.dsize = strlen(keyname);
-
-       if (!ctdb_db->persistent) {
-               DEBUG(DEBUG_ERR,(__location__ " Attempted transaction on non-persistent database\n"));
-               return -1;
-       }
-
-again:
-       tmp_ctx = talloc_new(h);
-
-       rh = ctdb_fetch_lock(ctdb_db, tmp_ctx, key, NULL);
-       if (rh == NULL) {
-               DEBUG(DEBUG_ERR,(__location__ " Failed to fetch_lock database\n"));
-               talloc_free(tmp_ctx);
-               return -1;
-       }
-
-       status = ctdb_ctrl_transaction_active(ctdb_db->ctdb,
-                                             CTDB_CURRENT_NODE,
-                                             ctdb_db->db_id);
-       if (status == 1) {
-               unsigned long int usec = (1000 + random()) % 100000;
-               DEBUG(DEBUG_DEBUG, (__location__ " transaction is active "
-                                   "on db_id[0x%08x]. waiting for %lu "
-                                   "microseconds\n",
-                                   ctdb_db->db_id, usec));
-               talloc_free(tmp_ctx);
-               usleep(usec);
-               goto again;
-       }
-
-       /*
-        * store the pid in the database:
-        * it is not enough that the node is dmaster...
-        */
-       pid = getpid();
-       data.dptr = (unsigned char *)&pid;
-       data.dsize = sizeof(pid_t);
-       rh->header.rsn++;
-       rh->header.dmaster = ctdb_db->ctdb->pnn;
-       ret = ctdb_ltdb_store(ctdb_db, key, &(rh->header), data);
-       if (ret != 0) {
-               DEBUG(DEBUG_ERR, (__location__ " Failed to store pid in "
-                                 "transaction record\n"));
-               talloc_free(tmp_ctx);
-               return -1;
-       }
-
-       talloc_free(rh);
-
-       ret = tdb_transaction_start(ctdb_db->ltdb->tdb);
-       if (ret != 0) {
-               DEBUG(DEBUG_ERR,(__location__ " Failed to start tdb transaction\n"));
-               talloc_free(tmp_ctx);
-               return -1;
-       }
-
-       ret = ctdb_ltdb_fetch(ctdb_db, key, &header, tmp_ctx, &data);
-       if (ret != 0) {
-               DEBUG(DEBUG_ERR,(__location__ " Failed to re-fetch transaction "
-                                "lock record inside transaction\n"));
-               tdb_transaction_cancel(ctdb_db->ltdb->tdb);
-               talloc_free(tmp_ctx);
-               goto again;
-       }
-
-       if (header.dmaster != ctdb_db->ctdb->pnn) {
-               DEBUG(DEBUG_DEBUG,(__location__ " not dmaster any more on "
-                                  "transaction lock record\n"));
-               tdb_transaction_cancel(ctdb_db->ltdb->tdb);
-               talloc_free(tmp_ctx);
-               goto again;
-       }
-
-       if ((data.dsize != sizeof(pid_t)) || (*(pid_t *)(data.dptr) != pid)) {
-               DEBUG(DEBUG_DEBUG, (__location__ " my pid is not stored in "
-                                   "the transaction lock record\n"));
-               tdb_transaction_cancel(ctdb_db->ltdb->tdb);
-               talloc_free(tmp_ctx);
-               goto again;
-       }
-
-       talloc_free(tmp_ctx);
-
-       return 0;
-}
-
-
-/* start a transaction on a database */
-struct ctdb_transaction_handle *ctdb_transaction_start(struct ctdb_db_context *ctdb_db,
-                                                      TALLOC_CTX *mem_ctx)
-{
-       struct ctdb_transaction_handle *h;
-       int ret;
-
-       h = talloc_zero(mem_ctx, struct ctdb_transaction_handle);
-       if (h == NULL) {
-               DEBUG(DEBUG_ERR,(__location__ " oom for transaction handle\n"));                
-               return NULL;
-       }
-
-       h->ctdb_db = ctdb_db;
-
-       ret = ctdb_transaction_fetch_start(h);
-       if (ret != 0) {
-               talloc_free(h);
-               return NULL;
-       }
-
-       talloc_set_destructor(h, ctdb_transaction_destructor);
-
-       return h;
-}
-
-
-
-/*
-  fetch a record inside a transaction
- */
-int ctdb_transaction_fetch(struct ctdb_transaction_handle *h, 
-                          TALLOC_CTX *mem_ctx, 
-                          TDB_DATA key, TDB_DATA *data)
-{
-       struct ctdb_ltdb_header header;
-       int ret;
-
-       ZERO_STRUCT(header);
-
-       ret = ctdb_ltdb_fetch(h->ctdb_db, key, &header, mem_ctx, data);
-       if (ret == -1 && header.dmaster == (uint32_t)-1) {
-               /* record doesn't exist yet */
-               *data = tdb_null;
-               ret = 0;
-       }
-       
-       if (ret != 0) {
-               return ret;
-       }
-
-       if (!h->in_replay) {
-               h->m_all = ctdb_marshall_add(h, h->m_all, h->ctdb_db->db_id, 1, key, NULL, *data);
-               if (h->m_all == NULL) {
-                       DEBUG(DEBUG_ERR,(__location__ " Failed to add to marshalling record\n"));
-                       return -1;
-               }
-       }
-
-       return 0;
-}
-
-/*
-  stores a record inside a transaction
- */
-int ctdb_transaction_store(struct ctdb_transaction_handle *h, 
-                          TDB_DATA key, TDB_DATA data)
-{
-       TALLOC_CTX *tmp_ctx = talloc_new(h);
-       struct ctdb_ltdb_header header;
-       TDB_DATA olddata;
-       int ret;
-
-       ZERO_STRUCT(header);
-
-       /* we need the header so we can update the RSN */
-       ret = ctdb_ltdb_fetch(h->ctdb_db, key, &header, tmp_ctx, &olddata);
-       if (ret == -1 && header.dmaster == (uint32_t)-1) {
-               /* the record doesn't exist - create one with us as dmaster.
-                  This is only safe because we are in a transaction and this
-                  is a persistent database */
-               ZERO_STRUCT(header);
-       } else if (ret != 0) {
-               DEBUG(DEBUG_ERR,(__location__ " Failed to fetch record\n"));
-               talloc_free(tmp_ctx);
-               return ret;
-       }
-
-       if (data.dsize == olddata.dsize &&
-           memcmp(data.dptr, olddata.dptr, data.dsize) == 0) {
-               /* save writing the same data */
-               talloc_free(tmp_ctx);
-               return 0;
-       }
-
-       header.dmaster = h->ctdb_db->ctdb->pnn;
-       header.rsn++;
-
-       if (!h->in_replay) {
-               h->m_all = ctdb_marshall_add(h, h->m_all, h->ctdb_db->db_id, 0, key, NULL, data);
-               if (h->m_all == NULL) {
-                       DEBUG(DEBUG_ERR,(__location__ " Failed to add to marshalling record\n"));
-                       talloc_free(tmp_ctx);
-                       return -1;
-               }
-       }               
-
-       h->m_write = ctdb_marshall_add(h, h->m_write, h->ctdb_db->db_id, 0, key, &header, data);
-       if (h->m_write == NULL) {
-               DEBUG(DEBUG_ERR,(__location__ " Failed to add to marshalling record\n"));
-               talloc_free(tmp_ctx);
-               return -1;
-       }
-       
-       ret = ctdb_ltdb_store(h->ctdb_db, key, &header, data);
-
-       talloc_free(tmp_ctx);
-       
-       return ret;
-}
-
-/*
-  replay a transaction
- */
-static int ctdb_replay_transaction(struct ctdb_transaction_handle *h)
-{
-       int ret, i;
-       struct ctdb_rec_data *rec = NULL;
-
-       h->in_replay = true;
-       talloc_free(h->m_write);
-       h->m_write = NULL;
-
-       ret = ctdb_transaction_fetch_start(h);
-       if (ret != 0) {
-               return ret;
-       }
-
-       for (i=0;i<h->m_all->count;i++) {
-               TDB_DATA key, data;
-
-               rec = ctdb_marshall_loop_next(h->m_all, rec, NULL, NULL, &key, &data);
-               if (rec == NULL) {
-                       DEBUG(DEBUG_ERR, (__location__ " Out of records in ctdb_replay_transaction?\n"));
-                       goto failed;
-               }
-
-               if (rec->reqid == 0) {
-                       /* its a store */
-                       if (ctdb_transaction_store(h, key, data) != 0) {
-                               goto failed;
-                       }
-               } else {
-                       TDB_DATA data2;
-                       TALLOC_CTX *tmp_ctx = talloc_new(h);
-
-                       if (ctdb_transaction_fetch(h, tmp_ctx, key, &data2) != 0) {
-                               talloc_free(tmp_ctx);
-                               goto failed;
-                       }
-                       if (data2.dsize != data.dsize ||
-                           memcmp(data2.dptr, data.dptr, data.dsize) != 0) {
-                               /* the record has changed on us - we have to give up */
-                               talloc_free(tmp_ctx);
-                               goto failed;
-                       }
-                       talloc_free(tmp_ctx);
-               }
-       }
-       
-       return 0;
-
-failed:
-       tdb_transaction_cancel(h->ctdb_db->ltdb->tdb);
-       return -1;
-}
-
-
-/*
-  commit a transaction
- */
-int ctdb_transaction_commit(struct ctdb_transaction_handle *h)
-{
-       int ret, retries=0;
-       int32_t status;
-       struct ctdb_context *ctdb = h->ctdb_db->ctdb;
-       struct timeval timeout;
-       enum ctdb_controls failure_control = CTDB_CONTROL_TRANS2_ERROR;
-
-       talloc_set_destructor(h, NULL);
-
-       /* our commit strategy is quite complex.
-
-          - we first try to commit the changes to all other nodes
-
-          - if that works, then we commit locally and we are done
-
-          - if a commit on another node fails, then we need to cancel
-            the transaction, then restart the transaction (thus
-            opening a window of time for a pending recovery to
-            complete), then replay the transaction, checking all the
-            reads and writes (checking that reads give the same data,
-            and writes succeed). Then we retry the transaction to the
-            other nodes
-       */
-
-again:
-       if (h->m_write == NULL) {
-               /* no changes were made */
-               tdb_transaction_cancel(h->ctdb_db->ltdb->tdb);
-               talloc_free(h);
-               return 0;
-       }
-
-       /* tell ctdbd to commit to the other nodes */
-       timeout = timeval_current_ofs(1, 0);
-       ret = ctdb_control(ctdb, CTDB_CURRENT_NODE, h->ctdb_db->db_id, 
-                          retries==0?CTDB_CONTROL_TRANS2_COMMIT:CTDB_CONTROL_TRANS2_COMMIT_RETRY, 0, 
-                          ctdb_marshall_finish(h->m_write), NULL, NULL, &status, 
-                          &timeout, NULL);
-       if (ret != 0 || status != 0) {
-               tdb_transaction_cancel(h->ctdb_db->ltdb->tdb);
-               DEBUG(DEBUG_NOTICE, (__location__ " transaction commit%s failed"
-                                    ", retrying after 1 second...\n",
-                                    (retries==0)?"":"retry "));
-               sleep(1);
-
-               if (ret != 0) {
-                       failure_control = CTDB_CONTROL_TRANS2_ERROR;
-               } else {
-                       /* work out what error code we will give if we 
-                          have to fail the operation */
-                       switch ((enum ctdb_trans2_commit_error)status) {
-                       case CTDB_TRANS2_COMMIT_SUCCESS:
-                       case CTDB_TRANS2_COMMIT_SOMEFAIL:
-                       case CTDB_TRANS2_COMMIT_TIMEOUT:
-                               failure_control = CTDB_CONTROL_TRANS2_ERROR;
-                               break;
-                       case CTDB_TRANS2_COMMIT_ALLFAIL:
-                               failure_control = CTDB_CONTROL_TRANS2_FINISHED;
-                               break;
-                       }
-               }
-
-               if (++retries == 100) {
-                       DEBUG(DEBUG_ERR,(__location__ " Giving up transaction on db 0x%08x after %d retries failure_control=%u\n", 
-                                        h->ctdb_db->db_id, retries, (unsigned)failure_control));
-                       ctdb_control(ctdb, CTDB_CURRENT_NODE, h->ctdb_db->db_id, 
-                                    failure_control, CTDB_CTRL_FLAG_NOREPLY, 
-                                    tdb_null, NULL, NULL, NULL, NULL, NULL);           
-                       talloc_free(h);
-                       return -1;
-               }               
-
-               if (ctdb_replay_transaction(h) != 0) {
-                       DEBUG(DEBUG_ERR, (__location__ " Failed to replay "
-                                         "transaction on db 0x%08x, "
-                                         "failure control =%u\n",
-                                         h->ctdb_db->db_id,
-                                         (unsigned)failure_control));
-                       ctdb_control(ctdb, CTDB_CURRENT_NODE, h->ctdb_db->db_id, 
-                                    failure_control, CTDB_CTRL_FLAG_NOREPLY, 
-                                    tdb_null, NULL, NULL, NULL, NULL, NULL);           
-                       talloc_free(h);
-                       return -1;
-               }
-               goto again;
-       } else {
-               failure_control = CTDB_CONTROL_TRANS2_ERROR;
-       }
-
-       /* do the real commit locally */
-       ret = tdb_transaction_commit(h->ctdb_db->ltdb->tdb);
-       if (ret != 0) {
-               DEBUG(DEBUG_ERR, (__location__ " Failed to commit transaction "
-                                 "on db id 0x%08x locally, "
-                                 "failure_control=%u\n",
-                                 h->ctdb_db->db_id,
-                                 (unsigned)failure_control));
-               ctdb_control(ctdb, CTDB_CURRENT_NODE, h->ctdb_db->db_id, 
-                            failure_control, CTDB_CTRL_FLAG_NOREPLY, 
-                            tdb_null, NULL, NULL, NULL, NULL, NULL);           
-               talloc_free(h);
-               return ret;
-       }
-
-       /* 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, NULL, NULL, NULL);
-       talloc_free(h);
-       return 0;
-}
-#endif
 
 /*
   recovery daemon ping to main daemon