Author: astitcher
Date: Tue Jun  3 20:43:20 2014
New Revision: 1599793

URL: http://svn.apache.org/r1599793
Log:
PROTON-591, PROTON-590: Change frame dispatch to use switch statement
- Rather than an explicit function table
- This reduces the per connection memory use significantly
- Fixes a possible crash if Proton receives an unknown performative

Added:
    qpid/proton/trunk/proton-c/src/dispatch_actions.h
Modified:
    qpid/proton/trunk/proton-c/src/dispatcher/dispatcher.c
    qpid/proton/trunk/proton-c/src/dispatcher/dispatcher.h
    qpid/proton/trunk/proton-c/src/sasl/sasl.c
    qpid/proton/trunk/proton-c/src/transport/transport.c

Added: qpid/proton/trunk/proton-c/src/dispatch_actions.h
URL: 
http://svn.apache.org/viewvc/qpid/proton/trunk/proton-c/src/dispatch_actions.h?rev=1599793&view=auto
==============================================================================
--- qpid/proton/trunk/proton-c/src/dispatch_actions.h (added)
+++ qpid/proton/trunk/proton-c/src/dispatch_actions.h Tue Jun  3 20:43:20 2014
@@ -0,0 +1,45 @@
+#ifndef _PROTON_DISPATCH_ACTIONS_H
+#define _PROTON_DISPATCH_ACTIONS_H 1
+
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+
+#include "dispatcher/dispatcher.h"
+
+/* Transport actions */
+int pn_do_open(pn_dispatcher_t *disp);
+int pn_do_begin(pn_dispatcher_t *disp);
+int pn_do_attach(pn_dispatcher_t *disp);
+int pn_do_transfer(pn_dispatcher_t *disp);
+int pn_do_flow(pn_dispatcher_t *disp);
+int pn_do_disposition(pn_dispatcher_t *disp);
+int pn_do_detach(pn_dispatcher_t *disp);
+int pn_do_end(pn_dispatcher_t *disp);
+int pn_do_close(pn_dispatcher_t *disp);
+
+/* SASL actions */
+int pn_do_init(pn_dispatcher_t *disp);
+int pn_do_mechanisms(pn_dispatcher_t *disp);
+int pn_do_challenge(pn_dispatcher_t *disp);
+int pn_do_response(pn_dispatcher_t *disp);
+int pn_do_outcome(pn_dispatcher_t *disp);
+
+#endif // _PROTON_DISPATCH_ACTIONS_H

Modified: qpid/proton/trunk/proton-c/src/dispatcher/dispatcher.c
URL: 
http://svn.apache.org/viewvc/qpid/proton/trunk/proton-c/src/dispatcher/dispatcher.c?rev=1599793&r1=1599792&r2=1599793&view=diff
==============================================================================
--- qpid/proton/trunk/proton-c/src/dispatcher/dispatcher.c (original)
+++ qpid/proton/trunk/proton-c/src/dispatcher/dispatcher.c Tue Jun  3 20:43:20 
2014
@@ -30,6 +30,41 @@
 #include "../util.h"
 #include "../platform_fmt.h"
 
+#include "dispatch_actions.h"
+
+int pni_bad_frame(pn_dispatcher_t* disp) {
+  pn_transport_log(disp->transport, "Error dispatching frame: Unknown 
performative");
+  return PN_ERR;
+}
+
+// We could use a table based approach here if we needed to dynamically
+// add new performatives
+inline int pni_dispatch_action(pn_dispatcher_t* disp, uint64_t lcode)
+{
+  pn_action_t *action;
+  switch (lcode) {
+  /* Regular AMQP fames */
+  case OPEN:            action = pn_do_open; break;
+  case BEGIN:           action = pn_do_begin; break;
+  case ATTACH:          action = pn_do_attach; break;
+  case FLOW:            action = pn_do_flow; break;
+  case TRANSFER:        action = pn_do_transfer; break;
+  case DISPOSITION:     action = pn_do_disposition; break;
+  case DETACH:          action = pn_do_detach; break;
+  case END:             action = pn_do_end; break;
+  case CLOSE:           action = pn_do_close; break;
+
+  /* SASL frames */
+  case SASL_MECHANISMS: action = pn_do_mechanisms; break;
+  case SASL_INIT:       action = pn_do_init; break;
+  case SASL_CHALLENGE:  action = pn_do_challenge; break;
+  case SASL_RESPONSE:   action = pn_do_response; break;
+  case SASL_OUTCOME:    action = pn_do_outcome; break;
+  default:              action = pni_bad_frame; break;
+  };
+  return action(disp);
+}
+
 pn_dispatcher_t *pn_dispatcher(uint8_t frame_type, pn_transport_t *transport)
 {
   pn_dispatcher_t *disp = (pn_dispatcher_t *) calloc(sizeof(pn_dispatcher_t), 
1);
@@ -44,7 +79,6 @@ pn_dispatcher_t *pn_dispatcher(uint8_t f
   disp->fragment = 0;
 
   disp->channel = 0;
-  disp->code = 0;
   disp->args = pn_data(16);
   disp->payload = NULL;
   disp->size = 0;
@@ -77,12 +111,6 @@ void pn_dispatcher_free(pn_dispatcher_t 
   }
 }
 
-void pn_dispatcher_action(pn_dispatcher_t *disp, uint8_t code,
-                          pn_action_t *action)
-{
-  disp->actions[code] = action;
-}
-
 typedef enum {IN, OUT} pn_dir_t;
 
 static void pn_do_trace(pn_dispatcher_t *disp, uint16_t ch, pn_dir_t dir,
@@ -122,7 +150,8 @@ int pn_dispatch_frame(pn_dispatcher_t *d
   }
 
   disp->channel = frame.channel;
-  // XXX: assuming numeric
+  // XXX: assuming numeric -
+  // if we get a symbol we should map it to the numeric value and dispatch on 
that
   uint64_t lcode;
   bool scanned;
   int e = pn_data_scan(disp->args, "D?L.", &scanned, &lcode);
@@ -134,19 +163,15 @@ int pn_dispatch_frame(pn_dispatcher_t *d
     pn_transport_log(disp->transport, "Error dispatching frame");
     return PN_ERR;
   }
-  uint8_t code = lcode;
-  disp->code = code;
   disp->size = frame.size - dsize;
   if (disp->size)
     disp->payload = frame.payload + dsize;
 
   pn_do_trace(disp, disp->channel, IN, disp->args, disp->payload, disp->size);
 
-  pn_action_t *action = disp->actions[code];
-  int err = action(disp);
+  int err = pni_dispatch_action(disp, lcode);
 
   disp->channel = 0;
-  disp->code = 0;
   pn_data_clear(disp->args);
   disp->size = 0;
   disp->payload = NULL;

Modified: qpid/proton/trunk/proton-c/src/dispatcher/dispatcher.h
URL: 
http://svn.apache.org/viewvc/qpid/proton/trunk/proton-c/src/dispatcher/dispatcher.h?rev=1599793&r1=1599792&r2=1599793&view=diff
==============================================================================
--- qpid/proton/trunk/proton-c/src/dispatcher/dispatcher.h (original)
+++ qpid/proton/trunk/proton-c/src/dispatcher/dispatcher.h Tue Jun  3 20:43:20 
2014
@@ -34,7 +34,6 @@ typedef struct pn_dispatcher_t pn_dispat
 typedef int (pn_action_t)(pn_dispatcher_t *disp);
 
 struct pn_dispatcher_t {
-  pn_action_t *actions[256];
   pn_buffer_t *input;
   size_t fragment;
   pn_data_t *args;
@@ -48,22 +47,19 @@ struct pn_dispatcher_t {
   size_t capacity;
   size_t available; /* number of raw bytes pending output */
   char *output;
-  pn_transport_t *transport;
+  pn_transport_t *transport; // TODO: We keep this to get access to logging - 
perhaps move logging
   uint64_t output_frames_ct;
   uint64_t input_frames_ct;
   pn_string_t *scratch;
   pn_trace_t trace;
   uint16_t channel;
-  uint8_t frame_type;
-  uint8_t code;
+  uint8_t frame_type; // Used when constructing outgoing frames
   bool halt;
   bool batch;
 };
 
 pn_dispatcher_t *pn_dispatcher(uint8_t frame_type, pn_transport_t *transport);
 void pn_dispatcher_free(pn_dispatcher_t *disp);
-void pn_dispatcher_action(pn_dispatcher_t *disp, uint8_t code,
-                          pn_action_t *action);
 int pn_scan_args(pn_dispatcher_t *disp, const char *fmt, ...);
 void pn_set_payload(pn_dispatcher_t *disp, const char *data, size_t size);
 int pn_post_frame(pn_dispatcher_t *disp, uint16_t ch, const char *fmt, ...);

Modified: qpid/proton/trunk/proton-c/src/sasl/sasl.c
URL: 
http://svn.apache.org/viewvc/qpid/proton/trunk/proton-c/src/sasl/sasl.c?rev=1599793&r1=1599792&r2=1599793&view=diff
==============================================================================
--- qpid/proton/trunk/proton-c/src/sasl/sasl.c (original)
+++ qpid/proton/trunk/proton-c/src/sasl/sasl.c Tue Jun  3 20:43:20 2014
@@ -27,6 +27,7 @@
 #include <proton/engine.h> // XXX: just needed for PN_EOS
 #include <proton/sasl.h>
 #include "protocol.h"
+#include "dispatch_actions.h"
 #include "../dispatcher/dispatcher.h"
 #include "../engine/engine-internal.h"
 #include "../util.h"
@@ -55,12 +56,6 @@ static ssize_t pn_input_read_sasl(pn_io_
 static ssize_t pn_output_write_sasl_header(pn_io_layer_t *io_layer, char 
*bytes, size_t available);
 static ssize_t pn_output_write_sasl(pn_io_layer_t *io_layer, char *bytes, 
size_t available);
 
-int pn_do_init(pn_dispatcher_t *disp);
-int pn_do_mechanisms(pn_dispatcher_t *disp);
-int pn_do_challenge(pn_dispatcher_t *disp);
-int pn_do_response(pn_dispatcher_t *disp);
-int pn_do_outcome(pn_dispatcher_t *disp);
-
 pn_sasl_t *pn_sasl(pn_transport_t *transport)
 {
   if (!transport->sasl) {
@@ -68,12 +63,6 @@ pn_sasl_t *pn_sasl(pn_transport_t *trans
     sasl->disp = pn_dispatcher(1, transport);
     sasl->disp->batch = false;
 
-    pn_dispatcher_action(sasl->disp, SASL_INIT, pn_do_init);
-    pn_dispatcher_action(sasl->disp, SASL_MECHANISMS, pn_do_mechanisms);
-    pn_dispatcher_action(sasl->disp, SASL_CHALLENGE, pn_do_challenge);
-    pn_dispatcher_action(sasl->disp, SASL_RESPONSE, pn_do_response);
-    pn_dispatcher_action(sasl->disp, SASL_OUTCOME, pn_do_outcome);
-
     sasl->client = false;
     sasl->configured = false;
     sasl->mechanisms = NULL;

Modified: qpid/proton/trunk/proton-c/src/transport/transport.c
URL: 
http://svn.apache.org/viewvc/qpid/proton/trunk/proton-c/src/transport/transport.c?rev=1599793&r1=1599792&r2=1599793&view=diff
==============================================================================
--- qpid/proton/trunk/proton-c/src/transport/transport.c (original)
+++ qpid/proton/trunk/proton-c/src/transport/transport.c Tue Jun  3 20:43:20 
2014
@@ -24,6 +24,7 @@
 #include <string.h>
 #include <proton/framing.h>
 #include "protocol.h"
+#include "dispatch_actions.h"
 
 #include <assert.h>
 #include <stdarg.h>
@@ -92,16 +93,6 @@ void pn_delivery_map_clear(pn_delivery_m
   }
 }
 
-int pn_do_open(pn_dispatcher_t *disp);
-int pn_do_begin(pn_dispatcher_t *disp);
-int pn_do_attach(pn_dispatcher_t *disp);
-int pn_do_transfer(pn_dispatcher_t *disp);
-int pn_do_flow(pn_dispatcher_t *disp);
-int pn_do_disposition(pn_dispatcher_t *disp);
-int pn_do_detach(pn_dispatcher_t *disp);
-int pn_do_end(pn_dispatcher_t *disp);
-int pn_do_close(pn_dispatcher_t *disp);
-
 static ssize_t pn_input_read_amqp_header(pn_io_layer_t *io_layer, const char 
*bytes, size_t available);
 static ssize_t pn_input_read_amqp(pn_io_layer_t *io_layer, const char *bytes, 
size_t available);
 static ssize_t pn_output_write_amqp_header(pn_io_layer_t *io_layer, char 
*bytes, size_t available);
@@ -150,16 +141,6 @@ static void pn_transport_initialize(void
   amqp->buffered_input = NULL;
   amqp->next = NULL;
 
-  pn_dispatcher_action(transport->disp, OPEN, pn_do_open);
-  pn_dispatcher_action(transport->disp, BEGIN, pn_do_begin);
-  pn_dispatcher_action(transport->disp, ATTACH, pn_do_attach);
-  pn_dispatcher_action(transport->disp, TRANSFER, pn_do_transfer);
-  pn_dispatcher_action(transport->disp, FLOW, pn_do_flow);
-  pn_dispatcher_action(transport->disp, DISPOSITION, pn_do_disposition);
-  pn_dispatcher_action(transport->disp, DETACH, pn_do_detach);
-  pn_dispatcher_action(transport->disp, END, pn_do_end);
-  pn_dispatcher_action(transport->disp, CLOSE, pn_do_close);
-
   transport->open_sent = false;
   transport->open_rcvd = false;
   transport->close_sent = false;



---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to