You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@trafficserver.apache.org by jp...@apache.org on 2015/08/28 06:00:00 UTC
[2/3] trafficserver git commit: TS-2861: add traffic_ctl config diff
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 <jp...@apache.org>
Authored: Tue Aug 4 16:57:53 2015 -0700
Committer: James Peach <jp...@apache.org>
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;