]> git.ipfire.org Git - thirdparty/samba.git/commitdiff
simplified ctdb_call() interface, and made it easier to expand with more parameters...
authorAndrew Tridgell <tridge@samba.org>
Thu, 25 Jan 2007 05:13:17 +0000 (16:13 +1100)
committerAndrew Tridgell <tridge@samba.org>
Thu, 25 Jan 2007 05:13:17 +0000 (16:13 +1100)
(This used to be ctdb commit 6c816fe85e84faad167101bcf26850966c3044e5)

ctdb/common/ctdb_call.c
ctdb/ctdb_bench.c
ctdb/ctdb_test.c
ctdb/include/ctdb.h

index 923b423716b66f6582114d377052c1c7ebbd3bc4..0d135d5b07772689bb6a1a0bc92df37889f1e9fd 100644 (file)
@@ -44,9 +44,8 @@ static void ctdb_queue_packet(struct ctdb_context *ctdb, struct ctdb_req_header
 /*
   local version of ctdb_call
 */
-static int ctdb_call_local(struct ctdb_context *ctdb, TDB_DATA key, 
+static int ctdb_call_local(struct ctdb_context *ctdb, struct ctdb_call *call,
                           struct ctdb_ltdb_header *header, TDB_DATA *data,
-                          int call_id, TDB_DATA *call_data, TDB_DATA *reply_data,
                           uint32_t caller)
 {
        struct ctdb_call_info *c;
@@ -55,8 +54,8 @@ static int ctdb_call_local(struct ctdb_context *ctdb, TDB_DATA key,
        c = talloc(ctdb, struct ctdb_call_info);
        CTDB_NO_MEMORY(ctdb, c);
 
-       c->key = key;
-       c->call_data = call_data;
+       c->key = call->key;
+       c->call_data = &call->call_data;
        c->record_data.dptr = talloc_memdup(c, data->dptr, data->dsize);
        c->record_data.dsize = data->dsize;
        CTDB_NO_MEMORY(ctdb, c->record_data.dptr);
@@ -64,15 +63,15 @@ static int ctdb_call_local(struct ctdb_context *ctdb, TDB_DATA key,
        c->reply_data = NULL;
 
        for (fn=ctdb->calls;fn;fn=fn->next) {
-               if (fn->id == call_id) break;
+               if (fn->id == call->call_id) break;
        }
        if (fn == NULL) {
-               ctdb_set_error(ctdb, "Unknown call id %u\n", call_id);
+               ctdb_set_error(ctdb, "Unknown call id %u\n", call->call_id);
                return -1;
        }
 
        if (fn->fn(c) != 0) {
-               ctdb_set_error(ctdb, "ctdb_call %u failed\n", call_id);
+               ctdb_set_error(ctdb, "ctdb_call %u failed\n", call->call_id);
                return -1;
        }
 
@@ -89,20 +88,18 @@ static int ctdb_call_local(struct ctdb_context *ctdb, TDB_DATA key,
        }
 
        if (c->new_data) {
-               if (ctdb_ltdb_store(ctdb, key, header, *c->new_data) != 0) {
+               if (ctdb_ltdb_store(ctdb, call->key, header, *c->new_data) != 0) {
                        ctdb_set_error(ctdb, "ctdb_call tdb_store failed\n");
                        return -1;
                }
        }
 
-       if (reply_data) {
-               if (c->reply_data) {
-                       *reply_data = *c->reply_data;
-                       talloc_steal(ctdb, reply_data->dptr);
-               } else {
-                       reply_data->dptr = NULL;
-                       reply_data->dsize = 0;
-               }
+       if (c->reply_data) {
+               call->reply_data = *c->reply_data;
+               talloc_steal(ctdb, call->reply_data.dptr);
+       } else {
+               call->reply_data.dptr = NULL;
+               call->reply_data.dsize = 0;
        }
 
        talloc_free(c);
@@ -287,20 +284,22 @@ void ctdb_request_dmaster(struct ctdb_context *ctdb, struct ctdb_req_header *hdr
 void ctdb_request_call(struct ctdb_context *ctdb, struct ctdb_req_header *hdr)
 {
        struct ctdb_req_call *c = (struct ctdb_req_call *)hdr;
-       TDB_DATA key, data, call_data, reply_data;
+       TDB_DATA data;
        struct ctdb_reply_call *r;
        int ret, len;
        struct ctdb_ltdb_header header;
+       struct ctdb_call call;
 
-       key.dptr = c->data;
-       key.dsize = c->keylen;
-       call_data.dptr = c->data + c->keylen;
-       call_data.dsize = c->calldatalen;
+       call.call_id  = c->callid;
+       call.key.dptr = c->data;
+       call.key.dsize = c->keylen;
+       call.call_data.dptr = c->data + c->keylen;
+       call.call_data.dsize = c->calldatalen;
 
        /* determine if we are the dmaster for this key. This also
           fetches the record data (if any), thus avoiding a 2nd fetch of the data 
           if the call will be answered locally */
-       ret = ctdb_ltdb_fetch(ctdb, key, &header, &data);
+       ret = ctdb_ltdb_fetch(ctdb, call.key, &header, &data);
        if (ret != 0) {
                ctdb_send_error(ctdb, hdr, ret, "ltdb fetch failed in ctdb_request_call");
                return;
@@ -318,16 +317,14 @@ void ctdb_request_call(struct ctdb_context *ctdb, struct ctdb_req_header *hdr)
           then give them the record */
        if (header.laccessor == c->hdr.srcnode &&
            header.lacount >= ctdb->max_lacount) {
-               ctdb_call_send_dmaster(ctdb, c, &header, &key, &data);
+               ctdb_call_send_dmaster(ctdb, c, &header, &call.key, &data);
                talloc_free(data.dptr);
                return;
        }
 
-       ctdb_call_local(ctdb, key, &header, &data, c->callid, 
-                       call_data.dsize?&call_data:NULL,
-                       &reply_data, c->hdr.srcnode);
+       ctdb_call_local(ctdb, &call, &header, &data, c->hdr.srcnode);
 
-       len = offsetof(struct ctdb_reply_call, data) + reply_data.dsize;
+       len = offsetof(struct ctdb_reply_call, data) + call.reply_data.dsize;
        r = ctdb->methods->allocate_pkt(ctdb, len);
        CTDB_NO_MEMORY_FATAL(ctdb, r);
        r->hdr.length    = len;
@@ -335,12 +332,12 @@ void ctdb_request_call(struct ctdb_context *ctdb, struct ctdb_req_header *hdr)
        r->hdr.destnode  = hdr->srcnode;
        r->hdr.srcnode   = hdr->destnode;
        r->hdr.reqid     = hdr->reqid;
-       r->datalen       = reply_data.dsize;
-       memcpy(&r->data[0], reply_data.dptr, reply_data.dsize);
+       r->datalen       = call.reply_data.dsize;
+       memcpy(&r->data[0], call.reply_data.dptr, call.reply_data.dsize);
 
        ctdb_queue_packet(ctdb, &r->hdr);
 
-       talloc_free(reply_data.dptr);
+       talloc_free(call.reply_data.dptr);
        talloc_free(r);
 }
 
@@ -354,9 +351,7 @@ struct ctdb_call_state {
        struct ctdb_req_call *c;
        struct ctdb_node *node;
        const char *errmsg;
-       TDB_DATA call_data;
-       TDB_DATA reply_data;
-       TDB_DATA key;
+       struct ctdb_call call;
        int redirect_count;
        struct ctdb_ltdb_header header;
 };
@@ -380,7 +375,7 @@ void ctdb_reply_call(struct ctdb_context *ctdb, struct ctdb_req_header *hdr)
        reply_data.dptr = c->data;
        reply_data.dsize = c->datalen;
 
-       state->reply_data = reply_data;
+       state->call.reply_data = reply_data;
 
        talloc_steal(state, c);
 
@@ -412,14 +407,12 @@ void ctdb_reply_dmaster(struct ctdb_context *ctdb, struct ctdb_req_header *hdr)
           and data */
        state->header.dmaster = ctdb->vnn;
 
-       if (ctdb_ltdb_store(ctdb, state->key, &state->header, data) != 0) {
+       if (ctdb_ltdb_store(ctdb, state->call.key, &state->header, data) != 0) {
                ctdb_fatal(ctdb, "ctdb_reply_dmaster store failed\n");
                return;
        }
 
-       ctdb_call_local(ctdb, state->key, &state->header, &data, state->c->callid,
-                       state->call_data.dsize?&state->call_data:NULL,
-                       &state->reply_data, ctdb->vnn);
+       ctdb_call_local(ctdb, &state->call, &state->header, &data, ctdb->vnn);
 
        state->state = CTDB_CALL_DONE;
 }
@@ -462,7 +455,7 @@ void ctdb_reply_redirect(struct ctdb_context *ctdb, struct ctdb_req_header *hdr)
        
        /* don't allow for too many redirects */
        if (state->redirect_count++ == CTDB_MAX_REDIRECT) {
-               c->dmaster = ctdb_lmaster(ctdb, &state->key);
+               c->dmaster = ctdb_lmaster(ctdb, &state->call.key);
        }
 
        /* send it off again */
@@ -500,8 +493,7 @@ void ctdb_call_timeout(struct event_context *ev, struct timed_event *te,
   in an event driven manner
 */
 struct ctdb_call_state *ctdb_call_local_send(struct ctdb_context *ctdb, 
-                                            TDB_DATA key, int call_id, 
-                                            TDB_DATA *call_data, TDB_DATA *reply_data,
+                                            struct ctdb_call *call,
                                             struct ctdb_ltdb_header *header,
                                             TDB_DATA *data)
 {
@@ -514,9 +506,7 @@ struct ctdb_call_state *ctdb_call_local_send(struct ctdb_context *ctdb,
        state->state = CTDB_CALL_DONE;
        state->node = ctdb->nodes[ctdb->vnn];
 
-       ret = ctdb_call_local(ctdb, key, header, data, 
-                             call_id, call_data, &state->reply_data, 
-                             ctdb->vnn);
+       ret = ctdb_call_local(ctdb, call, header, data, ctdb->vnn);
        return state;
 }
 
@@ -527,9 +517,7 @@ struct ctdb_call_state *ctdb_call_local_send(struct ctdb_context *ctdb,
   This constructs a ctdb_call request and queues it for processing. 
   This call never blocks.
 */
-struct ctdb_call_state *ctdb_call_send(struct ctdb_context *ctdb, 
-                                      TDB_DATA key, int call_id, 
-                                      TDB_DATA *call_data, TDB_DATA *reply_data)
+struct ctdb_call_state *ctdb_call_send(struct ctdb_context *ctdb, struct ctdb_call *call)
 {
        uint32_t len;
        struct ctdb_call_state *state;
@@ -543,18 +531,17 @@ struct ctdb_call_state *ctdb_call_send(struct ctdb_context *ctdb,
          locally. To find out if we are the dmaster we need to look
          in our ltdb
        */
-       ret = ctdb_ltdb_fetch(ctdb, key, &header, &data);
+       ret = ctdb_ltdb_fetch(ctdb, call->key, &header, &data);
        if (ret != 0) return NULL;
 
        if (header.dmaster == ctdb->vnn && !(ctdb->flags & CTDB_FLAG_SELF_CONNECT)) {
-               return ctdb_call_local_send(ctdb, key, call_id, call_data, reply_data,
-                                           &header, &data);
+               return ctdb_call_local_send(ctdb, call, &header, &data);
        }
 
        state = talloc_zero(ctdb, struct ctdb_call_state);
        CTDB_NO_MEMORY_NULL(ctdb, state);
 
-       len = offsetof(struct ctdb_req_call, data) + key.dsize + (call_data?call_data->dsize:0);
+       len = offsetof(struct ctdb_req_call, data) + call->key.dsize + call->call_data.dsize;
        state->c = ctdb->methods->allocate_pkt(ctdb, len);
        CTDB_NO_MEMORY_NULL(ctdb, state->c);
 
@@ -564,17 +551,17 @@ struct ctdb_call_state *ctdb_call_send(struct ctdb_context *ctdb,
        state->c->hdr.srcnode   = ctdb->vnn;
        /* this limits us to 16k outstanding messages - not unreasonable */
        state->c->hdr.reqid     = idr_get_new(ctdb->idr, state, 0xFFFF);
-       state->c->callid        = call_id;
-       state->c->keylen        = key.dsize;
-       state->c->calldatalen   = call_data?call_data->dsize:0;
-       memcpy(&state->c->data[0], key.dptr, key.dsize);
-       if (call_data) {
-               memcpy(&state->c->data[key.dsize], call_data->dptr, call_data->dsize);
-               state->call_data.dptr = &state->c->data[key.dsize];
-               state->call_data.dsize = call_data->dsize;
-       }
-       state->key.dptr         = &state->c->data[0];
-       state->key.dsize        = key.dsize;
+       state->c->callid        = call->call_id;
+       state->c->keylen        = call->key.dsize;
+       state->c->calldatalen   = call->call_data.dsize;
+       memcpy(&state->c->data[0], call->key.dptr, call->key.dsize);
+       memcpy(&state->c->data[call->key.dsize], 
+              call->call_data.dptr, call->call_data.dsize);
+       state->call.call_data.dptr = &state->c->data[call->key.dsize];
+       state->call.call_data.dsize = call->call_data.dsize;
+
+       state->call.key.dptr         = &state->c->data[0];
+       state->call.key.dsize        = call->key.dsize;
 
        state->node   = ctdb->nodes[header.dmaster];
        state->state  = CTDB_CALL_WAIT;
@@ -596,7 +583,7 @@ struct ctdb_call_state *ctdb_call_send(struct ctdb_context *ctdb,
   This is called when the program wants to wait for a ctdb_call to complete and get the 
   results. This call will block unless the call has already completed.
 */
-int ctdb_call_recv(struct ctdb_call_state *state, TDB_DATA *reply_data)
+int ctdb_call_recv(struct ctdb_call_state *state, struct ctdb_call *call)
 {
        while (state->state < CTDB_CALL_DONE) {
                event_loop_once(state->node->ctdb->ev);
@@ -606,12 +593,10 @@ int ctdb_call_recv(struct ctdb_call_state *state, TDB_DATA *reply_data)
                talloc_free(state);
                return -1;
        }
-       if (reply_data) {
-               reply_data->dptr = talloc_memdup(state->node->ctdb,
-                                                state->reply_data.dptr,
-                                                state->reply_data.dsize);
-               reply_data->dsize = state->reply_data.dsize;
-       }
+       call->reply_data.dptr = talloc_memdup(state->node->ctdb,
+                                             state->call.reply_data.dptr,
+                                             state->call.reply_data.dsize);
+       call->reply_data.dsize = state->call.reply_data.dsize;
        talloc_free(state);
        return 0;
 }
@@ -619,11 +604,9 @@ int ctdb_call_recv(struct ctdb_call_state *state, TDB_DATA *reply_data)
 /*
   full ctdb_call. Equivalent to a ctdb_call_send() followed by a ctdb_call_recv()
 */
-int ctdb_call(struct ctdb_context *ctdb, 
-             TDB_DATA key, int call_id, 
-             TDB_DATA *call_data, TDB_DATA *reply_data)
+int ctdb_call(struct ctdb_context *ctdb, struct ctdb_call *call)
 {
        struct ctdb_call_state *state;
-       state = ctdb_call_send(ctdb, key, call_id, call_data, reply_data);
-       return ctdb_call_recv(state, reply_data);
+       state = ctdb_call_send(ctdb, call);
+       return ctdb_call_recv(state, call);
 }
index 7a9db5b2e180926436c17edb67b57b21b5d8f812..31abefc43fa5ab166b820f52d9a6373197774f01 100644 (file)
@@ -81,18 +81,23 @@ static int fetch_func(struct ctdb_call_info *call)
 */
 static void bench_incr(struct ctdb_context *ctdb)
 {
-       TDB_DATA key, data;
        int loops=0;
        int ret, i;
+       struct ctdb_call call;
+
+       ZERO_STRUCT(call);
 
        start_timer();
 
        while (1) {
                uint32_t v = loops % num_records;
-               key.dptr = &v;
-               key.dsize = 4;
+
+               call.call_id = FUNC_INCR;
+               call.key.dptr = (uint8_t *)&v;
+               call.key.dsize = 4;
+
                for (i=0;i<num_repeats;i++) {
-                       ret = ctdb_call(ctdb, key, FUNC_INCR, NULL, NULL);
+                       ret = ctdb_call(ctdb, &call);
                        if (ret != 0) {
                                printf("incr call failed - %s\n", ctdb_errstr(ctdb));
                                return;
@@ -105,14 +110,16 @@ static void bench_incr(struct ctdb_context *ctdb)
                }
        }
 
-       ret = ctdb_call(ctdb, key, FUNC_FETCH, NULL, &data);
+       call.call_id = FUNC_FETCH;
+
+       ret = ctdb_call(ctdb, &call);
        if (ret == -1) {
                printf("ctdb_call FUNC_FETCH failed - %s\n", ctdb_errstr(ctdb));
                return;
        }
 
        printf("Incr: %.2f ops/sec (loops=%d val=%d)\n", 
-              num_repeats*loops/end_timer(), loops, *(uint32_t *)data.dptr);
+              num_repeats*loops/end_timer(), loops, *(uint32_t *)call.reply_data.dptr);
 }
 
 /*
index 7f3430ad1aa33cdb79031bc4590b7a98698cc713..faf51f723bd96addc5577650321ffedc54f45aa1 100644 (file)
@@ -93,9 +93,9 @@ int main(int argc, const char *argv[])
        const char **extra_argv;
        int extra_argc = 0;
        int i, ret;
-       TDB_DATA key, data;
        poptContext pc;
        struct event_context *ev;
+       struct ctdb_call call;
 
        pc = poptGetContext(argv[0], argc, argv, popt_options, POPT_CONTEXT_KEEP_FIRST);
 
@@ -171,15 +171,19 @@ int main(int argc, const char *argv[])
           outide of test code) */
        ctdb_connect_wait(ctdb);
        
-       key.dptr = "test";
-       key.dsize = strlen("test")+1;
+       ZERO_STRUCT(call);
+       call.key.dptr = "test";
+       call.key.dsize = strlen("test")+1;
 
        /* add some random data */
        for (i=0;i<10;i++) {
                int v = random() % 1000;
-               data.dptr = (uint8_t *)&v;
-               data.dsize = sizeof(v);
-               ret = ctdb_call(ctdb, key, FUNC_SORT, &data, NULL);
+
+               call.call_id = FUNC_SORT;
+               call.call_data.dptr = (uint8_t *)&v;
+               call.call_data.dsize = sizeof(v);
+
+               ret = ctdb_call(ctdb, &call);
                if (ret == -1) {
                        printf("ctdb_call FUNC_SORT failed - %s\n", ctdb_errstr(ctdb));
                        exit(1);
@@ -187,16 +191,20 @@ int main(int argc, const char *argv[])
        }
 
        /* fetch the record */
-       ret = ctdb_call(ctdb, key, FUNC_FETCH, NULL, &data);
+       call.call_id = FUNC_FETCH;
+       call.call_data.dptr = NULL;
+       call.call_data.dsize = 0;
+
+       ret = ctdb_call(ctdb, &call);
        if (ret == -1) {
                printf("ctdb_call FUNC_FETCH failed - %s\n", ctdb_errstr(ctdb));
                exit(1);
        }
 
-       for (i=0;i<data.dsize/sizeof(int);i++) {
-               printf("%3d\n", ((int *)data.dptr)[i]);
+       for (i=0;i<call.reply_data.dsize/sizeof(int);i++) {
+               printf("%3d\n", ((int *)call.reply_data.dptr)[i]);
        }
-       talloc_free(data.dptr);
+       talloc_free(call.reply_data.dptr);
 
        /* go into a wait loop to allow other nodes to complete */
        ctdb_wait_loop(ctdb);
index 4683cde3888d861e1ae93a6ce6c76b461a927f96..8a2006f678df6cff425711211e810654dba63689 100644 (file)
 #ifndef _CTDB_H
 #define _CTDB_H
 
+struct ctdb_call {
+       int call_id;
+       TDB_DATA key;
+       TDB_DATA call_data;
+       TDB_DATA reply_data;
+};
+
 /*
-  structure passed to a ctdb call function
+  structure passed to a ctdb call backend function
 */
 struct ctdb_call_info {
        TDB_DATA key;          /* record key */
@@ -103,8 +110,7 @@ int ctdb_attach(struct ctdb_context *ctdb, const char *name, int tdb_flags,
   make a ctdb call. The associated ctdb call function will be called on the DMASTER
   for the given record
 */
-int ctdb_call(struct ctdb_context *ctdb, TDB_DATA key, int call_id, 
-             TDB_DATA *call_data, TDB_DATA *reply_data);
+int ctdb_call(struct ctdb_context *ctdb, struct ctdb_call *call);
 
 /*
   wait for all nodes to be connected - useful for test code