TS-2861: add traffic_ctl config diff Add a traffic_ctl option to show which options have been changed from the defaults.
Project: http://git-wip-us.apache.org/repos/asf/trafficserver/repo Commit: http://git-wip-us.apache.org/repos/asf/trafficserver/commit/2c19cd2b Tree: http://git-wip-us.apache.org/repos/asf/trafficserver/tree/2c19cd2b Diff: http://git-wip-us.apache.org/repos/asf/trafficserver/diff/2c19cd2b Branch: refs/heads/master Commit: 2c19cd2b70b42b283811a042ab0126436c4670d2 Parents: 244b78e Author: James Peach <[email protected]> Authored: Tue Aug 4 16:57:53 2015 -0700 Committer: James Peach <[email protected]> Committed: Thu Aug 27 20:53:54 2015 -0700 ---------------------------------------------------------------------- cmd/traffic_ctl/config.cc | 101 +++++++++++++++ cmd/traffic_ctl/traffic_ctl.h | 43 ++----- doc/reference/commands/traffic_ctl.en.rst | 7 ++ lib/records/I_RecCore.h | 2 +- lib/records/RecCore.cc | 17 ++- mgmt/api/CoreAPI.cc | 6 + mgmt/api/CoreAPI.h | 1 + mgmt/api/CoreAPIRemote.cc | 165 ++++++++++++++++--------- mgmt/api/INKMgmtAPI.cc | 28 +++++ mgmt/api/NetworkMessage.h | 4 + mgmt/api/TSControlMain.cc | 139 +++++++++++++-------- mgmt/api/include/mgmtapi.h | 6 + 12 files changed, 372 insertions(+), 147 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/trafficserver/blob/2c19cd2b/cmd/traffic_ctl/config.cc ---------------------------------------------------------------------- diff --git a/cmd/traffic_ctl/config.cc b/cmd/traffic_ctl/config.cc index 44b6e82..61e07fe 100644 --- a/cmd/traffic_ctl/config.cc +++ b/cmd/traffic_ctl/config.cc @@ -26,6 +26,30 @@ #include <I_RecDefs.h> #include <P_RecUtils.h> +struct RecordDescriptionPolicy { + typedef TSConfigRecordDescription *entry_type; + + static void + free(entry_type e) + { + TSConfigRecordDescriptionDestroy(e); + } + + static entry_type + cast(void *ptr) + { + return (entry_type)ptr; + } +}; + +struct CtrlMgmtRecordDescriptionList : CtrlMgmtList<RecordDescriptionPolicy> { + TSMgmtError + match(const char *regex) + { + return TSConfigRecordDescribeMatchMlt(regex, 0u /* flags */, this->list); + } +}; + // Record data type names, indexed by TSRecordT. static const char * rec_typeof(int rec_type) @@ -366,11 +390,88 @@ config_status(unsigned argc, const char **argv) return CTRL_EX_OK; } +static int +config_diff(unsigned argc, const char **argv) +{ + int recfmt = 0; + const ArgumentDescription opts[] = { + {"records", '-', "Emit output in records.config format", "F", &recfmt, NULL, NULL}, + }; + + if (!CtrlProcessArguments(argc, argv, opts, countof(opts)) || n_file_arguments != 0) { + return CtrlCommandUsage("config diff [OPTIONS]"); + } + + TSMgmtError error; + CtrlMgmtRecordDescriptionList descriptions; + + error = descriptions.match(".*"); + if (error != TS_ERR_OKAY) { + CtrlMgmtError(error, "failed to fetch record metadata"); + return CTRL_EX_ERROR; + } + + while (!descriptions.empty()) { + TSConfigRecordDescription *desc; + bool changed = false; + + desc = descriptions.next(); + + switch (desc->rec_type) { + case TS_REC_INT: + changed = (desc->rec_value.int_val != desc->rec_default.int_val); + break; + case TS_REC_COUNTER: + changed = (desc->rec_value.counter_val != desc->rec_default.counter_val); + break; + case TS_REC_FLOAT: + changed = (desc->rec_value.float_val != desc->rec_default.float_val); + break; + case TS_REC_STRING: + changed = (strcmp(desc->rec_value.string_val, desc->rec_default.string_val) != 0); + break; + default: + break; + } + + if (changed) { + CtrlMgmtRecordValue current(desc->rec_type, desc->rec_value); + CtrlMgmtRecordValue deflt(desc->rec_type, desc->rec_default); + + if (recfmt) { + const char *label; + + switch (desc->rec_class) { + case RECT_CONFIG: + label = "CONFIG "; + break; + case RECT_LOCAL: + label = "LOCAL "; + break; + default: + label = ""; + } + + printf("%s%s %s %s # default: %s\n", label, desc->rec_name, rec_typeof(desc->rec_type), current.c_str(), deflt.c_str()); + } else { + printf("%s has changed\n", desc->rec_name); + printf("\t%-16s: %s\n", "Current Value", current.c_str()); + printf("\t%-16s: %s\n", "Default Value", deflt.c_str()); + } + } + + TSConfigRecordDescriptionDestroy(desc); + } + + return CTRL_EX_OK; +} + int subcommand_config(unsigned argc, const char **argv) { const subcommand commands[] = { {config_describe, "describe", "Show detailed information about configuration values"}, + {config_diff, "diff", "Show non-default configuration values"}, {config_get, "get", "Get one or more configuration values"}, {config_match, "match", "Get configuration matching a regular expression"}, {config_reload, "reload", "Request a configuration reload"}, http://git-wip-us.apache.org/repos/asf/trafficserver/blob/2c19cd2b/cmd/traffic_ctl/traffic_ctl.h ---------------------------------------------------------------------- diff --git a/cmd/traffic_ctl/traffic_ctl.h b/cmd/traffic_ctl/traffic_ctl.h index bc0847a..751d266 100644 --- a/cmd/traffic_ctl/traffic_ctl.h +++ b/cmd/traffic_ctl/traffic_ctl.h @@ -110,43 +110,20 @@ private: } fmt; }; -struct CtrlMgmtRecordList { - CtrlMgmtRecordList() : list(TSListCreate()) {} +struct RecordListPolicy { + typedef TSRecordEle *entry_type; - ~CtrlMgmtRecordList() + static void + free(entry_type e) { - this->clear(); - TSListDestroy(this->list); - } - - bool - empty() const - { - return TSListIsEmpty(this->list); - } - - void - clear() const - { - while (!this->empty()) { - TSRecordEleDestroy((TSRecordEle *)TSListDequeue(this->list)); - } + TSRecordEleDestroy(e); } - // Return (ownership of) the next list entry. - TSRecordEle * - next() + static entry_type + cast(void *ptr) { - return (TSRecordEle *)TSListDequeue(this->list); + return (entry_type)ptr; } - - TSMgmtError match(const char *); - -private: - CtrlMgmtRecordList(const CtrlMgmtRecordList &); // disabled - CtrlMgmtRecordList &operator=(const CtrlMgmtRecordList &); // disabled - - TSList list; }; template <typename T> struct CtrlMgmtList { @@ -186,6 +163,10 @@ private: CtrlMgmtList &operator=(const CtrlMgmtList &); // disabled }; +struct CtrlMgmtRecordList : CtrlMgmtList<RecordListPolicy> { + TSMgmtError match(const char *); +}; + struct CtrlCommandLine { CtrlCommandLine() { this->args.push_back(NULL); } http://git-wip-us.apache.org/repos/asf/trafficserver/blob/2c19cd2b/doc/reference/commands/traffic_ctl.en.rst ---------------------------------------------------------------------- diff --git a/doc/reference/commands/traffic_ctl.en.rst b/doc/reference/commands/traffic_ctl.en.rst index 86df74a..7393e6a 100644 --- a/doc/reference/commands/traffic_ctl.en.rst +++ b/doc/reference/commands/traffic_ctl.en.rst @@ -104,6 +104,13 @@ traffic_ctl config the record class and syntax checking expression. .. program:: traffic_ctl config +.. option:: diff [--records] + + Display configuration records that have non-default values. The + *--records* flag has the same behavior as :option:`traffic_ctl + config get --records`. + +.. program:: traffic_ctl config .. option:: get [--records] RECORD [RECORD...] Display the current value of a configuration record. http://git-wip-us.apache.org/repos/asf/trafficserver/blob/2c19cd2b/lib/records/I_RecCore.h ---------------------------------------------------------------------- diff --git a/lib/records/I_RecCore.h b/lib/records/I_RecCore.h index 1d8ab52..eb4eb4b 100644 --- a/lib/records/I_RecCore.h +++ b/lib/records/I_RecCore.h @@ -169,7 +169,7 @@ int RecGetRecordBool(const char *name, RecBool *rec_byte, bool lock = true); typedef void (*RecLookupCallback)(const RecRecord *, void *); int RecLookupRecord(const char *name, RecLookupCallback callback, void *data, bool lock = true); -int RecLookupMatchingRecords(const char *match, RecLookupCallback callback, void *data, bool lock = true); +int RecLookupMatchingRecords(unsigned rec_type, const char *match, RecLookupCallback callback, void *data, bool lock = true); int RecGetRecordType(const char *name, RecT *rec_type, bool lock = true); int RecGetRecordDataType(const char *name, RecDataT *data_type, bool lock = true); http://git-wip-us.apache.org/repos/asf/trafficserver/blob/2c19cd2b/lib/records/RecCore.cc ---------------------------------------------------------------------- diff --git a/lib/records/RecCore.cc b/lib/records/RecCore.cc index 041a218..d35230d 100644 --- a/lib/records/RecCore.cc +++ b/lib/records/RecCore.cc @@ -455,7 +455,7 @@ RecLookupRecord(const char *name, void (*callback)(const RecRecord *, void *), v } int -RecLookupMatchingRecords(const char *match, void (*callback)(const RecRecord *, void *), void *data, bool lock) +RecLookupMatchingRecords(unsigned rec_type, const char *match, void (*callback)(const RecRecord *, void *), void *data, bool lock) { int num_records; DFA regex; @@ -467,11 +467,18 @@ RecLookupMatchingRecords(const char *match, void (*callback)(const RecRecord *, num_records = g_num_records; for (int i = 0; i < num_records; i++) { RecRecord *r = &(g_records[i]); - if (regex.match(r->name) >= 0) { - rec_mutex_acquire(&(r->lock)); - callback(r, data); - rec_mutex_release(&(r->lock)); + + if ((r->rec_type & rec_type) == 0) { + continue; + } + + if (regex.match(r->name) < 0) { + continue; } + + rec_mutex_acquire(&(r->lock)); + callback(r, data); + rec_mutex_release(&(r->lock)); } return REC_ERR_OKAY; http://git-wip-us.apache.org/repos/asf/trafficserver/blob/2c19cd2b/mgmt/api/CoreAPI.cc ---------------------------------------------------------------------- diff --git a/mgmt/api/CoreAPI.cc b/mgmt/api/CoreAPI.cc index b14320b..972de27 100644 --- a/mgmt/api/CoreAPI.cc +++ b/mgmt/api/CoreAPI.cc @@ -565,6 +565,12 @@ MgmtConfigRecordDescribe(const char * /* rec_name */, unsigned /* flags */, TSCo return TS_ERR_NOT_SUPPORTED; } +TSMgmtError +MgmtConfigRecordDescribeMatching(const char *, unsigned, TSList) +{ + return TS_ERR_NOT_SUPPORTED; +} + /*------------------------------------------------------------------------- * reads the RecordsConfig info to determine which type of action is needed * when the record rec_name is changed; if the rec_name is invalid, http://git-wip-us.apache.org/repos/asf/trafficserver/blob/2c19cd2b/mgmt/api/CoreAPI.h ---------------------------------------------------------------------- diff --git a/mgmt/api/CoreAPI.h b/mgmt/api/CoreAPI.h index c803299..c6ed7e5 100644 --- a/mgmt/api/CoreAPI.h +++ b/mgmt/api/CoreAPI.h @@ -66,6 +66,7 @@ TSMgmtError MgmtRecordSetString(const char *rec_name, const char *string_val, TS TSMgmtError MgmtRecordGetMatching(const char *regex, TSList rec_vals); TSMgmtError MgmtConfigRecordDescribe(const char *rec_name, unsigned flags, TSConfigRecordDescription *val); +TSMgmtError MgmtConfigRecordDescribeMatching(const char *regex, unsigned flags, TSList rec_vals); /*************************************************************************** * File Operations http://git-wip-us.apache.org/repos/asf/trafficserver/blob/2c19cd2b/mgmt/api/CoreAPIRemote.cc ---------------------------------------------------------------------- diff --git a/mgmt/api/CoreAPIRemote.cc b/mgmt/api/CoreAPIRemote.cc index 4ce8cae..8622945 100644 --- a/mgmt/api/CoreAPIRemote.cc +++ b/mgmt/api/CoreAPIRemote.cc @@ -534,6 +534,72 @@ done: return ret; } +static TSMgmtError +mgmt_record_describe_reply(TSConfigRecordDescription *val) +{ + TSMgmtError ret; + MgmtMarshallData reply = {NULL, 0}; + + ret = recv_mgmt_message(main_socket_fd, reply); + if (ret != TS_ERR_OKAY) { + return ret; + } + + MgmtMarshallInt err; + MgmtMarshallString name = NULL; + MgmtMarshallString expr = NULL; + MgmtMarshallData value = {NULL, 0}; + MgmtMarshallData deflt = {NULL, 0}; + + MgmtMarshallInt rtype; + MgmtMarshallInt rclass; + MgmtMarshallInt version; + MgmtMarshallInt rsb; + MgmtMarshallInt order; + MgmtMarshallInt access; + MgmtMarshallInt update; + MgmtMarshallInt updatetype; + MgmtMarshallInt checktype; + MgmtMarshallInt source; + + ret = recv_mgmt_response(reply.ptr, reply.len, RECORD_DESCRIBE_CONFIG, &err, &name, &value, &deflt, &rtype, &rclass, &version, + &rsb, &order, &access, &update, &updatetype, &checktype, &source, &expr); + + ats_free(reply.ptr); + + if (ret != TS_ERR_OKAY) { + goto done; + } + + if (err != TS_ERR_OKAY) { + ret = (TSMgmtError)err; + goto done; + } + + // Everything is cool, populate the description ... + val->rec_name = ats_strdup(name); + val->rec_checkexpr = ats_strdup(expr); + val->rec_type = (TSRecordT)rtype; + val->rec_class = rclass; + val->rec_version = version; + val->rec_rsb = rsb; + val->rec_order = order; + val->rec_access = access; + val->rec_updatetype = updatetype; + val->rec_checktype = checktype; + val->rec_source = source; + + mgmt_record_convert_value(val->rec_type, value, val->rec_value); + mgmt_record_convert_value(val->rec_type, deflt, val->rec_default); + +done: + ats_free(name); + ats_free(expr); + ats_free(value.ptr); + ats_free(deflt.ptr); + return ret; +} + // note that the record value is being sent as chunk of memory, regardless of // record type; it's not being converted to a string!! TSMgmtError @@ -553,84 +619,69 @@ MgmtRecordGet(const char *rec_name, TSRecordEle *rec_ele) } TSMgmtError -MgmtConfigRecordDescribe(const char *rec_name, unsigned options, TSConfigRecordDescription *val) +MgmtConfigRecordDescribeMatching(const char *rec_name, unsigned options, TSList rec_vals) { TSMgmtError ret; MgmtMarshallInt optype = RECORD_DESCRIBE_CONFIG; - MgmtMarshallInt flags = options; + MgmtMarshallInt flags = options | RECORD_DESCRIBE_FLAGS_MATCH; MgmtMarshallString record = const_cast<MgmtMarshallString>(rec_name); - MgmtMarshallData reply = {NULL, 0}; - // create and send request ret = MGMTAPI_SEND_MESSAGE(main_socket_fd, RECORD_DESCRIBE_CONFIG, &optype, &record, &flags); if (ret != TS_ERR_OKAY) { return ret; } - ret = recv_mgmt_message(main_socket_fd, reply); - if (ret != TS_ERR_OKAY) { - return ret; - } else { - MgmtMarshallInt err; - MgmtMarshallString name = NULL; - MgmtMarshallString expr = NULL; - MgmtMarshallData value = {NULL, 0}; - MgmtMarshallData deflt = {NULL, 0}; - - MgmtMarshallInt rtype; - MgmtMarshallInt rclass; - MgmtMarshallInt version; - MgmtMarshallInt rsb; - MgmtMarshallInt order; - MgmtMarshallInt access; - MgmtMarshallInt update; - MgmtMarshallInt updatetype; - MgmtMarshallInt checktype; - MgmtMarshallInt source; - - ret = recv_mgmt_response(reply.ptr, reply.len, RECORD_DESCRIBE_CONFIG, &err, &name, &value, &deflt, &rtype, &rclass, &version, - &rsb, &order, &access, &update, &updatetype, &checktype, &source, &expr); - - ats_free(reply.ptr); + for (;;) { + TSConfigRecordDescription *val; + + val = TSConfigRecordDescriptionCreate(); + // parse the reply to get record value and type + ret = mgmt_record_describe_reply(val); if (ret != TS_ERR_OKAY) { - goto done; + TSConfigRecordDescriptionDestroy(val); + goto fail; } - if (err != TS_ERR_OKAY) { - ret = (TSMgmtError)err; - goto done; + // A NULL record ends the list. + if (val->rec_type == TS_REC_UNDEFINED) { + TSConfigRecordDescriptionDestroy(val); + break; } - // Everything is cool, populate the description ... - val->rec_name = ats_strdup(name); - val->rec_checkexpr = ats_strdup(expr); - val->rec_type = (TSRecordT)rtype; - val->rec_class = rclass; - val->rec_version = version; - val->rec_rsb = rsb; - val->rec_order = order; - val->rec_access = access; - val->rec_updatetype = updatetype; - val->rec_checktype = checktype; - val->rec_source = source; - - mgmt_record_convert_value(val->rec_type, value, val->rec_value); - mgmt_record_convert_value(val->rec_type, deflt, val->rec_default); - - done: - ats_free(name); - ats_free(expr); - ats_free(value.ptr); - ats_free(deflt.ptr); - return ret; + enqueue((LLQ *)rec_vals, val); + } + + return TS_ERR_OKAY; + +fail: + while (!queue_is_empty((LLQ *)rec_vals)) { + TSConfigRecordDescription *val = (TSConfigRecordDescription *)dequeue((LLQ *)rec_vals); + TSConfigRecordDescriptionDestroy(val); } return ret; } TSMgmtError +MgmtConfigRecordDescribe(const char *rec_name, unsigned options, TSConfigRecordDescription *val) +{ + TSMgmtError ret; + MgmtMarshallInt optype = RECORD_DESCRIBE_CONFIG; + MgmtMarshallInt flags = options & ~RECORD_DESCRIBE_FLAGS_MATCH; + MgmtMarshallString record = const_cast<MgmtMarshallString>(rec_name); + + // create and send request + ret = MGMTAPI_SEND_MESSAGE(main_socket_fd, RECORD_DESCRIBE_CONFIG, &optype, &record, &flags); + if (ret != TS_ERR_OKAY) { + return ret; + } + + return mgmt_record_describe_reply(val); +} + +TSMgmtError MgmtRecordGetMatching(const char *regex, TSList rec_vals) { TSMgmtError ret; @@ -670,8 +721,8 @@ MgmtRecordGetMatching(const char *regex, TSList rec_vals) return TS_ERR_OKAY; fail: - - for (rec_ele = (TSRecordEle *)dequeue((LLQ *)rec_vals); rec_ele; rec_ele = (TSRecordEle *)dequeue((LLQ *)rec_vals)) { + while (!queue_is_empty((LLQ *)rec_vals)) { + rec_ele = (TSRecordEle *)dequeue((LLQ *)rec_vals); TSRecordEleDestroy(rec_ele); } http://git-wip-us.apache.org/repos/asf/trafficserver/blob/2c19cd2b/mgmt/api/INKMgmtAPI.cc ---------------------------------------------------------------------- diff --git a/mgmt/api/INKMgmtAPI.cc b/mgmt/api/INKMgmtAPI.cc index ad78811..f989b71 100644 --- a/mgmt/api/INKMgmtAPI.cc +++ b/mgmt/api/INKMgmtAPI.cc @@ -2358,6 +2358,24 @@ TSIsValid(TSCfgEle *ele) return (ele_obj->isValid()); } +TSConfigRecordDescription * +TSConfigRecordDescriptionCreate(void) +{ + TSConfigRecordDescription *val = (TSConfigRecordDescription *)ats_malloc(sizeof(TSConfigRecordDescription)); + + ink_zero(*val); + val->rec_type = TS_REC_UNDEFINED; + + return val; +} + +void +TSConfigRecordDescriptionDestroy(TSConfigRecordDescription *val) +{ + TSConfigRecordDescriptionFree(val); + ats_free(val); +} + void TSConfigRecordDescriptionFree(TSConfigRecordDescription *val) { @@ -2384,3 +2402,13 @@ TSConfigRecordDescribe(const char *rec_name, unsigned flags, TSConfigRecordDescr TSConfigRecordDescriptionFree(val); return MgmtConfigRecordDescribe(rec_name, flags, val); } + +TSMgmtError +TSConfigRecordDescribeMatchMlt(const char *rec_regex, unsigned flags, TSList rec_vals) +{ + if (!rec_regex || !rec_vals) { + return TS_ERR_PARAMS; + } + + return MgmtConfigRecordDescribeMatching(rec_regex, flags, rec_vals); +} http://git-wip-us.apache.org/repos/asf/trafficserver/blob/2c19cd2b/mgmt/api/NetworkMessage.h ---------------------------------------------------------------------- diff --git a/mgmt/api/NetworkMessage.h b/mgmt/api/NetworkMessage.h index 1aea548..88ef72d 100644 --- a/mgmt/api/NetworkMessage.h +++ b/mgmt/api/NetworkMessage.h @@ -65,6 +65,10 @@ typedef enum { #define MGMT_OPERATION_TYPE_MAX (UNDEFINED_OP) +enum { + RECORD_DESCRIBE_FLAGS_MATCH = 0x0001, +}; + struct mgmt_message_sender { virtual TSMgmtError send(void *msg, size_t msglen) const = 0; virtual ~mgmt_message_sender(){}; http://git-wip-us.apache.org/repos/asf/trafficserver/blob/2c19cd2b/mgmt/api/TSControlMain.cc ---------------------------------------------------------------------- diff --git a/mgmt/api/TSControlMain.cc b/mgmt/api/TSControlMain.cc index 1f22a52..5c711cf 100644 --- a/mgmt/api/TSControlMain.cc +++ b/mgmt/api/TSControlMain.cc @@ -441,7 +441,7 @@ handle_record_match(int fd, void *req, size_t reqlen) match.err = TS_ERR_OKAY; match.fd = fd; - if (RecLookupMatchingRecords(name, send_record_match, &match) != REC_ERR_OKAY) { + if (RecLookupMatchingRecords(RECT_ALL, name, send_record_match, &match) != REC_ERR_OKAY) { ats_free(name); return TS_ERR_FAIL; } @@ -1017,78 +1017,96 @@ handle_server_backtrace(int fd, void *req, size_t reqlen) } static void -send_record_describe(const RecRecord *rec, void *ptr) +send_record_describe(const RecRecord *rec, void *edata) { - MgmtMarshallString rec_name = const_cast<char *>(rec->name); + MgmtMarshallString rec_name = NULL; MgmtMarshallData rec_value = {NULL, 0}; MgmtMarshallData rec_default = {NULL, 0}; - MgmtMarshallInt rec_type = rec->data_type; - MgmtMarshallInt rec_class = rec->rec_type; - MgmtMarshallInt rec_version = rec->version; - MgmtMarshallInt rec_rsb = rec->rsb_id; - MgmtMarshallInt rec_order = rec->order; - MgmtMarshallInt rec_access = rec->config_meta.access_type; - MgmtMarshallInt rec_update = rec->config_meta.update_required; - MgmtMarshallInt rec_updatetype = rec->config_meta.update_type; - MgmtMarshallInt rec_checktype = rec->config_meta.check_type; - MgmtMarshallInt rec_source = rec->config_meta.source; - MgmtMarshallString rec_checkexpr = rec->config_meta.check_expr; + MgmtMarshallInt rec_type = TS_REC_UNDEFINED; + MgmtMarshallInt rec_class = RECT_NULL; + MgmtMarshallInt rec_version = 0; + MgmtMarshallInt rec_rsb = 0; + MgmtMarshallInt rec_order = 0; + MgmtMarshallInt rec_access = RECA_NULL; + MgmtMarshallInt rec_update = RECU_NULL; + MgmtMarshallInt rec_updatetype = 0; + MgmtMarshallInt rec_checktype = RECC_NULL; + MgmtMarshallInt rec_source = REC_SOURCE_NULL; + MgmtMarshallString rec_checkexpr = NULL; + + TSMgmtError err = TS_ERR_OKAY; - MgmtMarshallInt err = TS_ERR_OKAY; - - int *fderr = (int *)ptr; + record_match_state *match = (record_match_state *)edata; - // We only describe config variables (for now). - if (!REC_TYPE_IS_CONFIG(rec->rec_type)) { - *fderr = TS_ERR_PARAMS; + if (match->err != TS_ERR_OKAY) { return; } - switch (rec_type) { - case RECD_INT: - rec_type = TS_REC_INT; - break; - case RECD_FLOAT: - rec_type = TS_REC_FLOAT; - break; - case RECD_STRING: - rec_type = TS_REC_STRING; - break; - case RECD_COUNTER: - rec_type = TS_REC_COUNTER; - break; - default: - rec_type = TS_REC_UNDEFINED; - } + if (rec) { + // We only describe config variables (for now). + if (!REC_TYPE_IS_CONFIG(rec->rec_type)) { + match->err = TS_ERR_PARAMS; + return; + } - err = marshall_rec_data(rec->data_type, rec->data, rec_value); - if (err != TS_ERR_OKAY) { - goto done; - } + rec_name = const_cast<char *>(rec->name); + rec_type = rec->data_type; + rec_class = rec->rec_type; + rec_version = rec->version; + rec_rsb = rec->rsb_id; + rec_order = rec->order; + rec_access = rec->config_meta.access_type; + rec_update = rec->config_meta.update_required; + rec_updatetype = rec->config_meta.update_type; + rec_checktype = rec->config_meta.check_type; + rec_source = rec->config_meta.source; + rec_checkexpr = rec->config_meta.check_expr; + + switch (rec_type) { + case RECD_INT: + rec_type = TS_REC_INT; + break; + case RECD_FLOAT: + rec_type = TS_REC_FLOAT; + break; + case RECD_STRING: + rec_type = TS_REC_STRING; + break; + case RECD_COUNTER: + rec_type = TS_REC_COUNTER; + break; + default: + rec_type = TS_REC_UNDEFINED; + } - err = marshall_rec_data(rec->data_type, rec->data_default, rec_default); - if (err != TS_ERR_OKAY) { - goto done; + err = marshall_rec_data(rec->data_type, rec->data, rec_value); + if (err != TS_ERR_OKAY) { + goto done; + } + + err = marshall_rec_data(rec->data_type, rec->data_default, rec_default); + if (err != TS_ERR_OKAY) { + goto done; + } } - err = send_mgmt_response(*fderr, RECORD_DESCRIBE_CONFIG, &err, &rec_name, &rec_value, &rec_default, &rec_type, &rec_class, + err = send_mgmt_response(match->fd, RECORD_DESCRIBE_CONFIG, &err, &rec_name, &rec_value, &rec_default, &rec_type, &rec_class, &rec_version, &rec_rsb, &rec_order, &rec_access, &rec_update, &rec_updatetype, &rec_checktype, &rec_source, &rec_checkexpr); done: - *fderr = err; + match->err = err; } static TSMgmtError handle_record_describe(int fd, void *req, size_t reqlen) { TSMgmtError ret; + record_match_state match; MgmtMarshallInt optype; MgmtMarshallInt options; MgmtMarshallString name; - int fderr = fd; // [in,out] variable for the fd and error - ret = recv_mgmt_request(req, reqlen, RECORD_DESCRIBE_CONFIG, &optype, &name, &options); if (ret != TS_ERR_OKAY) { return ret; @@ -1099,19 +1117,34 @@ handle_record_describe(int fd, void *req, size_t reqlen) goto done; } - if (RecLookupRecord(name, send_record_describe, &fderr) != REC_ERR_OKAY) { - ret = TS_ERR_PARAMS; - goto done; + match.err = TS_ERR_OKAY; + match.fd = fd; + + if (options & RECORD_DESCRIBE_FLAGS_MATCH) { + if (RecLookupMatchingRecords(RECT_CONFIG | RECT_LOCAL, name, send_record_describe, &match) != REC_ERR_OKAY) { + ret = TS_ERR_PARAMS; + goto done; + } + + // If successful, send a list terminator. + if (match.err == TS_ERR_OKAY) { + send_record_describe(NULL, &match); + } + + } else { + if (RecLookupRecord(name, send_record_describe, &match) != REC_ERR_OKAY) { + ret = TS_ERR_PARAMS; + goto done; + } } - // If the lookup succeeded, the final error is in "fderr". if (ret == TS_ERR_OKAY) { - ret = (TSMgmtError)fderr; + ret = match.err; } done: ats_free(name); - return ret; + return match.err; } struct control_message_handler { http://git-wip-us.apache.org/repos/asf/trafficserver/blob/2c19cd2b/mgmt/api/include/mgmtapi.h ---------------------------------------------------------------------- diff --git a/mgmt/api/include/mgmtapi.h b/mgmt/api/include/mgmtapi.h index 65ff981..be20600 100644 --- a/mgmt/api/include/mgmtapi.h +++ b/mgmt/api/include/mgmtapi.h @@ -425,6 +425,11 @@ typedef struct { /* Free (the contents of) a TSConfigRecordDescription */ tsapi void TSConfigRecordDescriptionFree(TSConfigRecordDescription *val); +/* Heap-allocate a TSConfigRecordDescription. */ +tsapi TSConfigRecordDescription *TSConfigRecordDescriptionCreate(void); +/* Free and destroy a heap-allocated TSConfigRecordDescription. */ +tsapi void TSConfigRecordDescriptionDestroy(TSConfigRecordDescription *); + /*--- events --------------------------------------------------------------*/ /* Note: Each event has a format String associated with it from which the @@ -1108,6 +1113,7 @@ tsapi TSMgmtError TSRecordSetString(const char *rec_name, const char *string_val * Output: TSMgmtError */ tsapi TSMgmtError TSConfigRecordDescribe(const char *rec_name, unsigned flags, TSConfigRecordDescription *val); +tsapi TSMgmtError TSConfigRecordDescribeMatchMlt(const char *rec_regex, unsigned flags, TSList list); /* TSRecordSetMlt: sets a set of records * Input: rec_list - list of record names the user wants to set;
