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/03/09 06:03:07 UTC
trafficserver git commit: TS-3408: add a "config describe" command to
traffic_ctl
Repository: trafficserver
Updated Branches:
refs/heads/master c6c910bc0 -> 857766c5c
TS-3408: add a "config describe" command to traffic_ctl
Add a new management API TSConfigRecordDescribe() to publish all
the information that we know about a configuration record. Plumb
this through the messaging layer and expose it in traffic_ctl as
the "config describe" subcommand.
Project: http://git-wip-us.apache.org/repos/asf/trafficserver/repo
Commit: http://git-wip-us.apache.org/repos/asf/trafficserver/commit/857766c5
Tree: http://git-wip-us.apache.org/repos/asf/trafficserver/tree/857766c5
Diff: http://git-wip-us.apache.org/repos/asf/trafficserver/diff/857766c5
Branch: refs/heads/master
Commit: 857766c5caefd2c1b890e34e379cfcd7bbde475d
Parents: c6c910b
Author: James Peach <jp...@apache.org>
Authored: Wed Feb 11 16:27:00 2015 -0800
Committer: James Peach <jp...@apache.org>
Committed: Sun Mar 8 22:02:55 2015 -0700
----------------------------------------------------------------------
CHANGES | 2 +
cmd/traffic_ctl/Makefile.am | 1 +
cmd/traffic_ctl/config.cc | 122 ++++++++++++++++++++++++++--
cmd/traffic_ctl/metric.cc | 4 +-
cmd/traffic_ctl/traffic_ctl.cc | 69 +++++++++++-----
cmd/traffic_ctl/traffic_ctl.h | 26 +++++-
lib/records/I_RecCore.h | 6 +-
lib/records/RecCore.cc | 25 ++++++
mgmt/api/CoreAPI.cc | 6 ++
mgmt/api/CoreAPI.h | 1 +
mgmt/api/CoreAPIRemote.cc | 157 ++++++++++++++++++++++++++----------
mgmt/api/INKMgmtAPI.cc | 42 ++++++----
mgmt/api/NetworkMessage.cc | 18 ++++-
mgmt/api/NetworkMessage.h | 3 +
mgmt/api/TSControlMain.cc | 128 ++++++++++++++++++++++++++++-
mgmt/api/include/mgmtapi.h | 50 ++++++++++--
16 files changed, 559 insertions(+), 101 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/trafficserver/blob/857766c5/CHANGES
----------------------------------------------------------------------
diff --git a/CHANGES b/CHANGES
index 320d0c6..17f59bc 100644
--- a/CHANGES
+++ b/CHANGES
@@ -1,6 +1,8 @@
-*- coding: utf-8 -*-
Changes with Apache Traffic Server 5.3.0
+ *) [TS-3408] Add a "config describe" command to traffic_ctl.
+
*) [TS-3393] Fix records with missing validation expressions.
*) [TS-3424] SSL Failed: decryption failed or bad record mac.
http://git-wip-us.apache.org/repos/asf/trafficserver/blob/857766c5/cmd/traffic_ctl/Makefile.am
----------------------------------------------------------------------
diff --git a/cmd/traffic_ctl/Makefile.am b/cmd/traffic_ctl/Makefile.am
index 51cc05c..d83fd19 100644
--- a/cmd/traffic_ctl/Makefile.am
+++ b/cmd/traffic_ctl/Makefile.am
@@ -21,6 +21,7 @@ AM_CPPFLAGS = \
$(iocore_include_dirs) \
-I$(top_srcdir)/lib \
-I$(top_srcdir)/lib/ts \
+ -I$(top_srcdir)/lib/records \
-I$(top_srcdir)/mgmt/api/include
bin_PROGRAMS = traffic_ctl
http://git-wip-us.apache.org/repos/asf/trafficserver/blob/857766c5/cmd/traffic_ctl/config.cc
----------------------------------------------------------------------
diff --git a/cmd/traffic_ctl/config.cc b/cmd/traffic_ctl/config.cc
index 66e10de..f8b4886 100644
--- a/cmd/traffic_ctl/config.cc
+++ b/cmd/traffic_ctl/config.cc
@@ -23,6 +23,73 @@
#include "traffic_ctl.h"
#include <time.h>
+#include <I_RecDefs.h>
+
+// Record data type names, indexed by TSRecordT.
+static const char *
+rec_typeof(int rec_type) {
+ switch (rec_type) {
+ case TS_REC_INT: return "INT";
+ case TS_REC_COUNTER: return "COUNTER";
+ case TS_REC_FLOAT: return "FLOAT";
+ case TS_REC_STRING: return "STRING";
+ case TS_REC_UNDEFINED: /* fallthru */
+ default: return "UNDEFINED";
+ }
+}
+
+// Record type name, indexed by RecT.
+static const char *
+rec_classof(int rec_class) {
+ switch (rec_class) {
+ case RECT_CONFIG: return "standard config";
+ case RECT_LOCAL: return "local config";
+ case RECT_PROCESS:return "process metric";
+ case RECT_NODE: return "node metric";
+ case RECT_CLUSTER:return "cluster metric";
+ case RECT_PLUGIN: return "plugin metric";
+ default: return "undefined";
+ }
+}
+
+// Record access control, indexed by RecAccessT.
+static const char *
+rec_accessof(int rec_access)
+{
+ switch (rec_access) {
+ case RECA_NO_ACCESS: return "no access";
+ case RECA_READ_ONLY: return "read only";
+ case RECA_NULL: /* fallthru */
+ default: return "default";
+ }
+}
+
+// Record access control, indexed by RecUpdateT.
+static const char *
+rec_updateof(int rec_updatetype)
+{
+ switch (rec_updatetype) {
+ case RECU_DYNAMIC: return "dynamic, no restart";
+ case RECU_RESTART_TS: return "static, restart traffic_server";
+ case RECU_RESTART_TM: return "static, restart traffic_manager";
+ case RECU_RESTART_TC: return "static, full restart";
+ case RECU_NULL: /* fallthru */
+ default: return "unknown";
+ }
+}
+
+// Record check type, indexed by RecCheckT.
+static const char *
+rec_checkof(int rec_checktype)
+{
+ switch (rec_checktype) {
+ case RECC_STR: return "string matching a regular expression";
+ case RECC_INT: return "integer with a specified range";
+ case RECC_IP: return "IP address";
+ case RECC_NULL: /* fallthru */
+ default: return "none";
+ }
+}
static std::string
timestr(time_t tm)
@@ -34,15 +101,13 @@ timestr(time_t tm)
static void
format_record(const CtrlMgmtRecord& record, bool recfmt)
{
- const char * typestr[] = {
- "INT", "COUNTER", "FLOAT", "STRING", "UNDEFINED"
- };
+ CtrlMgmtRecordValue value(record);
if (recfmt) {
// XXX Detect CONFIG or LOCAL ...
- printf("CONFIG %s %s %s\n", record.name(), typestr[record.type()], record.c_str());
+ printf("CONFIG %s %s %s\n", record.name(), rec_typeof(record.type()), value.c_str());
} else {
- printf("%s: %s\n", record.name(), record.c_str());
+ printf("%s: %s\n", record.name(), value.c_str());
}
}
@@ -75,6 +140,49 @@ config_get(unsigned argc, const char ** argv)
}
static int
+config_describe(unsigned argc, const char ** argv)
+{
+ if (!CtrlProcessArguments(argc, argv, NULL, 0) || n_file_arguments < 1) {
+ return CtrlCommandUsage("config describe RECORD [RECORD ...]");
+ }
+
+ for (unsigned i = 0; i < n_file_arguments; ++i) {
+ TSConfigRecordDescription desc;
+ TSMgmtError error;
+
+ ink_zero(desc);
+ error = TSConfigRecordDescribe(file_arguments[i], 0 /* flags */, &desc);
+ if (error != TS_ERR_OKAY) {
+ CtrlMgmtError(error, "failed to describe %s", file_arguments[i]);
+ return CTRL_EX_ERROR;
+ }
+
+ printf("%-16s: %s\n", "Name", desc.rec_name);
+ printf("%-16s: %s\n", "Current Value", CtrlMgmtRecordValue(desc.rec_type, desc.rec_value).c_str());
+ printf("%-16s: %s\n", "Default Value", CtrlMgmtRecordValue(desc.rec_type, desc.rec_default).c_str());
+ printf("%-16s: %s\n", "Record Type", rec_classof(desc.rec_class));
+ printf("%-16s: %s\n", "Data Type", rec_typeof(desc.rec_type));
+ printf("%-16s: %s\n", "Access Control ", rec_accessof(desc.rec_access));
+ printf("%-16s: %s\n", "Update Type", rec_updateof(desc.rec_updatetype));
+ printf("%-16s: 0x%" PRIx64 "\n", "Update Status", desc.rec_update);
+
+ if (strlen(desc.rec_checkexpr)) {
+ printf("%-16s: %s, '%s'\n", "Syntax Check", rec_checkof(desc.rec_checktype), desc.rec_checkexpr);
+ } else {
+ printf("%-16s: %s\n", "Syntax Check", rec_checkof(desc.rec_checktype));
+ }
+
+ printf("%-16s: %" PRId64 "\n", "Version", desc.rec_version);
+ printf("%-16s: %" PRId64 "\n", "Order", desc.rec_order);
+ printf("%-16s: %" PRId64 "\n", "Raw Stat Block", desc.rec_rsb);
+
+ TSConfigRecordDescriptionFree(&desc);
+ }
+
+ return CTRL_EX_OK;
+}
+
+static int
config_set(unsigned argc, const char ** argv)
{
TSMgmtError error;
@@ -181,7 +289,7 @@ config_status(unsigned argc, const char ** argv)
CTRL_MGMT_CHECK(manager.fetch("proxy.node.config.restart_required.manager"));
CTRL_MGMT_CHECK(cop.fetch("proxy.node.config.restart_required.cop"));
- printf("%s\n", version.c_str());
+ printf("%s\n", CtrlMgmtRecordValue(version).c_str());
printf("Started at %s", timestr((time_t)starttime.as_int()).c_str());
printf("Last reconfiguration at %s", timestr((time_t)configtime.as_int()).c_str());
printf("%s\n", reconfig.as_int() ? "Reconfiguration required" : "Configuration is current");
@@ -204,7 +312,7 @@ subcommand_config(unsigned argc, const char ** argv)
{
const subcommand commands[] =
{
- { CtrlUnimplementedCommand, "describe", "Show detailed information about configuration values" },
+ { config_describe, "describe", "Show detailed information about 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/857766c5/cmd/traffic_ctl/metric.cc
----------------------------------------------------------------------
diff --git a/cmd/traffic_ctl/metric.cc b/cmd/traffic_ctl/metric.cc
index fb4da30..4a90958 100644
--- a/cmd/traffic_ctl/metric.cc
+++ b/cmd/traffic_ctl/metric.cc
@@ -40,7 +40,7 @@ metric_get(unsigned argc, const char ** argv)
return CTRL_EX_ERROR;
}
- printf("%s %s\n", record.name(), record.c_str());
+ printf("%s %s\n", record.name(), CtrlMgmtRecordValue(record).c_str());
}
return CTRL_EX_OK;
@@ -67,7 +67,7 @@ metric_match(unsigned argc, const char ** argv)
while (!reclist.empty()) {
CtrlMgmtRecord record(reclist.next());
- printf("%s %s\n", record.name(), record.c_str());
+ printf("%s %s\n", record.name(), CtrlMgmtRecordValue(record).c_str());
}
}
http://git-wip-us.apache.org/repos/asf/trafficserver/blob/857766c5/cmd/traffic_ctl/traffic_ctl.cc
----------------------------------------------------------------------
diff --git a/cmd/traffic_ctl/traffic_ctl.cc b/cmd/traffic_ctl/traffic_ctl.cc
index 39b81fb..2b627f5 100644
--- a/cmd/traffic_ctl/traffic_ctl.cc
+++ b/cmd/traffic_ctl/traffic_ctl.cc
@@ -50,26 +50,6 @@ CtrlMgmtRecord::as_int() const
}
}
-const char *
-CtrlMgmtRecord::c_str() const
-{
- switch (this->ele->rec_type) {
- case TS_REC_INT:
- snprintf(this->nbuf, sizeof(this->nbuf), "%" PRId64, this->ele->valueT.int_val);
- return this->nbuf;
- case TS_REC_COUNTER:
- snprintf(this->nbuf, sizeof(this->nbuf), "%" PRId64, this->ele->valueT.counter_val);
- return this->nbuf;
- case TS_REC_FLOAT:
- snprintf(this->nbuf, sizeof(this->nbuf), "%f", this->ele->valueT.float_val);
- return this->nbuf;
- case TS_REC_STRING:
- return this->ele->valueT.string_val;
- default:
- return "(invalid)";
- }
-}
-
TSMgmtError
CtrlMgmtRecord::fetch(const char * name)
{
@@ -82,6 +62,55 @@ CtrlMgmtRecordList::match(const char * name)
return TSRecordGetMatchMlt(name, this->list);
}
+CtrlMgmtRecordValue::CtrlMgmtRecordValue(const CtrlMgmtRecord& rec)
+{
+ this->init(rec.ele->rec_type, rec.ele->valueT);
+}
+
+CtrlMgmtRecordValue::CtrlMgmtRecordValue(const TSRecordEle * ele)
+{
+ this->init(ele->rec_type, ele->valueT);
+}
+
+CtrlMgmtRecordValue::CtrlMgmtRecordValue(TSRecordT _t, TSRecordValueT _v)
+{
+ this->init(_t, _v);
+}
+
+void
+CtrlMgmtRecordValue::init(TSRecordT _t, TSRecordValueT _v)
+{
+ this->rec_type = _t;
+ switch (this->rec_type) {
+ case TS_REC_INT:
+ snprintf(this->fmt.nbuf, sizeof(this->fmt.nbuf), "%" PRId64, _v.int_val);
+ break;
+ case TS_REC_COUNTER:
+ snprintf(this->fmt.nbuf, sizeof(this->fmt.nbuf), "%" PRId64, _v.counter_val);
+ break;
+ case TS_REC_FLOAT:
+ snprintf(this->fmt.nbuf, sizeof(this->fmt.nbuf), "%f", _v.float_val);
+ break;
+ case TS_REC_STRING:
+ this->fmt.str = _v.string_val;
+ break;
+ default:
+ rec_type = TS_REC_STRING;
+ this->fmt.str = "(invalid)";
+ }
+}
+
+const char *
+CtrlMgmtRecordValue::c_str() const
+{
+ switch (this->rec_type) {
+ case TS_REC_STRING:
+ return this->fmt.str;
+ default:
+ return this->fmt.nbuf;
+ }
+}
+
void
CtrlMgmtError(TSMgmtError err, const char * fmt, ...)
{
http://git-wip-us.apache.org/repos/asf/trafficserver/blob/857766c5/cmd/traffic_ctl/traffic_ctl.h
----------------------------------------------------------------------
diff --git a/cmd/traffic_ctl/traffic_ctl.h b/cmd/traffic_ctl/traffic_ctl.h
index 62d2c5e..17e7af3 100644
--- a/cmd/traffic_ctl/traffic_ctl.h
+++ b/cmd/traffic_ctl/traffic_ctl.h
@@ -75,10 +75,9 @@ struct CtrlMgmtRecord
}
TSMgmtError fetch(const char *);
+
const char * name() const;
TSRecordT type() const;
- const char * c_str() const;
-
int64_t as_int() const;
private:
@@ -86,7 +85,28 @@ private:
CtrlMgmtRecord& operator=(const CtrlMgmtRecord&); // disabled
TSRecordEle * ele;
- mutable char nbuf[32];
+
+ friend struct CtrlMgmtRecordValue;
+};
+
+struct CtrlMgmtRecordValue
+{
+ explicit CtrlMgmtRecordValue(const TSRecordEle *);
+ explicit CtrlMgmtRecordValue(const CtrlMgmtRecord&);
+
+ CtrlMgmtRecordValue(TSRecordT, TSRecordValueT);
+ const char * c_str() const;
+
+private:
+ CtrlMgmtRecordValue(const CtrlMgmtRecordValue&); // disabled
+ CtrlMgmtRecordValue& operator=(const CtrlMgmtRecordValue&); // disabled
+ void init(TSRecordT, TSRecordValueT);
+
+ TSRecordT rec_type;
+ union {
+ const char * str;
+ char nbuf[32];
+ } fmt;
};
struct CtrlMgmtRecordList
http://git-wip-us.apache.org/repos/asf/trafficserver/blob/857766c5/lib/records/I_RecCore.h
----------------------------------------------------------------------
diff --git a/lib/records/I_RecCore.h b/lib/records/I_RecCore.h
index 40bf46c..5b5ffe0 100644
--- a/lib/records/I_RecCore.h
+++ b/lib/records/I_RecCore.h
@@ -31,6 +31,7 @@
#include "I_RecSignals.h"
#include "I_RecEvents.h"
+struct RecRecord;
//-------------------------------------------------------------------------
// Diagnostic Output
@@ -163,6 +164,9 @@ int RecGetRecordBool(const char *name, RecBool * rec_byte, bool lock = true);
//------------------------------------------------------------------------
// Record Attributes Reading
//------------------------------------------------------------------------
+
+int RecLookupRecord(const char *name, void (*callback)(const RecRecord *, void *), 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);
int RecGetRecordPersistenceType(const char *name, RecPersistT * persist_type, bool lock = true);
@@ -301,6 +305,4 @@ int RecSetSyncRequired(char *name, bool lock = true);
typedef void *(*RecManagerCb) (void *opaque_cb_data, char *data_raw, int data_len);
int RecRegisterManagerCb(int _signal, RecManagerCb _fn, void *_data = NULL);
-void RecResizeAdditional(int add);
-
#endif
http://git-wip-us.apache.org/repos/asf/trafficserver/blob/857766c5/lib/records/RecCore.cc
----------------------------------------------------------------------
diff --git a/lib/records/RecCore.cc b/lib/records/RecCore.cc
index 848eed4..f24cd84 100644
--- a/lib/records/RecCore.cc
+++ b/lib/records/RecCore.cc
@@ -422,6 +422,31 @@ RecGetRecordBool(const char *name, RecBool *rec_bool, bool lock)
//-------------------------------------------------------------------------
// RecGetRec Attributes
//-------------------------------------------------------------------------
+
+int
+RecLookupRecord(const char *name, void (*callback)(const RecRecord *, void *), void * data, bool lock)
+{
+ int err = REC_ERR_FAIL;
+ RecRecord *r;
+
+ if (lock) {
+ ink_rwlock_rdlock(&g_records_rwlock);
+ }
+
+ if (ink_hash_table_lookup(g_records_ht, name, (void **) &r)) {
+ rec_mutex_acquire(&(r->lock));
+ callback(r, data);
+ err = REC_ERR_OKAY;
+ rec_mutex_release(&(r->lock));
+ }
+
+ if (lock) {
+ ink_rwlock_unlock(&g_records_rwlock);
+ }
+
+ return err;
+}
+
int
RecGetRecordType(const char *name, RecT * rec_type, bool lock)
{
http://git-wip-us.apache.org/repos/asf/trafficserver/blob/857766c5/mgmt/api/CoreAPI.cc
----------------------------------------------------------------------
diff --git a/mgmt/api/CoreAPI.cc b/mgmt/api/CoreAPI.cc
index f48fd01..ded05d0 100644
--- a/mgmt/api/CoreAPI.cc
+++ b/mgmt/api/CoreAPI.cc
@@ -557,6 +557,12 @@ MgmtRecordGetMatching(const char * /* regex */, TSList /* rec_vals */)
return TS_ERR_FAIL;
}
+TSMgmtError
+MgmtConfigRecordDescribe(const char * /* rec_name */, unsigned /* flags */, TSConfigRecordDescription * /* val */)
+{
+ 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/857766c5/mgmt/api/CoreAPI.h
----------------------------------------------------------------------
diff --git a/mgmt/api/CoreAPI.h b/mgmt/api/CoreAPI.h
index b7a434f..5c79843 100644
--- a/mgmt/api/CoreAPI.h
+++ b/mgmt/api/CoreAPI.h
@@ -66,6 +66,7 @@ TSMgmtError MgmtRecordSetFloat(const char * rec_name, MgmtFloat float_val, TSAct
TSMgmtError MgmtRecordSetString(const char * rec_name, const char * string_val, TSActionNeedT * action_need);
TSMgmtError MgmtRecordGetMatching(const char * regex, TSList rec_vals);
+TSMgmtError MgmtConfigRecordDescribe(const char * rec_name, unsigned flags, TSConfigRecordDescription * val);
/***************************************************************************
* File Operations
http://git-wip-us.apache.org/repos/asf/trafficserver/blob/857766c5/mgmt/api/CoreAPIRemote.cc
----------------------------------------------------------------------
diff --git a/mgmt/api/CoreAPIRemote.cc b/mgmt/api/CoreAPIRemote.cc
index cc462d8..24e3c0b 100644
--- a/mgmt/api/CoreAPIRemote.cc
+++ b/mgmt/api/CoreAPIRemote.cc
@@ -427,7 +427,6 @@ Restart(unsigned options)
return ret;
}
-
/*-------------------------------------------------------------------------
* Bounce
*-------------------------------------------------------------------------
@@ -464,6 +463,35 @@ StorageDeviceCmdOffline(char const* dev)
/***************************************************************************
* Record Operations
***************************************************************************/
+
+static void
+mgmt_record_convert_value(TSRecordT rec_type, const MgmtMarshallData& data, TSRecordValueT& value)
+{
+ // convert the record value to appropriate type
+ if (data.ptr) {
+ switch (rec_type) {
+ case TS_REC_INT:
+ ink_assert(data.len == sizeof(TSInt));
+ value.int_val = *(TSInt *)data.ptr;
+ break;
+ case TS_REC_COUNTER:
+ ink_assert(data.len == sizeof(TSCounter));
+ value.counter_val = *(TSCounter *)data.ptr;
+ break;
+ case TS_REC_FLOAT:
+ ink_assert(data.len == sizeof(TSFloat));
+ value.float_val = *(TSFloat *)data.ptr;
+ break;
+ case TS_REC_STRING:
+ ink_assert(data.len == strlen((char *)data.ptr) + 1);
+ value.string_val = ats_strdup((char *)data.ptr);
+ break;
+ default:
+ ; // nothing ... shut up compiler!
+ }
+ }
+}
+
static TSMgmtError
mgmt_record_get_reply(OpType op, TSRecordEle * rec_ele)
{
@@ -472,8 +500,8 @@ mgmt_record_get_reply(OpType op, TSRecordEle * rec_ele)
MgmtMarshallData reply = { NULL, 0 };
MgmtMarshallInt err;
MgmtMarshallInt type;
- MgmtMarshallString name;
- MgmtMarshallData value;
+ MgmtMarshallString name = NULL;
+ MgmtMarshallData value = { NULL, 0 };
ink_zero(*rec_ele);
rec_ele->rec_type = TS_REC_UNDEFINED;
@@ -487,50 +515,22 @@ mgmt_record_get_reply(OpType op, TSRecordEle * rec_ele)
ret = recv_mgmt_response(reply.ptr, reply.len, op, &err, &type, &name, &value);
ats_free(reply.ptr);
if (ret != TS_ERR_OKAY) {
- return ret;
+ goto done;
}
if (err != TS_ERR_OKAY) {
- ats_free(name);
- ats_free(value.ptr);
- return (TSMgmtError)err;
+ ret = (TSMgmtError)err;
+ goto done;
}
rec_ele->rec_type = (TSRecordT)type;
+ rec_ele->rec_name = ats_strdup(name);
+ mgmt_record_convert_value(rec_ele->rec_type, value, rec_ele->valueT);
- // convert the record value to appropriate type
- if (value.ptr) {
- switch (rec_ele->rec_type) {
- case TS_REC_INT:
- ink_assert(value.len == sizeof(TSInt));
- rec_ele->valueT.int_val = *(TSInt *)value.ptr;
- break;
- case TS_REC_COUNTER:
- ink_assert(value.len == sizeof(TSCounter));
- rec_ele->valueT.counter_val = *(TSCounter *)value.ptr;
- break;
- case TS_REC_FLOAT:
- ink_assert(value.len == sizeof(TSFloat));
- rec_ele->valueT.float_val = *(TSFloat *)value.ptr;
- break;
- case TS_REC_STRING:
- ink_assert(value.len == strlen((char *)value.ptr) + 1);
- rec_ele->valueT.string_val = ats_strdup((char *)value.ptr);
- break;
- default:
- ; // nothing ... shut up compiler!
- }
- }
-
- // The record takes ownership of the (non-empty) name.
- if (strlen(name)) {
- rec_ele->rec_name = name;
- } else {
- ats_free(name);
- }
-
+done:
+ ats_free(name);
ats_free(value.ptr);
- return TS_ERR_OKAY;
+ return ret;
}
// note that the record value is being sent as chunk of memory, regardless of
@@ -552,6 +552,82 @@ MgmtRecordGet(const char *rec_name, TSRecordEle * rec_ele)
}
TSMgmtError
+MgmtConfigRecordDescribe(const char *rec_name, unsigned options, TSConfigRecordDescription * val)
+{
+ TSMgmtError ret;
+ MgmtMarshallInt optype = RECORD_DESCRIBE_CONFIG;
+ MgmtMarshallInt flags = options;
+ 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;
+
+ ret = recv_mgmt_response(reply.ptr, reply.len, RECORD_DESCRIBE_CONFIG, &err, &name, &value, &deflt, &rtype,
+ &rclass, &version, &rsb, &order, &access, &update, &updatetype, &checktype, &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;
+
+ 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;
+ }
+
+ return ret;
+}
+
+TSMgmtError
MgmtRecordGetMatching(const char * regex, TSList rec_vals)
{
TSMgmtError ret;
@@ -661,7 +737,6 @@ MgmtRecordSetFloat(const char *rec_name, MgmtFloat float_val, TSActionNeedT * ac
return ret;
}
-
TSMgmtError
MgmtRecordSetString(const char *rec_name, const char *string_val, TSActionNeedT * action_need)
{
@@ -674,7 +749,6 @@ MgmtRecordSetString(const char *rec_name, const char *string_val, TSActionNeedT
return ret;
}
-
/***************************************************************************
* File Operations
***************************************************************************/
@@ -981,4 +1055,3 @@ StatsReset(bool cluster, const char * stat_name)
ret = MGMTAPI_SEND_MESSAGE(main_socket_fd, op, &optype, &name);
return (ret == TS_ERR_OKAY) ? parse_generic_response(op, main_socket_fd) : ret;
}
-
http://git-wip-us.apache.org/repos/asf/trafficserver/blob/857766c5/mgmt/api/INKMgmtAPI.cc
----------------------------------------------------------------------
diff --git a/mgmt/api/INKMgmtAPI.cc b/mgmt/api/INKMgmtAPI.cc
index c84d83f..c7e1bbe 100644
--- a/mgmt/api/INKMgmtAPI.cc
+++ b/mgmt/api/INKMgmtAPI.cc
@@ -45,7 +45,6 @@
// forward declarations
void init_pdss_format(TSPdSsFormat& info);
-
/***************************************************************************
* API Memory Management
***************************************************************************/
@@ -73,7 +72,6 @@ _TSfree(void *ptr)
ats_free(ptr);
}
-
/***************************************************************************
* API Helper Functions for Data Carrier Structures
***************************************************************************/
@@ -212,7 +210,6 @@ TSIpAddrListEnqueue(TSIpAddrList ip_addrl, TSIpAddrEle * ip_addr)
}
}
-
/* The the TSIpAddrEle returned is actually removed from the end of list */
tsapi TSIpAddrEle *
TSIpAddrListDequeue(TSIpAddrList ip_addrl)
@@ -224,7 +221,6 @@ TSIpAddrListDequeue(TSIpAddrList ip_addrl)
return (TSIpAddrEle *) dequeue((LLQ *) ip_addrl);
}
-
tsapi int
TSIpAddrListLen(TSIpAddrList ip_addrl)
{
@@ -370,7 +366,6 @@ TSPortListIsValid(TSPortList portl)
return true;
}
-
/*--- TSDomainList operations -----------------------------------------*/
tsapi TSDomainList
TSDomainListCreate()
@@ -657,7 +652,6 @@ TSIntListIsValid(TSIntList intl, int min, int max)
return true;
}
-
// helper fn that sets default values for the info passed in
void
init_pdss_format(TSPdSsFormat& info)
@@ -948,7 +942,6 @@ TSCongestionEleDestroy(TSCongestionEle * ele)
return;
}
-
/*-------------------------------------------------------------
* HostingObj
*-------------------------------------------------------------*/
@@ -1043,7 +1036,6 @@ TSIpAllowEleDestroy(TSIpAllowEle * ele)
}
-
/*-------------------------------------------------------------
* TSLogFilterEle
*-------------------------------------------------------------*/
@@ -1513,7 +1505,6 @@ END:
return ret;
}
-
/*-------------------------------------------------------------------------
* TSRecordGetMlt
*-------------------------------------------------------------------------
@@ -1586,7 +1577,6 @@ TSRecordSet(const char *rec_name, const char *val, TSActionNeedT * action_need)
return MgmtRecordSet(rec_name, val, action_need);
}
-
tsapi TSMgmtError
TSRecordSetInt(const char *rec_name, TSInt int_val, TSActionNeedT * action_need)
{
@@ -1611,7 +1601,6 @@ TSRecordSetString(const char *rec_name, const char *str_val, TSActionNeedT * act
return MgmtRecordSetString(rec_name, str_val, action_need);
}
-
/*-------------------------------------------------------------------------
* TSRecordSetMlt
*-------------------------------------------------------------------------
@@ -1822,7 +1811,6 @@ TSStorageDeviceCmdOffline(char const* dev)
return StorageDeviceCmdOffline(dev);
}
-
/*--- diags output operations ---------------------------------------------*/
tsapi void
TSDiags(TSDiagsT mode, const char *fmt, ...)
@@ -1900,7 +1888,6 @@ TSGetErrorMessage(TSMgmtError err_id)
return err_msg;
}
-
/*--- password operations -------------------------------------------------*/
tsapi TSMgmtError
TSEncryptPassword(char *passwd, char **e_passwd)
@@ -1941,7 +1928,6 @@ TSConfigFileWrite(TSFileNameT file, char *text, int size, int version)
return WriteFile(file, text, size, version);
}
-
/* ReadFromUrl: reads a remotely located config file into a buffer
* Input: url - remote location of the file
* header - a buffer is allocated on the header char* pointer
@@ -2376,7 +2362,6 @@ TSCfgContextMoveEleDown(TSCfgContext ctx, int index)
return CfgContextMoveEleDown((CfgContext *) ctx, index);
}
-
TSMgmtError
TSCfgContextAppendEle(TSCfgContext ctx, TSCfgEle * ele)
{
@@ -2413,3 +2398,30 @@ TSIsValid(TSCfgEle * ele)
ele_obj = create_ele_obj_from_ele(ele);
return (ele_obj->isValid());
}
+
+void
+TSConfigRecordDescriptionFree(TSConfigRecordDescription * val)
+{
+ if (val) {
+ ats_free(val->rec_name);
+ ats_free(val->rec_checkexpr);
+
+ if (val->rec_type == TS_REC_STRING) {
+ ats_free(val->rec_value.string_val);
+ }
+
+ ink_zero(*val);
+ val->rec_type = TS_REC_UNDEFINED;
+ }
+}
+
+TSMgmtError
+TSConfigRecordDescribe(const char * rec_name, unsigned flags, TSConfigRecordDescription * val)
+{
+ if (!rec_name || !val) {
+ return TS_ERR_PARAMS;
+ }
+
+ TSConfigRecordDescriptionFree(val);
+ return MgmtConfigRecordDescribe(rec_name, flags, val);
+}
http://git-wip-us.apache.org/repos/asf/trafficserver/blob/857766c5/mgmt/api/NetworkMessage.cc
----------------------------------------------------------------------
diff --git a/mgmt/api/NetworkMessage.cc b/mgmt/api/NetworkMessage.cc
index 828be32..66c7e6f 100644
--- a/mgmt/api/NetworkMessage.cc
+++ b/mgmt/api/NetworkMessage.cc
@@ -29,7 +29,7 @@
#include "NetworkMessage.h"
#define MAX_OPERATION_BUFSZ 1024
-#define MAX_OPERATION_FIELDS 10
+#define MAX_OPERATION_FIELDS 16
struct NetCmdOperation
{
@@ -65,6 +65,7 @@ static const struct NetCmdOperation requests[] = {
/* RECORD_MATCH_GET */ { 2, { MGMT_MARSHALL_INT, MGMT_MARSHALL_STRING } },
/* API_PING */ { 2, { MGMT_MARSHALL_INT, MGMT_MARSHALL_INT } },
/* SERVER_BACKTRACE */ { 2, { MGMT_MARSHALL_INT, MGMT_MARSHALL_INT } },
+ /* RECORD_DESCRIBE_CONFIG */ { 3, { MGMT_MARSHALL_INT, MGMT_MARSHALL_STRING, MGMT_MARSHALL_INT } },
};
// Responses always begin with a TSMgmtError code, followed by additional fields.
@@ -95,6 +96,12 @@ static const struct NetCmdOperation responses[] = {
/* RECORD_MATCH_GET */ { 4, { MGMT_MARSHALL_INT, MGMT_MARSHALL_INT, MGMT_MARSHALL_STRING, MGMT_MARSHALL_DATA } },
/* API_PING */ { 0, {} }, // no reply
/* SERVER_BACKTRACE */ { 2, { MGMT_MARSHALL_INT, MGMT_MARSHALL_STRING } },
+ /* RECORD_DESCRIBE_CONFIG */ { 14, { MGMT_MARSHALL_INT /* status */,
+ MGMT_MARSHALL_STRING /* name */, MGMT_MARSHALL_DATA /* value */, MGMT_MARSHALL_DATA /* default */,
+ MGMT_MARSHALL_INT /* type */, MGMT_MARSHALL_INT /* class */, MGMT_MARSHALL_INT /* version */,
+ MGMT_MARSHALL_INT /* rsb */, MGMT_MARSHALL_INT /* order */, MGMT_MARSHALL_INT /* access */,
+ MGMT_MARSHALL_INT /* update */, MGMT_MARSHALL_INT /* updatetype */, MGMT_MARSHALL_INT /* checktype */,
+ MGMT_MARSHALL_STRING /* checkexpr */} },
};
#define GETCMD(ops, optype, cmd) do { \
@@ -221,6 +228,15 @@ send_mgmt_error(int fd, OpType optype, TSMgmtError error)
ink_release_assert(responses[optype].nfields == 4);
return send_mgmt_response(fd, optype, &ecode, &intval, &strval, &dataval);
+ case RECORD_DESCRIBE_CONFIG:
+ ink_release_assert(responses[optype].nfields == 14);
+ return send_mgmt_response(fd, optype, &ecode,
+ &strval /* name */, &dataval /* value */, &dataval /* default */,
+ &intval /* type */, &intval /* class */, &intval /* version */,
+ &intval /* rsb */, &intval /* order */, &intval /* access */,
+ &intval /* update */, &intval /* updatetype */, &intval /* checktype */,
+ &strval /* checkexpr */);
+
case EVENT_REG_CALLBACK:
case EVENT_UNREG_CALLBACK:
case EVENT_NOTIFY:
http://git-wip-us.apache.org/repos/asf/trafficserver/blob/857766c5/mgmt/api/NetworkMessage.h
----------------------------------------------------------------------
diff --git a/mgmt/api/NetworkMessage.h b/mgmt/api/NetworkMessage.h
index feb34cd..923fb7c 100644
--- a/mgmt/api/NetworkMessage.h
+++ b/mgmt/api/NetworkMessage.h
@@ -60,9 +60,12 @@ typedef enum
RECORD_MATCH_GET,
API_PING,
SERVER_BACKTRACE,
+ RECORD_DESCRIBE_CONFIG,
UNDEFINED_OP /* This must be last */
} OpType;
+#define MGMT_OPERATION_TYPE_MAX (UNDEFINED_OP)
+
struct mgmt_message_sender
{
virtual TSMgmtError send(void * msg, size_t msglen) const = 0;
http://git-wip-us.apache.org/repos/asf/trafficserver/blob/857766c5/mgmt/api/TSControlMain.cc
----------------------------------------------------------------------
diff --git a/mgmt/api/TSControlMain.cc b/mgmt/api/TSControlMain.cc
index 9eff803..8f8633e 100644
--- a/mgmt/api/TSControlMain.cc
+++ b/mgmt/api/TSControlMain.cc
@@ -263,6 +263,39 @@ ts_ctrl_main(void *arg)
*/
static TSMgmtError
+marshall_rec_data(RecDataT rec_type, const RecData& rec_data, MgmtMarshallData& data)
+{
+ switch (rec_type) {
+ case TS_REC_INT:
+ data.ptr = const_cast<RecInt *>(&rec_data.rec_int);
+ data.len = sizeof(TSInt);
+ break;
+ case TS_REC_COUNTER:
+ data.ptr = const_cast<RecCounter *>(&rec_data.rec_counter);
+ data.len = sizeof(TSCounter);
+ break;
+ case TS_REC_FLOAT:
+ data.ptr = const_cast<RecFloat *>(&rec_data.rec_float);
+ data.len = sizeof(TSFloat);
+ break;
+ case TS_REC_STRING:
+ // Make sure to send the NULL in the string value response.
+ if (rec_data.rec_string) {
+ data.ptr = rec_data.rec_string;
+ data.len = strlen(rec_data.rec_string) + 1;
+ } else {
+ data.ptr = (void *)"NULL";
+ data.len = countof("NULL");
+ }
+ break;
+ default: // invalid record type
+ return TS_ERR_FAIL;
+ }
+
+ return TS_ERR_OKAY;
+}
+
+static TSMgmtError
send_record_get_response(int fd, TSRecordT rec_type, const char * rec_name, const void * rec_data, size_t data_len)
{
MgmtMarshallInt err = TS_ERR_OKAY;
@@ -971,6 +1004,94 @@ handle_server_backtrace(int fd, void * req, size_t reqlen)
return (TSMgmtError)err;
}
+static void
+send_record_describe(const RecRecord * rec, void * ptr)
+{
+ MgmtMarshallString rec_name = const_cast<char *>(rec->name);
+ 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;
+ MgmtMarshallString rec_checkexpr = rec->config_meta.check_expr;
+
+ MgmtMarshallInt err = TS_ERR_OKAY;
+
+ int * fderr = (int *)ptr;
+
+ // We only describe config variables (for now).
+ if (!REC_TYPE_IS_CONFIG(rec->rec_type)) {
+ *fderr = TS_ERR_PARAMS;
+ 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;
+ }
+
+ 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, &rec_version, &rec_rsb, &rec_order,
+ &rec_access, &rec_update, &rec_updatetype, &rec_checktype, &rec_checkexpr);
+
+done:
+ *fderr = err;
+}
+
+static TSMgmtError
+handle_record_describe(int fd, void * req, size_t reqlen)
+{
+ TSMgmtError ret;
+ 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;
+ }
+
+ if (strlen(name) == 0) {
+ ret = TS_ERR_PARAMS;
+ goto done;
+ }
+
+ if (RecLookupRecord(name, send_record_describe, &fderr) != 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;
+ }
+
+done:
+ ats_free(name);
+ return ret;
+}
+
struct control_message_handler
{
unsigned flags;
@@ -1003,9 +1124,14 @@ static const control_message_handler handlers[] = {
/* STORAGE_DEVICE_CMD_OFFLINE */ { MGMT_API_PRIVILEGED, handle_storage_device_cmd_offline },
/* RECORD_MATCH_GET */ { 0, handle_record_match },
/* API_PING */ { 0, handle_api_ping },
- /* SERVER_BACKTRACE */ { MGMT_API_PRIVILEGED, handle_server_backtrace }
+ /* SERVER_BACKTRACE */ { MGMT_API_PRIVILEGED, handle_server_backtrace },
+ /* RECORD_DESCRIBE_CONFIG */ { 0, handle_record_describe }
};
+// This should use countof(), but we need a constexpr :-/
+#define NUM_OP_HANDLERS (sizeof(handlers)/sizeof(handlers[0]))
+extern char __msg_handler_static_assert[NUM_OP_HANDLERS == MGMT_OPERATION_TYPE_MAX ? 0 : -1];
+
static TSMgmtError
handle_control_message(int fd, void * req, size_t reqlen)
{
http://git-wip-us.apache.org/repos/asf/trafficserver/blob/857766c5/mgmt/api/include/mgmtapi.h
----------------------------------------------------------------------
diff --git a/mgmt/api/include/mgmtapi.h b/mgmt/api/include/mgmtapi.h
index 156e5b2..47e4b06 100644
--- a/mgmt/api/include/mgmtapi.h
+++ b/mgmt/api/include/mgmtapi.h
@@ -110,6 +110,7 @@ extern "C"
typedef int64_t TSInt;
typedef int64_t TSCounter;
typedef float TSFloat;
+ typedef bool TSBool;
typedef char *TSString;
typedef char *TSIpAddr;
@@ -432,19 +433,44 @@ extern "C"
/*--- records -------------------------------------------------------------*/
+ typedef union
+ { /* record value */
+ TSInt int_val;
+ TSCounter counter_val;
+ TSFloat float_val;
+ TSString string_val;
+ } TSRecordValueT;
+
typedef struct
{
- char *rec_name; /* record name */
+ char *rec_name; /* record name */
TSRecordT rec_type; /* record type {TS_REC_INT...} */
- union
- { /* record value */
- TSInt int_val;
- TSCounter counter_val;
- TSFloat float_val;
- TSString string_val;
- } valueT;
+ TSRecordValueT valueT; /* record value */
} TSRecordEle;
+ typedef struct
+ {
+ /* Common RecRecord fields ... */
+ char * rec_name;
+ TSRecordValueT rec_value;
+ TSRecordValueT rec_default;
+ TSRecordT rec_type; /* data type (RecDataT) */
+ TSInt rec_class; /* data class (RecT) */
+ TSInt rec_version;
+ TSInt rec_rsb; /* Raw Stat Block ID */
+ TSInt rec_order;
+
+ /* RecConfigMeta fields ... */
+ TSInt rec_access; /* access rights (RecAccessT) */
+ TSInt rec_update; /* update_required bitmask */
+ TSInt rec_updatetype; /* update type (RecUpdateT) */
+ TSInt rec_checktype; /* syntax check type (RecCheckT) */
+ char * rec_checkexpr; /* syntax check expression */
+ } TSConfigRecordDescription;
+
+ /* Free (the contents of) a TSConfigRecordDescription */
+ tsapi void TSConfigRecordDescriptionFree(TSConfigRecordDescription * val);
+
/*--- events --------------------------------------------------------------*/
/* Note: Each event has a format String associated with it from which the
@@ -1160,6 +1186,14 @@ extern "C"
tsapi TSMgmtError TSRecordSetFloat(const char *rec_name, TSFloat float_val, TSActionNeedT * action_need);
tsapi TSMgmtError TSRecordSetString(const char *rec_name, const char *string_val, TSActionNeedT * action_need);
+/* TSConfigRecordDescribe: fetch a full description of a configuration record
+ * Input: rec_name - name of the record
+ * flags - (unused) fetch flags bitmask
+ * val - output value;
+ * Output: TSMgmtError
+ */
+ tsapi TSMgmtError TSConfigRecordDescribe(const char * rec_name, unsigned flags, TSConfigRecordDescription * val);
+
/* TSRecordSetMlt: sets a set of records
* Input: rec_list - list of record names the user wants to set;
* if one set fails, transaction will be aborted