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
