]> git.ipfire.org Git - thirdparty/samba.git/commitdiff
added error reply packets
authorAndrew Tridgell <tridge@samba.org>
Mon, 18 Dec 2006 03:27:20 +0000 (14:27 +1100)
committerAndrew Tridgell <tridge@samba.org>
Mon, 18 Dec 2006 03:27:20 +0000 (14:27 +1100)
(This used to be ctdb commit 49ee165808985ce0fa174dd6e05292871d3f3130)

ctdb/common/ctdb.c
ctdb/common/ctdb_call.c
ctdb/include/ctdb_private.h

index f09f6029b1b2a6b1fe7fda7e87e6443455532cc2..80e4649c4da6c89389a71511870964a51c0b349d 100644 (file)
@@ -177,6 +177,10 @@ static void ctdb_recv_pkt(struct ctdb_context *ctdb, uint8_t *data, uint32_t len
                ctdb_reply_call(ctdb, hdr);
                break;
 
+       case CTDB_REPLY_ERROR:
+               ctdb_reply_error(ctdb, hdr);
+               break;
+
        default:
                printf("Packet with unknown operation %d\n", hdr->operation);
                talloc_free(hdr);
index 74d97ee5994b9dacf74156997870910790b37f3a..6349146b12d6c38a69b16e254ed20b875c3ae35c 100644 (file)
@@ -85,9 +85,42 @@ static int ctdb_call_local(struct ctdb_context *ctdb, TDB_DATA key,
   send an error reply
 */
 static void ctdb_send_error(struct ctdb_context *ctdb, 
-                           struct ctdb_req_header *hdr, int ecode)
+                           struct ctdb_req_header *hdr, uint32_t status,
+                           const char *fmt, ...)
 {
-       printf("ctdb_send_error not implemented\n");
+       va_list ap;
+       struct ctdb_reply_error *r;
+       char *msg;
+       int len;
+       struct ctdb_node *node;
+
+       va_start(ap, fmt);
+       msg = talloc_vasprintf(ctdb, fmt, ap);
+       if (msg == NULL) {
+               /* can't send an error message, need to rely on call
+                  timeouts instead */
+               return;
+       }
+       va_end(ap);
+
+       len = strlen(msg)+1;
+       r = talloc_size(ctdb, sizeof(*r) + len);
+       r->hdr.length = sizeof(*r) + len;
+       r->hdr.operation = CTDB_REPLY_ERROR;
+       r->hdr.destnode  = hdr->srcnode;
+       r->hdr.srcnode   = ctdb->vnn;
+       r->hdr.reqid     = hdr->reqid;
+       r->status        = status;
+       r->msglen        = len;
+       memcpy(&r->msg[0], msg, len);
+
+       talloc_free(msg);
+
+       node = ctdb->nodes[hdr->srcnode];
+
+       ctdb->methods->queue_pkt(node, (uint8_t *)r, r->hdr.length);
+
+       talloc_free(r);
 }
 
 /*
@@ -122,7 +155,7 @@ void ctdb_request_call(struct ctdb_context *ctdb, struct ctdb_req_header *hdr)
           if the call will be answered locally */
        ret = ctdb_ltdb_fetch(ctdb, key, &header, &data);
        if (ret != 0) {
-               ctdb_send_error(ctdb, hdr, ret);
+               ctdb_send_error(ctdb, hdr, ret, "ltdb fetch failed in ctdb_request_call");
                return;
        }
 
@@ -164,6 +197,7 @@ struct ctdb_call_state {
        enum call_state state;
        struct ctdb_req_call *c;
        struct ctdb_node *node;
+       const char *errmsg;
        TDB_DATA reply_data;
 };
 
@@ -189,6 +223,23 @@ void ctdb_reply_call(struct ctdb_context *ctdb, struct ctdb_req_header *hdr)
        state->state = CTDB_CALL_DONE;
 }
 
+
+/*
+  called when a CTDB_REPLY_ERROR packet comes in
+*/
+void ctdb_reply_error(struct ctdb_context *ctdb, struct ctdb_req_header *hdr)
+{
+       struct ctdb_reply_error *c = (struct ctdb_reply_error *)hdr;
+       struct ctdb_call_state *state;
+
+       state = idr_find(ctdb->idr, hdr->reqid);
+
+       talloc_steal(state, c);
+
+       state->state  = CTDB_CALL_ERROR;
+       state->errmsg = (char *)c->msg;
+}
+
 /*
   destroy a ctdb_call
 */
@@ -306,6 +357,7 @@ int ctdb_call_recv(struct ctdb_call_state *state, TDB_DATA *reply_data)
                event_loop_once(state->node->ctdb->ev);
        }
        if (state->state != CTDB_CALL_DONE) {
+               ctdb_set_error(state->node->ctdb, "%s", state->errmsg);
                talloc_free(state);
                return -1;
        }
index 8675dccaddfeea30699d7ff49cfe642b695b8051..6270ac3132fa9d967aa82d6fb9ace76d78a0ceda 100644 (file)
@@ -116,11 +116,12 @@ struct ctdb_ltdb_header {
   operation IDs
 */
 enum ctdb_operation {
-       CTDB_REQ_CALL   = 0,
-       CTDB_REPLY_CALL = 1,
+       CTDB_REQ_CALL       = 0,
+       CTDB_REPLY_CALL     = 1,
        CTDB_REPLY_REDIRECT = 2,
-       CTDB_REQ_DMASTER = 3,
-       CTDB_REPLY_DMASTER = 4,
+       CTDB_REQ_DMASTER    = 3,
+       CTDB_REPLY_DMASTER  = 4,
+       CTDB_REPLY_ERROR    = 5
 };
 
 /*
@@ -148,6 +149,13 @@ struct ctdb_reply_call {
        uint8_t  data[0];
 };
 
+struct ctdb_reply_error {
+       struct ctdb_req_header hdr;
+       uint32_t status;
+       uint32_t msglen;
+       uint8_t  msg[0];
+};
+
 /* internal prototypes */
 void ctdb_set_error(struct ctdb_context *ctdb, const char *fmt, ...);
 bool ctdb_same_address(struct ctdb_address *a1, struct ctdb_address *a2);
@@ -157,6 +165,7 @@ int ctdb_parse_address(struct ctdb_context *ctdb,
 uint32_t ctdb_hash(TDB_DATA *key);
 void ctdb_request_call(struct ctdb_context *ctdb, struct ctdb_req_header *hdr);
 void ctdb_reply_call(struct ctdb_context *ctdb, struct ctdb_req_header *hdr);
+void ctdb_reply_error(struct ctdb_context *ctdb, struct ctdb_req_header *hdr);
 
 int ctdb_ltdb_fetch(struct ctdb_context *ctdb, 
                    TDB_DATA key, struct ctdb_ltdb_header *header, TDB_DATA *data);