This is an automated email from the ASF dual-hosted git repository.

jpeach pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/trafficserver.git


The following commit(s) were added to refs/heads/master by this push:
     new 4b42ada  Fix Lua metrics configuration reloading.
4b42ada is described below

commit 4b42adaf94fc7efce8e163989bed4fb32ef58e16
Author: James Peach <[email protected]>
AuthorDate: Wed Jun 7 22:42:26 2017 -0700

    Fix Lua metrics configuration reloading.
    
    The Lua metrics evaluator stored the chunk to be evaluated in the
    registry. We carefully placed an assertion in the Evaluator destructor to
    make sure that we cleaned up the registry, but we never actually did it.
    
    Add an unbind() API to Evaluator and EvaluatorList to clean up the Lua
    state registry entries, and add some simple unit tests to verify that
    this works corrrectly.
    
    This fixes issue #2091.
---
 cmd/Makefile.am                        |  2 +
 cmd/traffic_manager/Makefile.am        | 13 ++++++
 cmd/traffic_manager/metrics.cc         | 58 ++++++++++++++++++-------
 cmd/traffic_manager/metrics.h          |  8 ++++
 cmd/traffic_manager/test_metrics.cc    | 78 ++++++++++++++++++++++++++++++++++
 cmd/traffic_manager/traffic_manager.cc |  6 +--
 6 files changed, 147 insertions(+), 18 deletions(-)

diff --git a/cmd/Makefile.am b/cmd/Makefile.am
index bd66e52..00a63b4 100644
--- a/cmd/Makefile.am
+++ b/cmd/Makefile.am
@@ -24,6 +24,8 @@ SUBDIRS = \
   traffic_top \
   traffic_via
 
+TESTS = $(check_PROGRAMS)
+
 if BUILD_WCCP
 
 SUBDIRS += traffic_wccp
diff --git a/cmd/traffic_manager/Makefile.am b/cmd/traffic_manager/Makefile.am
index 0aa4823..40342e2 100644
--- a/cmd/traffic_manager/Makefile.am
+++ b/cmd/traffic_manager/Makefile.am
@@ -16,6 +16,9 @@
 #  limitations under the License.
 
 bin_PROGRAMS = traffic_manager
+check_PROGRAMS = test_metrics
+
+TESTS = $(check_PROGRAMS)
 
 AM_CPPFLAGS += \
   $(LUAJIT_CPPFLAGS) \
@@ -85,6 +88,16 @@ traffic_manager_LDADD += \
   @OPENSSL_LIBS@
 endif
 
+test_metrics_SOURCES = test_metrics.cc metrics.cc
+test_metrics_LDADD = \
+  $(top_builddir)/mgmt/libmgmt_lm.la \
+  $(top_builddir)/lib/records/librecords_lm.a \
+  $(top_builddir)/lib/bindings/libbindings.la \
+  $(top_builddir)/lib/luajit/src/libluajit.a \
+  $(top_builddir)/lib/ts/libtsutil.la \
+  $(top_builddir)/iocore/eventsystem/libinkevent.a \
+  @LIBTCL@ @LIBPCRE@
+
 include $(top_srcdir)/build/tidy.mk
 
 tidy-local: $(DIST_SOURCES)
diff --git a/cmd/traffic_manager/metrics.cc b/cmd/traffic_manager/metrics.cc
index f06d5a5..eda0ae7 100644
--- a/cmd/traffic_manager/metrics.cc
+++ b/cmd/traffic_manager/metrics.cc
@@ -36,12 +36,12 @@
 #include "metrics.h"
 
 struct Evaluator {
-  Evaluator() : rec_name(nullptr), data_type(RECD_NULL), ref(-1) {}
-  ~Evaluator()
-  {
-    ats_free(this->rec_name);
-    ink_release_assert(this->ref == -1);
-  }
+  Evaluator() : rec_name(nullptr), data_type(RECD_NULL), ref(LUA_NOREF) {}
+
+  ~Evaluator() { ink_release_assert(this->ref == LUA_NOREF); }
+
+  Evaluator(const Evaluator &) = delete;
+  Evaluator &operator=(const Evaluator &) = delete;
 
   bool
   bind(lua_State *L, const char *metric, const char *expression)
@@ -72,6 +72,20 @@ struct Evaluator {
   }
 
   void
+  unbind(lua_State *L)
+  {
+    if (this->ref != LUA_NOREF) {
+      luaL_unref(L, LUA_REGISTRYINDEX, this->ref);
+    }
+
+    ats_free(this->rec_name);
+
+    this->ref       = LUA_NOREF;
+    this->rec_name  = nullptr;
+    this->data_type = RECD_NULL;
+  }
+
+  void
   eval(lua_State *L) const
   {
     // Push the stashed expression chunk onto the stack.
@@ -137,6 +151,9 @@ struct EvaluatorList {
     }
   }
 
+  EvaluatorList(const EvaluatorList &) = delete;
+  EvaluatorList &operator=(const EvaluatorList &) = delete;
+
   void
   push_back(Evaluator *e)
   {
@@ -144,6 +161,14 @@ struct EvaluatorList {
   }
 
   void
+  unbind(lua_State *L) const
+  {
+    forv_Vec (Evaluator, e, this->evaluators) {
+      e->unbind(L);
+    }
+  }
+
+  void
   evaluate(lua_State *L) const
   {
     ink_hrtime start = ink_get_hrtime_internal();
@@ -278,9 +303,6 @@ metrics_create_float(lua_State *L)
 bool
 metrics_binding_initialize(BindingInstance &binding)
 {
-  ats_scoped_str sysconfdir(RecConfigReadConfigDir());
-  ats_scoped_str config(Layout::get()->relative_to(sysconfdir, 
"metrics.config"));
-
   if (!binding.construct()) {
     mgmt_fatal(0, "failed to initialize Lua runtime\n");
   }
@@ -300,12 +322,7 @@ metrics_binding_initialize(BindingInstance &binding)
   // Stash a backpointer to the evaluators.
   binding.attach_ptr("evaluators", new EvaluatorList());
 
-  // Finally, execute the config file.
-  if (binding.require(config.get())) {
-    return true;
-  }
-
-  return false;
+  return true;
 }
 
 void
@@ -315,9 +332,20 @@ metrics_binding_destroy(BindingInstance &binding)
 
   evaluators = (EvaluatorList *)binding.retrieve_ptr("evaluators");
   binding.attach_ptr("evaluators", nullptr);
+
+  evaluators->unbind(binding.lua);
   delete evaluators;
 }
 
+bool
+metrics_binding_configure(BindingInstance &binding)
+{
+  ats_scoped_str sysconfdir(RecConfigReadConfigDir());
+  ats_scoped_str config(Layout::get()->relative_to(sysconfdir, 
"metrics.config"));
+
+  return binding.require(config.get());
+}
+
 void
 metrics_binding_evaluate(BindingInstance &binding)
 {
diff --git a/cmd/traffic_manager/metrics.h b/cmd/traffic_manager/metrics.h
index 4bc97ce..8a41551 100644
--- a/cmd/traffic_manager/metrics.h
+++ b/cmd/traffic_manager/metrics.h
@@ -24,8 +24,16 @@
 #ifndef METRICS_H_D289E71B_AAC5_4CF3_9954_D54EDED60D1B
 #define METRICS_H_D289E71B_AAC5_4CF3_9954_D54EDED60D1B
 
+#include "bindings/bindings.h"
+#include "bindings/metrics.h"
+
 bool metrics_binding_initialize(BindingInstance &binding);
 void metrics_binding_destroy(BindingInstance &binding);
+
+// Configure metrics from the metrics.config configuration file.
+bool metrics_binding_configure(BindingInstance &binding);
+
+// Evaluate the metrics in this binding instance.
 void metrics_binding_evaluate(BindingInstance &binding);
 
 #endif /* METRICS_H_D289E71B_AAC5_4CF3_9954_D54EDED60D1B */
diff --git a/cmd/traffic_manager/test_metrics.cc 
b/cmd/traffic_manager/test_metrics.cc
new file mode 100644
index 0000000..52ca96e
--- /dev/null
+++ b/cmd/traffic_manager/test_metrics.cc
@@ -0,0 +1,78 @@
+/*
+
+  @section license License
+
+  Licensed to the Apache Software Foundation (ASF) under one
+  or more contributor license agreements.  See the NOTICE file
+  distributed with this work for additional information
+  regarding copyright ownership.  The ASF licenses this file
+  to you under the Apache License, Version 2.0 (the
+  "License"); you may not use this file except in compliance
+  with the License.  You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+*/
+
+#include "ts/Regression.h"
+#include "ts/TestBox.h"
+#include "ts/I_Layout.h"
+#include "LocalManager.h"
+#include "RecordsConfig.h"
+#include "P_RecLocal.h"
+#include "metrics.h"
+
+LocalManager *lmgmt = nullptr;
+
+// Check that we can load and delete metrics.
+REGRESSION_TEST(LoadMetrics)(RegressionTest *t, int /* atype ATS_UNUSED */, 
int *pstatus)
+{
+  TestBox box(t, pstatus);
+
+  box = REGRESSION_TEST_PASSED;
+
+  BindingInstance binding;
+  box.check(metrics_binding_initialize(binding), "initialize metrics");
+  metrics_binding_destroy(binding);
+}
+
+// Check that we can set a value.
+REGRESSION_TEST(EvalMetrics)(RegressionTest *t, int /* atype ATS_UNUSED */, 
int *pstatus)
+{
+  TestBox box(t, pstatus);
+
+  box = REGRESSION_TEST_PASSED;
+
+  const char *config = R"(
+integer 'proxy.node.test.value' [[
+  return 5
+]]
+  )";
+
+  BindingInstance binding;
+
+  box.check(metrics_binding_initialize(binding), "initialize metrics");
+  box.check(binding.eval(config), "load metrics config");
+
+  metrics_binding_evaluate(binding);
+
+  RecInt value = 0;
+  box.check(RecGetRecordInt("proxy.node.test.value", &value) == REC_ERR_OKAY, 
"read value (5) from proxy.node.test.value");
+  box.check(value == 5, "proxy.node.test.value was %" PRId64 ", wanted 5", 
value);
+
+  metrics_binding_destroy(binding);
+}
+
+int
+main(int argc, const char **argv)
+{
+  Layout::create();
+  RecLocalInit();
+  LibRecordsConfigInit();
+  return RegressionTest::main(argc, argv, REGRESSION_TEST_QUICK);
+}
diff --git a/cmd/traffic_manager/traffic_manager.cc 
b/cmd/traffic_manager/traffic_manager.cc
index 3f5734c..34f6dd2 100644
--- a/cmd/traffic_manager/traffic_manager.cc
+++ b/cmd/traffic_manager/traffic_manager.cc
@@ -50,9 +50,6 @@
 
 #include "P_RecLocal.h"
 
-#include "bindings/bindings.h"
-#include "bindings/metrics.h"
-
 #include "metrics.h"
 
 #if TS_USE_POSIX_CAP
@@ -679,6 +676,7 @@ main(int argc, const char **argv)
 
   binding = new BindingInstance;
   metrics_binding_initialize(*binding);
+  metrics_binding_configure(*binding);
 
   int sleep_time = 0; // sleep_time given in sec
 
@@ -692,6 +690,8 @@ main(int argc, const char **argv)
 
       binding = new BindingInstance;
       metrics_binding_initialize(*binding);
+      metrics_binding_configure(*binding);
+
       binding_version = metrics_version;
     }
 

-- 
To stop receiving notification emails like this one, please contact
['"[email protected]" <[email protected]>'].

Reply via email to