You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@trafficserver.apache.org by zw...@apache.org on 2014/04/20 21:20:24 UTC

[07/50] [abbrv] TS-2637: add traffic_line records match option

http://git-wip-us.apache.org/repos/asf/trafficserver/blob/0389be39/mgmt/api/NetworkUtilsRemote.cc
----------------------------------------------------------------------
diff --git a/mgmt/api/NetworkUtilsRemote.cc b/mgmt/api/NetworkUtilsRemote.cc
index 3bf941a..da4c9ab 100644
--- a/mgmt/api/NetworkUtilsRemote.cc
+++ b/mgmt/api/NetworkUtilsRemote.cc
@@ -61,7 +61,6 @@ extern TSInitOptionT ts_init_options;
 /**********************************************************************
  * Socket Helper Functions
  **********************************************************************/
-
 void
 set_socket_paths(const char *path)
 {
@@ -773,32 +772,25 @@ send_file_write_request(int fd, TSFileNameT file, int ver, int size, char *text)
   return err;
 }
 
-/**********************************************************************
- * send_record_get_request
- *
- * purpose: sends request to get record value from Traffic Manager
- * input: fd       - file descriptor to use
- *        rec_name - name of record to retrieve value for
- * output: TS_ERR_xx
- * format: RECORD_GET <msg_len> <rec_name>
- **********************************************************************/
-TSError
-send_record_get_request(int fd, char *rec_name)
+static TSError
+send_record_get_x_request(OpType optype, int fd, const char *rec_name)
 {
   char *msg_buf;
   int msg_pos = 0, total_len;
-  int16_t op;
+  int16_t op = (int16_t)optype;
   int32_t msg_len;
   TSError err;
 
-  if (!rec_name)
+  ink_assert(op == RECORD_GET || op == RECORD_MATCH_GET);
+
+  if (!rec_name) {
     return TS_ERR_PARAMS;
+  }
 
   total_len = SIZE_OP_T + SIZE_LEN + strlen(rec_name);
   msg_buf = (char *)ats_malloc(sizeof(char) * total_len);
 
   // fill in op type
-  op = (int16_t) RECORD_GET;
   memcpy(msg_buf + msg_pos, (void *) &op, SIZE_OP_T);
   msg_pos += SIZE_OP_T;
 
@@ -816,6 +808,35 @@ send_record_get_request(int fd, char *rec_name)
   return err;
 }
 
+/**********************************************************************
+ * send_record_get_request
+ *
+ * purpose: sends request to get record value from Traffic Manager
+ * input: fd       - file descriptor to use
+ *        rec_name - name of record to retrieve value for
+ * output: TS_ERR_xx
+ * format: RECORD_GET <msg_len> <rec_name>
+ **********************************************************************/
+TSError
+send_record_get_request(int fd, const char *rec_name)
+{
+  return send_record_get_x_request(RECORD_GET, fd, rec_name);
+}
+
+/**********************************************************************
+ * send_record_match_request
+ *
+ * purpose: sends request to get a list of matching record values from Traffic Manager
+ * input: fd       - file descriptor to use
+ *        rec_name - regex to match against record names
+ * output: TS_ERR_xx
+ * format: sequence of RECORD_GET <msg_len> <rec_name>
+ **********************************************************************/
+TSError
+send_record_match_request(int fd, const char *rec_regex)
+{
+  return send_record_get_x_request(RECORD_MATCH_GET, fd, rec_regex);
+}
 
 /*------ control functions -------------------------------------------*/
 /**********************************************************************
@@ -1231,19 +1252,25 @@ parse_file_read_reply(int fd, int *ver, int *size, char **text)
  *        rec_value - the value of the record in string format
  * output: errors on error or fill up class with response &
  *         return SUCC
- * notes: reply format = <TSError> <val_size> <rec_type> <record_value>
+ * notes: reply format = <TSError> <val_size> <name_size> <rec_type> <record_value> <record_name>
+ * Zero-length values and names are supported. If the size field is 0, the corresponding
+ * value field is not transmitted.
  * It's the responsibility of the calling function to conver the rec_value
  * based on the rec_type!!
  **********************************************************************/
 TSError
-parse_record_get_reply(int fd, TSRecordT * rec_type, void **rec_val)
+parse_record_get_reply(int fd, TSRecordT * rec_type, void **rec_val, char **rec_name)
 {
   int16_t ret_val, rec_t;
-  int32_t rec_size;
+  int32_t val_size, name_size;
   TSError err_t;
 
-  if (!rec_type || !rec_val)
+  if (!rec_type || !rec_val) {
     return TS_ERR_PARAMS;
+  }
+
+  *rec_name = NULL;
+  *rec_val = NULL;
 
   // check to see if anything to read; wait for specified time
   if (socket_read_timeout(fd, MAX_TIME_WAIT, 0) <= 0) { //time expired before ready to read
@@ -1253,49 +1280,72 @@ parse_record_get_reply(int fd, TSRecordT * rec_type, void **rec_val)
   // get the return value (TSError type)
   err_t = socket_read_conn(fd, (uint8_t *)&ret_val, SIZE_ERR_T);
   if (err_t != TS_ERR_OKAY) {
-    return err_t;
+    goto fail;
   }
 
   // if !TS_ERR_OKAY, stop reading rest of msg
   err_t = (TSError) ret_val;
   if (err_t != TS_ERR_OKAY) {
-    return err_t;
+    goto fail;
   }
 
   // now get size of record_value
-  err_t = socket_read_conn(fd, (uint8_t *)&rec_size, SIZE_LEN);
+  err_t = socket_read_conn(fd, (uint8_t *)&val_size, SIZE_LEN);
   if (err_t != TS_ERR_OKAY) {
-    return err_t;
+    goto fail;
+  }
+
+  // now get size of record name
+  err_t = socket_read_conn(fd, (uint8_t *)&name_size, SIZE_LEN);
+  if (err_t != TS_ERR_OKAY) {
+    goto fail;
   }
 
   // get the record type
   err_t = socket_read_conn(fd, (uint8_t *)&rec_t, SIZE_REC_T);
   if (err_t != TS_ERR_OKAY) {
-    return err_t;
+    goto fail;
   }
 
   *rec_type = (TSRecordT) rec_t;
 
-  // get record value
-  // allocate correct amount of memory for record value
-  if (*rec_type == TS_REC_STRING) {
-    *rec_val = ats_malloc(sizeof(char) * (rec_size + 1));
-  } else {
-    *rec_val = ats_malloc(sizeof(char) * (rec_size));
-  }
+  // get record value (if there is one)
+  if (val_size) {
+    if (*rec_type == TS_REC_STRING) {
+      *rec_val = ats_malloc(sizeof(char) * (val_size + 1));
+    } else {
+      *rec_val = ats_malloc(sizeof(char) * (val_size));
+    }
 
-  err_t = socket_read_conn(fd, (uint8_t *)(*rec_val), rec_size);
-  if (err_t != TS_ERR_OKAY) {
-    ats_free(*rec_val);
-    *rec_val = NULL;
-    return err_t;
+    err_t = socket_read_conn(fd, (uint8_t *)(*rec_val), val_size);
+    if (err_t != TS_ERR_OKAY) {
+      goto fail;
+    }
+
+    // add end of string to end of the record value
+    if (*rec_type == TS_REC_STRING) {
+      ((char *) (*rec_val))[val_size] = '\0';
+    }
   }
 
-  // add end of string to end of the record value
-  if (*rec_type == TS_REC_STRING) {
-    ((char *) (*rec_val))[rec_size] = '\0';
+  // get the record name (if there is one)
+  if (name_size) {
+    *rec_name = (char *)ats_malloc(sizeof(char) * (name_size + 1));
+    err_t = socket_read_conn(fd, (uint8_t *)(*rec_name), name_size);
+    if (err_t != TS_ERR_OKAY) {
+      goto fail;
+    }
+
+    (*rec_name)[name_size] = '\0';
   }
 
+  return TS_ERR_OKAY;
+
+fail:
+  ats_free(*rec_val);
+  ats_free(*rec_name);
+  *rec_val = NULL;
+  *rec_name = NULL;
   return err_t;
 }
 

http://git-wip-us.apache.org/repos/asf/trafficserver/blob/0389be39/mgmt/api/NetworkUtilsRemote.h
----------------------------------------------------------------------
diff --git a/mgmt/api/NetworkUtilsRemote.h b/mgmt/api/NetworkUtilsRemote.h
index b30ac14..f251dc0 100644
--- a/mgmt/api/NetworkUtilsRemote.h
+++ b/mgmt/api/NetworkUtilsRemote.h
@@ -76,7 +76,8 @@ TSError send_request_bool(int fd, OpType op, bool flag);
 
 TSError send_file_read_request(int fd, TSFileNameT file);
 TSError send_file_write_request(int fd, TSFileNameT file, int ver, int size, char *text);
-TSError send_record_get_request(int fd, char *rec_name);
+TSError send_record_get_request(int fd, const char *rec_name);
+TSError send_record_match_request(int fd, const char *rec_regex);
 
 TSError send_proxy_state_set_request(int fd, TSProxyStateT state, TSCacheClearT clear);
 
@@ -93,7 +94,7 @@ TSError parse_reply_list(int fd, char **list);
 
 TSError parse_file_read_reply(int fd, int *version, int *size, char **text);
 
-TSError parse_record_get_reply(int fd, TSRecordT * rec_type, void **rec_val);
+TSError parse_record_get_reply(int fd, TSRecordT * rec_type, void **rec_val, char **rec_name);
 TSError parse_record_set_reply(int fd, TSActionNeedT * action_need);
 
 TSError parse_proxy_state_get_reply(int fd, TSProxyStateT * state);

http://git-wip-us.apache.org/repos/asf/trafficserver/blob/0389be39/mgmt/api/TSControlMain.cc
----------------------------------------------------------------------
diff --git a/mgmt/api/TSControlMain.cc b/mgmt/api/TSControlMain.cc
index c507f5b..950e3b5 100644
--- a/mgmt/api/TSControlMain.cc
+++ b/mgmt/api/TSControlMain.cc
@@ -210,198 +210,83 @@ ts_ctrl_main(void *arg)
               con_entry = ink_hash_table_iterator_next(accepted_con, &con_state);
               continue;
             }
+
             // determine which handler function to call based on operation
             switch (op_t) {
             case RECORD_GET:
               ret = handle_record_get(client_entry->sock_info, req);
-              ats_free(req);     // free memory for req
-              if (ret == TS_ERR_NET_WRITE || ret == TS_ERR_NET_EOF) {
-                Debug("ts_main", "[ts_ctrl_main] ERROR:handle_record_get\n");
-                remove_client(client_entry, accepted_con);
-                con_entry = ink_hash_table_iterator_next(accepted_con, &con_state);
-                continue;
-              }
+              break;
+
+            case RECORD_MATCH_GET:
+              ret = handle_record_match(client_entry->sock_info, req);
+              // XXX
               break;
 
             case RECORD_SET:
               ret = handle_record_set(client_entry->sock_info, req);
-              ats_free(req);
-              if (ret == TS_ERR_NET_WRITE || ret == TS_ERR_NET_EOF) {
-                Debug("ts_main", "[ts_ctrl_main] ERROR:handle_record_set\n");
-                remove_client(client_entry, accepted_con);
-                con_entry = ink_hash_table_iterator_next(accepted_con, &con_state);
-                continue;
-              }
-
               break;
 
             case FILE_READ:
               ret = handle_file_read(client_entry->sock_info, req);
-              ats_free(req);
-              if (ret == TS_ERR_NET_WRITE || ret == TS_ERR_NET_EOF) {
-                Debug("ts_main", "[ts_ctrl_main] ERROR:handle_file_read\n");
-                remove_client(client_entry, accepted_con);
-                con_entry = ink_hash_table_iterator_next(accepted_con, &con_state);
-                continue;
-              }
-
               break;
 
             case FILE_WRITE:
               ret = handle_file_write(client_entry->sock_info, req);
-              ats_free(req);
-              if (ret == TS_ERR_NET_WRITE || ret == TS_ERR_NET_EOF) {
-                Debug("ts_main", "[ts_ctrl_main] ERROR:handle_file_write\n");
-                remove_client(client_entry, accepted_con);
-                con_entry = ink_hash_table_iterator_next(accepted_con, &con_state);
-                continue;
-              }
-
               break;
 
             case PROXY_STATE_GET:
               ret = handle_proxy_state_get(client_entry->sock_info);
-              ats_free(req);     // free the request allocated by preprocess_msg
-              if (ret == TS_ERR_NET_WRITE || ret == TS_ERR_NET_EOF) {
-                Debug("ts_main", "[ts_ctrl_main] ERROR:handle_proxy_state_get\n");
-                remove_client(client_entry, accepted_con);
-                con_entry = ink_hash_table_iterator_next(accepted_con, &con_state);
-                continue;
-              }
-
               break;
 
             case PROXY_STATE_SET:
               ret = handle_proxy_state_set(client_entry->sock_info, req);
-              ats_free(req);     // free the request allocated by preprocess_msg
-              if (ret == TS_ERR_NET_WRITE || ret == TS_ERR_NET_EOF) {
-                Debug("ts_main", "[ts_ctrl_main] ERROR:handle_proxy_state_set\n");
-                remove_client(client_entry, accepted_con);
-                con_entry = ink_hash_table_iterator_next(accepted_con, &con_state);
-                continue;
-              }
-
               break;
 
             case RECONFIGURE:
               ret = handle_reconfigure(client_entry->sock_info);
-              ats_free(req);     // free the request allocated by preprocess_msg
-              if (ret == TS_ERR_NET_WRITE || ret == TS_ERR_NET_EOF) {
-                Debug("ts_main", "[ts_ctrl_main] ERROR:handle_reconfigure\n");
-                remove_client(client_entry, accepted_con);
-                con_entry = ink_hash_table_iterator_next(accepted_con, &con_state);
-                continue;
-              }
-
               break;
 
             case RESTART:
               ret = handle_restart(client_entry->sock_info, req, false);
-              ats_free(req);     // free the request allocated by preprocess_msg
-              if (ret == TS_ERR_NET_WRITE || ret == TS_ERR_NET_EOF) {
-                Debug("ts_main", "[ts_ctrl_main] ERROR:handle_restart\n");
-                remove_client(client_entry, accepted_con);
-                con_entry = ink_hash_table_iterator_next(accepted_con, &con_state);
-                continue;
-              }
               break;
 
             case BOUNCE:
               ret = handle_restart(client_entry->sock_info, req, true);
-              ats_free(req);     // free the request allocated by preprocess_msg
-              if (ret == TS_ERR_NET_WRITE || ret == TS_ERR_NET_EOF) {
-                Debug("ts_main", "[ts_ctrl_main] ERROR:handle_restart bounce\n");
-                remove_client(client_entry, accepted_con);
-                con_entry = ink_hash_table_iterator_next(accepted_con, &con_state);
-                continue;
-              }
               break;
 
             case STORAGE_DEVICE_CMD_OFFLINE:
               ret = handle_storage_device_cmd_offline(client_entry->sock_info, req);
-              ats_free(req);     // free the request allocated by preprocess_msg
-              if (ret == TS_ERR_NET_WRITE || ret == TS_ERR_NET_EOF) {
-                Debug("ts_main", "[ts_ctrl_main] ERROR:handle_storage_device_cmd_offline\n");
-                remove_client(client_entry, accepted_con);
-                con_entry = ink_hash_table_iterator_next(accepted_con, &con_state);
-                continue;
-              }
               break;
 
             case EVENT_RESOLVE:
               ret = handle_event_resolve(client_entry->sock_info, req);
-              ats_free(req);     // free the request allocated by preprocess_msg
-              if (ret == TS_ERR_NET_WRITE || ret == TS_ERR_NET_EOF) {
-                Debug("ts_main", "[ts_ctrl_main] ERROR:handle_event_resolve\n");
-                remove_client(client_entry, accepted_con);
-                con_entry = ink_hash_table_iterator_next(accepted_con, &con_state);
-                continue;
-              }
               break;
 
             case EVENT_GET_MLT:
               ret = handle_event_get_mlt(client_entry->sock_info);
-              ats_free(req);     // free the request allocated by preprocess_msg
-              if (ret == TS_ERR_NET_WRITE || ret == TS_ERR_NET_EOF) {
-                Debug("ts_main", "[ts_ctrl_main] ERROR:event_get_mlt\n");
-                remove_client(client_entry, accepted_con);
-                con_entry = ink_hash_table_iterator_next(accepted_con, &con_state);
-                continue;
-              }
               break;
 
             case EVENT_ACTIVE:
               ret = handle_event_active(client_entry->sock_info, req);
-              ats_free(req);     // free the request allocated by preprocess_msg
-              if (ret == TS_ERR_NET_WRITE || ret == TS_ERR_NET_EOF) {
-                Debug("ts_main", "[ts_ctrl_main] ERROR:event_active\n");
-                remove_client(client_entry, accepted_con);
-                con_entry = ink_hash_table_iterator_next(accepted_con, &con_state);
-                continue;
-              }
               break;
 
             case SNAPSHOT_TAKE:
             case SNAPSHOT_RESTORE:
             case SNAPSHOT_REMOVE:
               ret = handle_snapshot(client_entry->sock_info, req, op_t);
-              ats_free(req);
-              if (ret == TS_ERR_NET_WRITE || ret == TS_ERR_NET_EOF) {
-                Debug("ts_main", "[ts_ctrl_main] ERROR:handle_snapshot\n");
-                remove_client(client_entry, accepted_con);
-                con_entry = ink_hash_table_iterator_next(accepted_con, &con_state);
-                continue;
-              }
               break;
 
             case SNAPSHOT_GET_MLT:
               ret = handle_snapshot_get_mlt(client_entry->sock_info);
-              ats_free(req);
-              if (ret == TS_ERR_NET_WRITE || ret == TS_ERR_NET_EOF) {
-                Debug("ts_main", "[ts_ctrl_main] ERROR:snapshot_get_mlt\n");
-                remove_client(client_entry, accepted_con);
-                con_entry = ink_hash_table_iterator_next(accepted_con, &con_state);
-                continue;
-              }
               break;
 
             case DIAGS:
-              if (req) {
-                handle_diags(client_entry->sock_info, req);
-                ats_free(req);
-              }
+              ret = handle_diags(client_entry->sock_info, req);
               break;
 
             case STATS_RESET_CLUSTER:
             case STATS_RESET_NODE:
               ret = handle_stats_reset(client_entry->sock_info, req, op_t);
-              ats_free(req);
-              if (ret == TS_ERR_NET_WRITE || ret == TS_ERR_NET_EOF) {
-                Debug("ts_main", "[ts_ctrl_main] ERROR: stats_reset\n");
-                remove_client(client_entry, accepted_con);
-                con_entry = ink_hash_table_iterator_next(accepted_con, &con_state);
-                continue;
-              }
               break;
 
             case UNDEFINED_OP:
@@ -409,6 +294,16 @@ ts_ctrl_main(void *arg)
               break;
 
             }                   // end switch (op_t)
+
+            ats_free(req);
+
+            if (ret == TS_ERR_NET_WRITE || ret == TS_ERR_NET_EOF) {
+              Debug("ts_main", "[ts_ctrl_main] ERROR: sending response for message op %d\n", (int)op_t);
+              remove_client(client_entry, accepted_con);
+              con_entry = ink_hash_table_iterator_next(accepted_con, &con_state);
+              continue;
+            }
+
           }                     // end if(client_entry->sock_info.fd && FD_ISSET(client_entry->sock_info.fd, &selectFDs))
 
           con_entry = ink_hash_table_iterator_next(accepted_con, &con_state);
@@ -487,16 +382,16 @@ handle_record_get(struct SocketInfo sock_info, char *req)
   // create and send reply back to client
   switch (ele->rec_type) {
   case TS_REC_INT:
-    ret = send_record_get_reply(sock_info, ret, &(ele->int_val), sizeof(TSInt), ele->rec_type);
+    ret = send_record_get_reply(sock_info, ret, &(ele->int_val), sizeof(TSInt), ele->rec_type, ele->rec_name);
     break;
   case TS_REC_COUNTER:
-    ret = send_record_get_reply(sock_info, ret, &(ele->counter_val), sizeof(TSCounter), ele->rec_type);
+    ret = send_record_get_reply(sock_info, ret, &(ele->counter_val), sizeof(TSCounter), ele->rec_type, ele->rec_name);
     break;
   case TS_REC_FLOAT:
-    ret = send_record_get_reply(sock_info, ret, &(ele->float_val), sizeof(TSFloat), ele->rec_type);
+    ret = send_record_get_reply(sock_info, ret, &(ele->float_val), sizeof(TSFloat), ele->rec_type, ele->rec_name);
     break;
   case TS_REC_STRING:
-    ret = send_record_get_reply(sock_info, ret, ele->string_val, strlen(ele->string_val), ele->rec_type);
+    ret = send_record_get_reply(sock_info, ret, ele->string_val, strlen(ele->string_val), ele->rec_type, ele->rec_name);
     break;
   default:                     // invalid record type
     ret = send_reply(sock_info, TS_ERR_FAIL);
@@ -513,6 +408,70 @@ handle_record_get(struct SocketInfo sock_info, char *req)
   return ret;
 }
 
+struct record_match_state {
+  TSError     err;
+  SocketInfo  sock;
+  DFA         regex;
+};
+
+static void
+send_record_match(RecT /* rec_type */, void *edata, int /* registered */, const char *name, int data_type, RecData *rec_val)
+{
+  record_match_state *match = (record_match_state *)edata ;
+
+  if (match->err != TS_ERR_OKAY) {
+    return;
+  }
+
+  if (match->regex.match(name) >= 0) {
+    switch (data_type) {
+    case RECD_INT:
+      match->err = send_record_get_reply(match->sock, TS_ERR_OKAY, &(rec_val->rec_int), sizeof(TSInt), TS_REC_INT, name);
+      break;
+    case RECD_COUNTER:
+      match->err = send_record_get_reply(match->sock, TS_ERR_OKAY, &(rec_val->rec_counter), sizeof(TSCounter), TS_REC_COUNTER, name);
+      break;
+    case RECD_STRING:
+      match->err = send_record_get_reply(match->sock, TS_ERR_OKAY, rec_val->rec_string, rec_val->rec_string ? strlen(rec_val->rec_string): 0, TS_REC_STRING, name);
+      break;
+    case RECD_FLOAT:
+      match->err = send_record_get_reply(match->sock, TS_ERR_OKAY, &(rec_val->rec_float), sizeof(TSFloat), TS_REC_FLOAT, name);
+      break;
+    default:
+      break; // skip it
+    }
+  }
+}
+
+TSError
+handle_record_match(struct SocketInfo sock_info, char *req)
+{
+  TSError ret;
+  record_match_state match;
+
+  // parse msg - don't really need since the request itself is the regex itself
+  if (!req) {
+    ret = send_reply(sock_info, TS_ERR_FAIL);
+    return ret;
+  }
+
+  if (match.regex.compile(req, RE_CASE_INSENSITIVE) != 0) {
+    ret = send_reply(sock_info, TS_ERR_FAIL);
+    return ret;
+  }
+
+  match.err = TS_ERR_OKAY;
+  match.sock = sock_info;
+
+  RecDumpRecords(RECT_NULL, send_record_match, &match);
+
+  // If successful, send a list terminator.
+  if (match.err == TS_ERR_OKAY) {
+    return send_record_get_reply(sock_info, TS_ERR_OKAY, NULL, 0, TS_REC_UNDEFINED, NULL);
+  }
+
+  return match.err;
+}
 
 /**************************************************************************
  * handle_record_set
@@ -957,7 +916,7 @@ handle_snapshot_get_mlt(struct SocketInfo sock_info)
  *        req - the diag message (already formatted with arguments)
  * output: TS_ERR_xx
  *************************************************************************/
-void
+TSError
 handle_diags(struct SocketInfo /* sock_info ATS_UNUSED */, char *req)
 {
   TSError ret;
@@ -1008,12 +967,12 @@ handle_diags(struct SocketInfo /* sock_info ATS_UNUSED */, char *req)
   if (diags_init) {
     diags->print("TSMgmtAPI", DTA(level), "%s", diag_msg);
     ats_free(diag_msg);
-    return;
+    return TS_ERR_OKAY;
   }
 
 Lerror:
   ats_free(diag_msg);
-  return;
+  return TS_ERR_FAIL;
 }
 
 /**************************************************************************

http://git-wip-us.apache.org/repos/asf/trafficserver/blob/0389be39/mgmt/api/TSControlMain.h
----------------------------------------------------------------------
diff --git a/mgmt/api/TSControlMain.h b/mgmt/api/TSControlMain.h
index 397b8bb..b53603e 100644
--- a/mgmt/api/TSControlMain.h
+++ b/mgmt/api/TSControlMain.h
@@ -49,6 +49,7 @@ void delete_client(ClientT * client);
 void *ts_ctrl_main(void *arg);
 
 TSError handle_record_get(struct SocketInfo sock_info, char *req);
+TSError handle_record_match(struct SocketInfo sock_info, char *req);
 TSError handle_record_set(struct SocketInfo sock_info, char *req);
 
 TSError handle_file_read(struct SocketInfo sock_info, char *req);
@@ -67,7 +68,7 @@ TSError handle_event_active(struct SocketInfo sock_info, char *req);
 TSError handle_snapshot(struct SocketInfo sock_info, char *req, OpType op);
 TSError handle_snapshot_get_mlt(struct SocketInfo sock_info);
 
-void handle_diags(struct SocketInfo sock_info, char *req);
+TSError handle_diags(struct SocketInfo sock_info, char *req);
 
 TSError handle_stats_reset(struct SocketInfo sock_info, char *req, OpType op);
 

http://git-wip-us.apache.org/repos/asf/trafficserver/blob/0389be39/mgmt/api/include/mgmtapi.h
----------------------------------------------------------------------
diff --git a/mgmt/api/include/mgmtapi.h b/mgmt/api/include/mgmtapi.h
index 7b88d92..786db7f 100644
--- a/mgmt/api/include/mgmtapi.h
+++ b/mgmt/api/include/mgmtapi.h
@@ -1174,6 +1174,12 @@ extern "C"
  */
   tsapi TSError TSRecordGetMlt(TSStringList rec_names, TSList rec_vals);
 
+/* TSRecordGetMatchMlt: gets a set of records
+ * Input:  rec_regex - regular expression to match against record names
+ * Output: TSError, TSList of TSRecordEle
+ */
+  tsapi TSError TSRecordGetMatchMlt(const char *rec_regex, TSList list);
+
 /* TSRecordSet*: sets a record w/ a known type
  * Input:  rec_name     - the name of the record (proxy.config.record_name)
  *         *_val        - the value to set the record to