You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@trafficcontrol.apache.org by da...@apache.org on 2017/01/13 18:47:45 UTC

[1/9] incubator-trafficcontrol git commit: Reorganized .rat-excludes.

Repository: incubator-trafficcontrol
Updated Branches:
  refs/heads/1.8.x 37325da58 -> 7e5db8d0d


Reorganized .rat-excludes.

There were several large directories excluded that contained code
that needed to be analyzed. I re-did the list of excludes to reduce
the chances that future updates that require analysis will escape it
by virtue of accidentally matching an exclusion rule.

Additionally, I included a "comment" regarding each exclusion line,
such as the regex allows. This makes it much clearer why various
files are being excluded and encourages a bit of organization in
the file.

(cherry picked from commit 4dbd960bca6974ab6d42f3e4624a93774657afb5)


Project: http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/commit/7e5db8d0
Tree: http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/tree/7e5db8d0
Diff: http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/diff/7e5db8d0

Branch: refs/heads/1.8.x
Commit: 7e5db8d0dbdfebe2c8b897a403f13610e00a97e5
Parents: 45abd39
Author: Chris Lemmons <Ch...@comcast.com>
Authored: Thu Jan 12 15:43:15 2017 -0700
Committer: Dan Kirkwood <da...@gmail.com>
Committed: Fri Jan 13 11:46:09 2017 -0700

----------------------------------------------------------------------
 .rat-excludes | 105 ++++++++++++++++++++++-------------------------------
 1 file changed, 43 insertions(+), 62 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/7e5db8d0/.rat-excludes
----------------------------------------------------------------------
diff --git a/.rat-excludes b/.rat-excludes
index 549d945..319ef8e 100644
--- a/.rat-excludes
+++ b/.rat-excludes
@@ -1,62 +1,43 @@
-.*\.cfg
-.*\.conf
-.*\.config.dist
-.*\.crt
-.*\.css
-.*\.csv
-.*\.eot
-.*\.gif
-.*\.ico
-.*\.iml
-.*\.jpg
-.*\.js
-.*\.json
-.*\.jsx
-.*\.key
-.*\.logrotate
-.*\.md
-.*\.otf
-.*\.png
-.*\.prop
-.*\.svg
-.*\.ttf
-.*\.txt
-.*\.woff
-.*\.woff2
-.*\.xml.test
-BUILD_NUMBER
-CHANGELOG
-CrStates
-DISCLAIMER
-GeoLite2-City.mmdb.gz
-LICENSE
-NOTICE
-README.*
-VERSION
-\.bowerrc
-\.classpath
-\.git.*
-\.jshintrc
-\.keep
-\.pmd
-\.project
-\.rat-excludes
-auto-zones
-checks
-docs
-etc
-goose
-jMenu.*
-jquery.*
-keystore
-keystore.jks
-misc
-perl5
-profile\..*
-profiles
-teak_favicon.ico
-testFiles
-tomcat
-traffic_ops/lib/Schema/Results
-traffic_server
-vendor
+.*\.md(?:                            Markdown files aren't usually code. ){0}
+VERSION(?:                           This very short file doesn't support comments and doesn't constitute code. ){0}
+.*\.min\.css(?:                      minified files are generated files, more akin to compiled binaries. Their source bears the license. ){0}
+.*\.min\.js(?:                       minified files ){0}
+.*\.css\.map(?:                      debug files for minified css. License borne by source. ){0}
+\..*(?:                              hidden files ought not to be code. These are generally things like projects, ignore files and such. ){0}
+LICEN[SC]E.*(?:                      Licenses do not usually require meta-licenses. ){0}
+.*\.conf(?:ig)?(?:\.?.*)?(?:         Config files aren't code and don't typically require licenses. ){0}
+.*\.cfg(?:                           config file ){0}
+.*\.logrotate(?:                     config file ){0}
+.*\.example(?:                       example config file ){0}
+etc(?:                               this folder contains only config files ){0}
+conf(?:                              this folder contains only config files ){0}
+.*\.prop(?:                          resource file for configuration ){0}
+.*\.csv(?:                           CSV data files can't handle comments, so their licenses must be documented as part of their project. ){0}
+.*\.json(?:                          json data files can't handle comments, so their licenses must be documented as part of their project. ){0}
+.*\.traffic_ops(?:                   these are also json data files, albeit in a specific format. ){0}
+CrStates(?:                          these are also json data files, albeit in a specific format. ){0}
+testFiles(?:                         test data that is neither code nor capable of bearing a license notice ){0}
+.*\.spec(?:                          Specifies license, among other things. ){0}
+.*\.test(?:                          test data ){0}
+.*\.txt(?:                           text data files can't handle comments, so their licenses must be documented as part of their project ){0}
+ssl\.(?:crt|key)(?:                  demo certificate ){0}
+keystore.*(?:                        keystore ){0}
+README.*(?:                          Readme's don't usually require a separate license. ){0}
+.*\.(?:png|gif|ico|jpe?g)?(?:        Images don't bear their own license information. ){0}
+sphinx_rtd_theme(?:                  MIT. Properly documented in LICENSE ){0}
+selenium(?:                          MIT. Properly documented in LICENSE ){0}
+gmx(?:                               MIT. Properly documented in LICENSE ){0}
+stoppableListener(?:                 MIT. Properly documented in LICENSE ){0}
+fsnotify\.v1(?:                      MIT. Properly documented in LICENSE ){0}
+jwt\-go(?:                           MIT. Properly documented in LICENSE ){0}
+pq(?:                                MIT. Properly documented in LICENSE ){0}
+bootstrap(?:-theme)?\.(?:css|js)(?:  MIT. Properly documented in LICENSE ){0}
+j[mM]enu(?:\.jquery)?\.(?:css|js)(?: MIT. Properly documented in LICENSE ){0}
+.*underscore.*(?:                    MIT. Properly documented in LICENSE ){0}
+NetPacket(?:                         MIT. Properly documented in LICENSE ){0}
+dataTables\.tableTools\.js(?:        MIT. Properly documented in LICENSE ){0}
+handlebars\.js(?:                    MIT. Properly documented in LICENSE ){0}
+.*[fF]ont[aA]wesome.*(?:             SIL OFL. Properly documented in LICENSE ){0}
+01-gofmt(?:                          Go BSD. Properly documented in LICENSE ){0}
+GeoLite2-City\.mmdb\.gz(?:           CC-SA 4.0. Properly documented in LICENSE ){0}
+ssl-bundle\.crt(?:                   MPL. Properly documented in LICENSE ){0}


[2/9] incubator-trafficcontrol git commit: Added license header for load-test.jsx.

Posted by da...@apache.org.
Added license header for load-test.jsx.

(cherry picked from commit e8021a247370cbfabe8c415ed69e0910ef1cebf1)


Project: http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/commit/9cfbf920
Tree: http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/tree/9cfbf920
Diff: http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/diff/9cfbf920

Branch: refs/heads/1.8.x
Commit: 9cfbf9209bb66300ce9fceca27aa155bde08592b
Parents: 1d9d13f
Author: Chris Lemmons <Ch...@comcast.com>
Authored: Thu Jan 12 15:11:23 2017 -0700
Committer: Dan Kirkwood <da...@gmail.com>
Committed: Fri Jan 13 11:46:09 2017 -0700

----------------------------------------------------------------------
 test/router/js/load-test.jsx | 13 +++++++++++++
 1 file changed, 13 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/9cfbf920/test/router/js/load-test.jsx
----------------------------------------------------------------------
diff --git a/test/router/js/load-test.jsx b/test/router/js/load-test.jsx
index abee17a..05cc3d2 100644
--- a/test/router/js/load-test.jsx
+++ b/test/router/js/load-test.jsx
@@ -1,3 +1,16 @@
+{/*
+	Licensed 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.
+*/}
 
 if ( ! Array.prototype.groupBy) {
     Array.prototype.groupBy = function (f)


[7/9] incubator-trafficcontrol git commit: Added license headers for git pre-commit hooks.

Posted by da...@apache.org.
Added license headers for git pre-commit hooks.

(cherry picked from commit 3e06a6d1b56d4df89437915a3604fbc312b2eee5)


Project: http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/commit/63dc2fb0
Tree: http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/tree/63dc2fb0
Diff: http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/diff/63dc2fb0

Branch: refs/heads/1.8.x
Commit: 63dc2fb0c7a1c64d4fd4376e83f4f69b96e314d5
Parents: 927e489
Author: Chris Lemmons <Ch...@comcast.com>
Authored: Thu Jan 12 15:09:04 2017 -0700
Committer: Dan Kirkwood <da...@gmail.com>
Committed: Fri Jan 13 11:46:09 2017 -0700

----------------------------------------------------------------------
 misc/git/pre-commit                 | 18 ++++++++++++++++++
 misc/git/pre-commit-hooks/02-govet  | 18 ++++++++++++++++++
 misc/git/pre-commit-hooks/03-golint | 17 +++++++++++++++++
 misc/git/pre-commit-hooks/99-gotest | 17 +++++++++++++++++
 misc/git/pre-commit-hooks/pkgs      | 17 +++++++++++++++++
 5 files changed, 87 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/63dc2fb0/misc/git/pre-commit
----------------------------------------------------------------------
diff --git a/misc/git/pre-commit b/misc/git/pre-commit
index 2067903..b362dc5 100755
--- a/misc/git/pre-commit
+++ b/misc/git/pre-commit
@@ -1,5 +1,23 @@
 #!/bin/sh
 #
+# 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.
+
+#
 # Base pre-commit hook. Place this file in ".git/hooks/pre-commit" to activate.
 # All executables in the misc/pre-commit-hooks directory will be run, stopping after first failure.
 

http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/63dc2fb0/misc/git/pre-commit-hooks/02-govet
----------------------------------------------------------------------
diff --git a/misc/git/pre-commit-hooks/02-govet b/misc/git/pre-commit-hooks/02-govet
index a868012..3676b2a 100755
--- a/misc/git/pre-commit-hooks/02-govet
+++ b/misc/git/pre-commit-hooks/02-govet
@@ -1,5 +1,23 @@
 #!/bin/sh
 
+# 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.
+
+
 # git go vet pre-commit hook
 #
 # Runs go vet

http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/63dc2fb0/misc/git/pre-commit-hooks/03-golint
----------------------------------------------------------------------
diff --git a/misc/git/pre-commit-hooks/03-golint b/misc/git/pre-commit-hooks/03-golint
index 73a651d..d6144da 100755
--- a/misc/git/pre-commit-hooks/03-golint
+++ b/misc/git/pre-commit-hooks/03-golint
@@ -1,5 +1,22 @@
 #!/bin/sh
 
+# 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.
+
 # git golint pre-commit hook
 #
 # Runs golint

http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/63dc2fb0/misc/git/pre-commit-hooks/99-gotest
----------------------------------------------------------------------
diff --git a/misc/git/pre-commit-hooks/99-gotest b/misc/git/pre-commit-hooks/99-gotest
index 8d6640a..8ed77c6 100755
--- a/misc/git/pre-commit-hooks/99-gotest
+++ b/misc/git/pre-commit-hooks/99-gotest
@@ -1,5 +1,22 @@
 #!/bin/sh
 
+# 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.
+
 # git gotest pre-commit hook
 #
 # Runs go tests and also ensures that packages with no tests compile, ie

http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/63dc2fb0/misc/git/pre-commit-hooks/pkgs
----------------------------------------------------------------------
diff --git a/misc/git/pre-commit-hooks/pkgs b/misc/git/pre-commit-hooks/pkgs
index ac8496b..a9614c5 100644
--- a/misc/git/pre-commit-hooks/pkgs
+++ b/misc/git/pre-commit-hooks/pkgs
@@ -1,5 +1,22 @@
 #!/bin/sh
 #
+# 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.
+#
 # Source this file to use PKGS, which is a space delimited list of packges
 # to be tested, linted, etc. This avoids running tests on vendored, non Traffic Control packages.
 #


[3/9] incubator-trafficcontrol git commit: Removed ATS patches.

Posted by da...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/927e4892/traffic_server/patches/trafficserver-5.3.2-f914e70.diff
----------------------------------------------------------------------
diff --git a/traffic_server/patches/trafficserver-5.3.2-f914e70.diff b/traffic_server/patches/trafficserver-5.3.2-f914e70.diff
deleted file mode 100644
index 2eaf073..0000000
--- a/traffic_server/patches/trafficserver-5.3.2-f914e70.diff
+++ /dev/null
@@ -1,7230 +0,0 @@
-diff --git a/build/ax_cxx_compile_stdcxx_11.m4 b/build/ax_cxx_compile_stdcxx_11.m4
-index e4ba5f5..a8b7d52 100644
---- a/build/ax_cxx_compile_stdcxx_11.m4
-+++ b/build/ax_cxx_compile_stdcxx_11.m4
-@@ -4,69 +4,57 @@
- #
- # SYNOPSIS
- #
--#   AX_CXX_COMPILE_STDCXX_11([ext|noext],[action-if-success],[action-if-failure])
-+#   AX_CXX_COMPILE_STDCXX_11([ext|noext],[mandatory|optional])
- #
- # DESCRIPTION
- #
- #   Check for baseline language coverage in the compiler for the C++11
- #   standard; if necessary, add switches to CXXFLAGS to enable support.
--#   Errors out if no mode that supports C++11 baseline syntax can be found.
--#   The argument, if specified, indicates whether you insist on an extended
--#   mode (e.g. -std=gnu++11) or a strict conformance mode (e.g. -std=c++11).
--#   If neither is specified, you get whatever works, with preference for an
--#   extended mode.
-+#
-+#   The first argument, if specified, indicates whether you insist on an
-+#   extended mode (e.g. -std=gnu++11) or a strict conformance mode (e.g.
-+#   -std=c++11).  If neither is specified, you get whatever works, with
-+#   preference for an extended mode.
-+#
-+#   The second argument, if specified 'mandatory' or if left unspecified,
-+#   indicates that baseline C++11 support is required and that the macro
-+#   should error out if no mode with that support is found.  If specified
-+#   'optional', then configuration proceeds regardless, after defining
-+#   HAVE_CXX11 if and only if a supporting mode is found.
- #
- # LICENSE
- #
- #   Copyright (c) 2008 Benjamin Kosnik <bk...@redhat.com>
- #   Copyright (c) 2012 Zack Weinberg <za...@panix.com>
-+#   Copyright (c) 2013 Roy Stogner <ro...@ices.utexas.edu>
-+#   Copyright (c) 2014, 2015 Google Inc.; contributed by Alexey Sokolov <so...@google.com>
- #
- #   Copying and distribution of this file, with or without modification, are
- #   permitted in any medium without royalty provided the copyright notice
- #   and this notice are preserved. This file is offered as-is, without any
- #   warranty.
- 
--#serial 1
--
--m4_define([_AX_CXX_COMPILE_STDCXX_11_testbody], [
--  template <typename T>
--    struct check
--    {
--      static_assert(sizeof(int) <= sizeof(T), "not big enough");
--    };
--
--
--    struct in_class_initialization {
--      int i = 0;
--    };
--
--    typedef check<check<bool>> right_angle_brackets;
--
--    int a;
--    decltype(a) b;
-+#serial 11
- 
--    typedef check<int> check_type;
--    check_type c;
--    check_type&& cr = static_cast<check_type&&>(c);
--
--    void * null_pointer_keyword = nullptr;
--])
-+# ATS: Modified to simply check for unordered map, which is the main
-+# feature we need right now from C++0x
-+m4_define([_AX_CXX_COMPILE_STDCXX_11_testbody], [[
-+    #include <unordered_map>
-+]])
- 
- AC_DEFUN([AX_CXX_COMPILE_STDCXX_11], [dnl
-   m4_if([$1], [], [],
-         [$1], [ext], [],
-         [$1], [noext], [],
-         [m4_fatal([invalid argument `$1' to AX_CXX_COMPILE_STDCXX_11])])dnl
--  AC_LANG_ASSERT([C++])dnl
-+  m4_if([$2], [], [ax_cxx_compile_cxx11_required=true],
-+        [$2], [mandatory], [ax_cxx_compile_cxx11_required=true],
-+        [$2], [optional], [ax_cxx_compile_cxx11_required=false],
-+        [m4_fatal([invalid second argument `$2' to AX_CXX_COMPILE_STDCXX_11])])
-+  AC_LANG_PUSH([C++])dnl
-+
-+# We now require either -std=c++11 or -std=c++0x, so don't test without either
-   ac_success=no
--  AC_CACHE_CHECK(whether $CXX supports C++11 features by default,
--  ax_cv_cxx_compile_cxx11,
--  [AC_COMPILE_IFELSE([AC_LANG_SOURCE([_AX_CXX_COMPILE_STDCXX_11_testbody])],
--    [ax_cv_cxx_compile_cxx11=yes],
--    [ax_cv_cxx_compile_cxx11=no])])
--  if test x$ax_cv_cxx_compile_cxx11 = xyes; then
--    ac_success=yes
--  fi
- 
-   m4_if([$1], [noext], [], [dnl
-   if test x$ac_success = xno; then
-@@ -90,7 +78,9 @@ AC_DEFUN([AX_CXX_COMPILE_STDCXX_11], [dnl
- 
-   m4_if([$1], [ext], [], [dnl
-   if test x$ac_success = xno; then
--    for switch in -std=c++11 -std=c++0x; do
-+    dnl HP's aCC needs +std=c++11 according to:
-+    dnl http://h21007.www2.hp.com/portal/download/files/unprot/aCxx/PDF_Release_Notes/769149-001.pdf
-+    for switch in -std=c++11 -std=c++0x +std=c++11; do
-       cachevar=AS_TR_SH([ax_cv_cxx_compile_cxx11_$switch])
-       AC_CACHE_CHECK(whether $CXX supports C++11 features with $switch,
-                      $cachevar,
-@@ -107,10 +97,21 @@ AC_DEFUN([AX_CXX_COMPILE_STDCXX_11], [dnl
-       fi
-     done
-   fi])
--
--  if test x$ac_success = xno ; then
--    m4_if([$3], [], [true], [$3])
-+  AC_LANG_POP([C++])
-+  if test x$ax_cxx_compile_cxx11_required = xtrue; then
-+    if test x$ac_success = xno; then
-+      AC_MSG_ERROR([*** A compiler with support for C++11 language features is required.])
-+    fi
-   else
--    m4_if([$2], [], [true], [$2])
-+    if test x$ac_success = xno; then
-+      HAVE_CXX11=0
-+      AC_MSG_NOTICE([No compiler with C++11 support was found])
-+    else
-+      HAVE_CXX11=1
-+      AC_DEFINE(HAVE_CXX11,1,
-+                [define if the compiler supports basic C++11 syntax])
-+    fi
-+
-+    AC_SUBST(HAVE_CXX11)
-   fi
- ])
-diff --git a/cmd/traffic_top/stats.h b/cmd/traffic_top/stats.h
-index 4b48bde..9fc8ac8 100644
---- a/cmd/traffic_top/stats.h
-+++ b/cmd/traffic_top/stats.h
-@@ -385,8 +385,8 @@ public:
-         value = (value - old) / _time_diff;
-       }
-     } else if (type == 3 || type == 4) {
--      double numerator;
--      double denominator;
-+      double numerator = 0;
-+      double denominator = 0;
-       getStat(item.numerator, numerator);
-       getStat(item.denominator, denominator);
-       if (denominator == 0)
-diff --git a/configure.ac b/configure.ac
-index 45c47fe..2c79ca4 100644
---- a/configure.ac
-+++ b/configure.ac
-@@ -578,10 +578,7 @@ CXXFLAGS="${_ts_saved_CXXFLAGS}"
- # AX_CXX_COMPILE_STDCXX_11 requires the current language to be C++.
- AC_LANG_PUSH([C++])
- 
--AX_CXX_COMPILE_STDCXX_11( [noext], [enable_cxx_11_support=yes], [
--  enable_cxx_11_support=no
--  AC_MSG_NOTICE([disabling features that depend on C++11 support])
--])
-+AX_CXX_COMPILE_STDCXX_11( [noext], [mandatory])
- 
- AM_CONDITIONAL([BUILD_HAVE_CXX_11], [ test "x${enable_cxx_11_support}" = "xyes" ])
- if test "x${enable_cxx_11_support}" = "xyes" ; then
-@@ -1948,6 +1945,7 @@ AS_IF([test "x$enable_experimental_plugins" = xyes], [
-     plugins/experimental/background_fetch/Makefile
-     plugins/experimental/balancer/Makefile
-     plugins/experimental/buffer_upload/Makefile
-+    plugins/experimental/cache_promote/Makefile
-     plugins/experimental/cache_range_requests/Makefile
-     plugins/experimental/channel_stats/Makefile
-     plugins/experimental/collapsed_connection/Makefile
-@@ -1968,6 +1966,7 @@ AS_IF([test "x$enable_experimental_plugins" = xyes], [
-     plugins/experimental/ssl_cert_loader/Makefile
-     plugins/experimental/sslheaders/Makefile
-     plugins/experimental/stale_while_revalidate/Makefile
-+    plugins/experimental/stream_editor/Makefile
-     plugins/experimental/ts_lua/Makefile
-     plugins/experimental/url_sig/Makefile
-     plugins/experimental/xdebug/Makefile
-diff --git a/doc/reference/configuration/parent.config.en.rst b/doc/reference/configuration/parent.config.en.rst
-index f025a7a..88166c9 100644
---- a/doc/reference/configuration/parent.config.en.rst
-+++ b/doc/reference/configuration/parent.config.en.rst
-@@ -21,11 +21,12 @@ parent.config
- 
- .. configfile:: parent.config
- 
--The :file:`parent.config` file identifies the parent proxies used in an
--cache hierarchy. Use this file to perform the following configuration:
-+The :file:`parent.config` file identifies the parent proxies or origins 
-+used in an cache hierarchy. Use this file to perform the following configuration:
- 
- -  Set up parent cache hierarchies, with multiple parents and parent
-    failover
-+-  Configure multiple parent origin servers.
- -  Configure selected URL requests to bypass parent proxies
- 
- Traffic Server uses the :file:`parent.config` file only when the parent
-@@ -122,6 +123,17 @@ The following list shows the possible actions and their allowed values.
-     origin server. You can specify either a hostname or an IP address,
-     but; you must specify the port number.
- 
-+.. _parent-config-format-secondary_parent-parent:
-+
-+``secondary_parent``
-+    An optional ordered list of secondary parent servers using the same format
-+    as the ``parent`` list.  A ``secondary_parent`` list only applies
-+    when ``round_robin`` is set to ``consistent_hash``.  When using
-+    ``consistent_hash``, if the server chosen from the primary list fails,
-+    a parent is selected from a secondary consistent hash ring. This feature
-+    works best in a multi-tiered cache hierarchy where one might take advantage
-+    of the content affinint built up on a secondary list of parents.
-+
- .. _parent-config-format-round-robin:
- 
- ``round_robin``
-@@ -135,6 +147,21 @@ The following list shows the possible actions and their allowed values.
-     -  ``false`` - Round robin selection does not occur.
-     -  ``consistent_hash`` - consistent hash.
- 
-+.. _parent-config-format-parent_is_proxy:
-+
-+``parent_is_proxy``
-+    One of the following values:
-+
-+    - ``true`` - Specifies that the parents are ATS cache proxies, within
-+                 a hierarchy.  This is the default value, if ``parent_is_proxy``
-+                 is not specified in the configuration.
-+
-+    - ``false`` - Specifies that the parents are origin servers. The request
-+                  url's are modified so they are appropriate for origin
-+                  requests.  Normal Parent Selection behaviour applies to
-+                  the origins listed.  Since these would be a list of origin
-+                  servers, set go_direct described below to ``false``.
-+
- .. _parent-config-format-go-direct:
- 
- ``go_direct``
-diff --git a/doc/reference/configuration/records.config.en.rst b/doc/reference/configuration/records.config.en.rst
-index d23b864..e7ea6ba 100644
---- a/doc/reference/configuration/records.config.en.rst
-+++ b/doc/reference/configuration/records.config.en.rst
-@@ -929,6 +929,26 @@ Parent Proxy Configuration
- 
-    Don't try to resolve DNS, forward all DNS requests to the parent. This is off (``0``) by default.
- 
-+.. ts:cv:: CONFIG proxy.config.http.parent_origin.simple_retry_enabled INT 0
-+
-+   Enable the simple retry feature, This is off (``0``) by default.  simple retry is only used for 
-+   parent origin servers, see configuration information for parent.config. 
-+
-+.. ts:cv:: CONFIG proxy.config.http.parent_origin.simple_retry_response_codes STRING 0
-+
-+   This is a comma separated list of response codes that will trigger a simple retry on a parent
-+   origin server if ``simple_retry`` above is enabled.  This is a ``404`` by default.
-+
-+.. ts:cv:: CONFIG proxy.config.http.parent_origin.dead_server_retry_enabled INT 0
-+
-+   Enable the dead_server retry feature, This is off (``0``) by default.  dead server retry 
-+   is only used for parent origin servers, see configuration information for parent.config. 
-+
-+.. ts:cv:: CONFIG proxy.config.http.parent_origin.dead_server_retry_response_codes STRING 0
-+
-+   This is a comma separated list of response codes that will trigger a dead server retry on 
-+   a parent origin server if ``dead_server_retry`` above is enabled.  This is a ``503`` by default.
-+
- HTTP Connection Timeouts
- ========================
- 
-diff --git a/iocore/cache/CacheDir.cc b/iocore/cache/CacheDir.cc
-index e54fbfb..30f46cd 100644
---- a/iocore/cache/CacheDir.cc
-+++ b/iocore/cache/CacheDir.cc
-@@ -1140,6 +1140,15 @@ CacheSync::mainEvent(int event, Event *e)
- Lrestart:
-   if (vol_idx >= gnvol) {
-     vol_idx = 0;
-+    if (buf) {
-+      if (buf_huge)
-+        ats_free_hugepage(buf, buflen);
-+      else
-+        ats_memalign_free(buf);
-+      buflen = 0;
-+      buf = NULL;
-+      buf_huge = false;
-+    }
-     Debug("cache_dir_sync", "sync done");
-     if (event == EVENT_INTERVAL)
-       trigger = e->ethread->schedule_in(this, HRTIME_SECONDS(cache_config_dir_sync_frequency));
-diff --git a/iocore/eventsystem/UnixEventProcessor.cc b/iocore/eventsystem/UnixEventProcessor.cc
-index 54fec71..c3180fa 100644
---- a/iocore/eventsystem/UnixEventProcessor.cc
-+++ b/iocore/eventsystem/UnixEventProcessor.cc
-@@ -135,10 +135,14 @@ EventProcessor::start(int n_event_threads, size_t stacksize)
-   Debug("iocore_thread", "Affinity: %d %ss: %d PU: %d", affinity, obj_name, obj_count, ink_number_of_processors());
- 
- #endif
--  for (i = first_thread; i < n_ethreads; i++) {
--    snprintf(thr_name, MAX_THREAD_NAME_LENGTH, "[ET_NET %d]", i);
--    ink_thread tid = all_ethreads[i]->start(thr_name, stacksize);
--    (void)tid;
-+  for (i = 0; i < n_ethreads; i++) {
-+    ink_thread tid;
-+    if (i >= first_thread) {
-+      snprintf(thr_name, MAX_THREAD_NAME_LENGTH, "[ET_NET %d]", i);
-+      tid = all_ethreads[i]->start(thr_name, stacksize);
-+    } else {
-+      tid = ink_thread_self();
-+    }
- #if TS_USE_HWLOC
-     if (obj_count > 0) {
-       obj = hwloc_get_obj_by_type(ink_get_topology(), obj_type, i % obj_count);
-@@ -154,6 +158,8 @@ EventProcessor::start(int n_event_threads, size_t stacksize)
-     } else {
-       Warning("hwloc returned an unexpected value -- CPU affinity disabled");
-     }
-+#else
-+    (void)tid;
- #endif // TS_USE_HWLOC
-   }
- 
-diff --git a/iocore/net/SSLSessionCache.cc b/iocore/net/SSLSessionCache.cc
-index 740b14f..67513a1 100644
---- a/iocore/net/SSLSessionCache.cc
-+++ b/iocore/net/SSLSessionCache.cc
-@@ -22,7 +22,6 @@
- #include "P_SSLConfig.h"
- #include "SSLSessionCache.h"
- #include <cstring>
--#include <memory>
- 
- #define SSLSESSIONCACHE_STRINGIFY0(x) #x
- #define SSLSESSIONCACHE_STRINGIFY(x) SSLSESSIONCACHE_STRINGIFY0(x)
-@@ -132,7 +131,7 @@ SSLSessionBucket::insertSession(const SSLSessionID &id, SSL_SESSION *sess)
-   unsigned char *loc = reinterpret_cast<unsigned char *>(buf->data());
-   i2d_SSL_SESSION(sess, &loc);
- 
--  std::auto_ptr<SSLSession> ssl_session(new SSLSession(id, buf, len));
-+  ats_scoped_obj<SSLSession> ssl_session(new SSLSession(id, buf, len));
- 
-   MUTEX_TRY_LOCK(lock, mutex, this_ethread());
-   if (!lock.is_locked()) {
-diff --git a/iocore/net/Socks.cc b/iocore/net/Socks.cc
-index a0350f6..7af322f 100644
---- a/iocore/net/Socks.cc
-+++ b/iocore/net/Socks.cc
-@@ -146,7 +146,7 @@ SocksEntry::free()
- 
- #ifdef SOCKS_WITH_TS
-   if (!lerrno && netVConnection && server_result.retry)
--    server_params->recordRetrySuccess(&server_result);
-+    server_params->markParentUp(&server_result);
- #endif
- 
-   if ((action_.cancelled || lerrno) && netVConnection)
-diff --git a/lib/records/RecProcess.cc b/lib/records/RecProcess.cc
-index 9a44ee6..1b69b0c 100644
---- a/lib/records/RecProcess.cc
-+++ b/lib/records/RecProcess.cc
-@@ -562,11 +562,6 @@ _RecRegisterRawStat(RecRawStatBlock *rsb, RecT rec_type, const char *name, RecDa
-     err = REC_ERR_FAIL;
-     goto Ldone;
-   }
--  if (r->rsb_id > 0 && r->rsb_id != id) {
--    Warning("_RecRegisterRawStat(): Created and reusing a stat with id = %d for new stat named %s", r->rsb_id, name);
--  } else {
--    Warning("_RecRegisterStat(): Stat created, name: %s, id: %d", name, id);
--  }
-   r->rsb_id = id; // This is the index within the RSB raw block for this stat, used for lookups by name.
-   if (i_am_the_record_owner(r->rec_type)) {
-     r->sync_required = r->sync_required | REC_PEER_SYNC_REQUIRED;
-@@ -581,7 +576,6 @@ _RecRegisterRawStat(RecRawStatBlock *rsb, RecT rec_type, const char *name, RecDa
- 
-   // setup the periodic sync callback
-   RecRegisterRawStatSyncCb(name, sync_cb, rsb, id);
--  Warning("_RecRegisterRawStat(): Stat created, id:%d name:%s, data address:%p", id, name, &r->stat_meta.data_raw);
- 
- Ldone:
-   return err;
-diff --git a/lib/ts/ConsistentHash.cc b/lib/ts/ConsistentHash.cc
-index 912bc74..22f12c0 100644
---- a/lib/ts/ConsistentHash.cc
-+++ b/lib/ts/ConsistentHash.cc
-@@ -67,19 +67,13 @@ ATSConsistentHash::insert(ATSConsistentHashNode *node, float weight, ATSHash64 *
- }
- 
- ATSConsistentHashNode *
--ATSConsistentHash::lookup(const char *url, size_t url_len, ATSConsistentHashIter *i, bool *w, ATSHash64 *h)
-+ATSConsistentHash::lookup(const char *url, ATSConsistentHashIter *i, bool *w, ATSHash64 *h)
- {
-   uint64_t url_hash;
-   ATSConsistentHashIter NodeMapIterUp, *iter;
-   ATSHash64 *thash;
-   bool *wptr, wrapped = false;
- 
--  if (url_len <= 0 && url) {
--    url_len = strlen(url);
--  } else {
--    url_len = 0;
--  }
--
-   if (h) {
-     thash = h;
-   } else if (hash) {
-@@ -101,7 +95,7 @@ ATSConsistentHash::lookup(const char *url, size_t url_len, ATSConsistentHashIter
-   }
- 
-   if (url) {
--    thash->update(url, url_len);
-+    thash->update(url, strlen(url));
-     thash->final();
-     url_hash = thash->get();
-     thash->clear();
-@@ -130,19 +124,13 @@ ATSConsistentHash::lookup(const char *url, size_t url_len, ATSConsistentHashIter
- }
- 
- ATSConsistentHashNode *
--ATSConsistentHash::lookup_available(const char *url, size_t url_len, ATSConsistentHashIter *i, bool *w, ATSHash64 *h)
-+ATSConsistentHash::lookup_available(const char *url, ATSConsistentHashIter *i, bool *w, ATSHash64 *h)
- {
-   uint64_t url_hash;
-   ATSConsistentHashIter NodeMapIterUp, *iter;
-   ATSHash64 *thash;
-   bool *wptr, wrapped = false;
- 
--  if (url_len <= 0 && url) {
--    url_len = strlen(url);
--  } else {
--    url_len = 0;
--  }
--
-   if (h) {
-     thash = h;
-   } else if (hash) {
-@@ -164,7 +152,7 @@ ATSConsistentHash::lookup_available(const char *url, size_t url_len, ATSConsiste
-   }
- 
-   if (url) {
--    thash->update(url, url_len);
-+    thash->update(url, strlen(url));
-     thash->final();
-     url_hash = thash->get();
-     thash->clear();
-diff --git a/lib/ts/ConsistentHash.h b/lib/ts/ConsistentHash.h
-index 49822ad..dbfd6c3 100644
---- a/lib/ts/ConsistentHash.h
-+++ b/lib/ts/ConsistentHash.h
-@@ -49,10 +49,9 @@ typedef std::map<uint64_t, ATSConsistentHashNode *>::iterator ATSConsistentHashI
- struct ATSConsistentHash {
-   ATSConsistentHash(int r = 1024, ATSHash64 *h = NULL);
-   void insert(ATSConsistentHashNode *node, float weight = 1.0, ATSHash64 *h = NULL);
--  ATSConsistentHashNode *lookup(const char *url = NULL, size_t url_len = 0, ATSConsistentHashIter *i = NULL, bool *w = NULL,
--                                ATSHash64 *h = NULL);
--  ATSConsistentHashNode *lookup_available(const char *url = NULL, size_t url_len = 0, ATSConsistentHashIter *i = NULL,
--                                          bool *w = NULL, ATSHash64 *h = NULL);
-+  ATSConsistentHashNode *lookup(const char *url = NULL, ATSConsistentHashIter *i = NULL, bool *w = NULL, ATSHash64 *h = NULL);
-+  ATSConsistentHashNode *lookup_available(const char *url = NULL, ATSConsistentHashIter *i = NULL, bool *w = NULL,
-+                                          ATSHash64 *h = NULL);
-   ATSConsistentHashNode *lookup_by_hashval(uint64_t hashval, ATSConsistentHashIter *i = NULL, bool *w = NULL);
-   ~ATSConsistentHash();
- 
-diff --git a/lib/ts/ink_memory.cc b/lib/ts/ink_memory.cc
-index 4c18c43..aba2104 100644
---- a/lib/ts/ink_memory.cc
-+++ b/lib/ts/ink_memory.cc
-@@ -187,22 +187,10 @@ ats_msync(caddr_t addr, size_t len, caddr_t end, int flags)
- int
- ats_madvise(caddr_t addr, size_t len, int flags)
- {
--#if defined(linux)
--  (void)addr;
--  (void)len;
--  (void)flags;
--  return 0;
--#else
--  size_t pagesize = ats_pagesize();
--  caddr_t a = (caddr_t)(((uintptr_t)addr) & ~(pagesize - 1));
--  size_t l = (len + (addr - a) + pagesize - 1) & ~(pagesize - 1);
--  int res = 0;
- #if HAVE_POSIX_MADVISE
--  res = posix_madvise(a, l, flags);
-+  return posix_madvise(addr, len, flags);
- #else
--  res = madvise(a, l, flags);
--#endif
--  return res;
-+  return madvise(addr, len, flags);
- #endif
- }
- 
-diff --git a/lib/ts/ink_queue.cc b/lib/ts/ink_queue.cc
-index 0f14b68..da2a93d 100644
---- a/lib/ts/ink_queue.cc
-+++ b/lib/ts/ink_queue.cc
-@@ -106,7 +106,7 @@ ink_freelist_init(InkFreeList **fl, const char *name, uint32_t type_size, uint32
-   if (ats_hugepage_enabled()) {
-     f->chunk_size = INK_ALIGN(chunk_size * f->type_size, ats_hugepage_size()) / f->type_size;
-   } else {
--    f->chunk_size = chunk_size;
-+    f->chunk_size = INK_ALIGN(chunk_size * f->type_size, ats_pagesize()) / f->type_size;
-   }
-   SET_FREELIST_POINTER_VERSION(f->head, FROM_PTR(0), 0);
- 
-@@ -163,6 +163,7 @@ ink_freelist_new(InkFreeList *f)
-     if (TO_PTR(FREELIST_POINTER(item)) == NULL) {
-       uint32_t type_size = f->type_size;
-       uint32_t i;
-+      size_t alloc_size = 0;
- 
- #ifdef MEMPROTECT
-       if (type_size >= MEMPROTECT_SIZE) {
-@@ -176,16 +177,17 @@ ink_freelist_new(InkFreeList *f)
- #ifdef DEBUG
-       char *oldsbrk = (char *)sbrk(0), *newsbrk = NULL;
- #endif
--      if (ats_hugepage_enabled())
--        newp = ats_alloc_hugepage(f->chunk_size * type_size);
-+      if (ats_hugepage_enabled()) {
-+        alloc_size = INK_ALIGN(f->chunk_size * f->type_size, ats_hugepage_size());
-+        newp = ats_alloc_hugepage(alloc_size);
-+      }
- 
-       if (newp == NULL) {
--        if (f->alignment)
--          newp = ats_memalign(f->alignment, f->chunk_size * type_size);
--        else
--          newp = ats_malloc(f->chunk_size * type_size);
-+        alloc_size = INK_ALIGN(f->chunk_size * f->type_size, ats_pagesize());
-+        newp = ats_memalign(ats_pagesize(), alloc_size);
-       }
--      ats_madvise((caddr_t)newp, f->chunk_size * type_size, f->advice);
-+
-+      ats_madvise((caddr_t)newp, alloc_size, f->advice);
-       fl_memadd(f->chunk_size * type_size);
- #ifdef DEBUG
-       newsbrk = (char *)sbrk(0);
-@@ -238,7 +240,6 @@ ink_freelist_new(InkFreeList *f)
- #endif /* SANITY */
-     }
-   } while (result == 0);
--  ink_assert(!((uintptr_t)TO_PTR(FREELIST_POINTER(item)) & (((uintptr_t)f->alignment) - 1)));
- 
-   ink_atomic_increment((int *)&f->used, 1);
-   ink_atomic_increment(&fastalloc_mem_in_use, (int64_t)f->type_size);
-@@ -252,7 +253,7 @@ ink_freelist_new(InkFreeList *f)
-     newp = ats_memalign(f->alignment, f->type_size);
-   else
-     newp = ats_malloc(f->type_size);
--  ats_madvise((caddr_t)newp, f->type_size, f->advice);
-+
-   return newp;
- #endif
- }
-diff --git a/lib/tsconfig/TsConfigGrammar.c b/lib/tsconfig/TsConfigGrammar.c
-index c63b4d8..042a146 100644
---- a/lib/tsconfig/TsConfigGrammar.c
-+++ b/lib/tsconfig/TsConfigGrammar.c
-@@ -1,19 +1,21 @@
--/* A Bison parser, made by GNU Bison 2.7.  */
- 
--/* Bison implementation for Yacc-like parsers in C
--
--      Copyright (C) 1984, 1989-1990, 2000-2012 Free Software Foundation, Inc.
-+/* A Bison parser, made by GNU Bison 2.4.1.  */
- 
-+/* Skeleton implementation for Bison's Yacc-like parsers in C
-+   
-+      Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006
-+   Free Software Foundation, Inc.
-+   
-    This program is free software: you can redistribute it and/or modify
-    it under the terms of the GNU General Public License as published by
-    the Free Software Foundation, either version 3 of the License, or
-    (at your option) any later version.
--
-+   
-    This program is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU General Public License for more details.
--
-+   
-    You should have received a copy of the GNU General Public License
-    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
- 
-@@ -26,7 +28,7 @@
-    special exception, which will cause the skeleton and the resulting
-    Bison output files to be licensed under the GNU General Public
-    License without this special exception.
--
-+   
-    This special exception was added by the Free Software Foundation in
-    version 2.2 of Bison.  */
- 
-@@ -44,7 +46,7 @@
- #define YYBISON 1
- 
- /* Bison version.  */
--#define YYBISON_VERSION "2.7"
-+#define YYBISON_VERSION "2.4.1"
- 
- /* Skeleton name.  */
- #define YYSKELETON_NAME "yacc.c"
-@@ -58,8 +60,12 @@
- /* Pull parsers.  */
- #define YYPULL 1
- 
-+/* Using locations.  */
-+#define YYLSP_NEEDED 0
-+
- /* "%code top" blocks.  */
--/* Line 349 of yacc.c  */
-+
-+/* Line 171 of yacc.c  */
- #line 26 "TsConfigGrammar.y"
- 
- # if ! (defined(__clang_analyzer__) || defined(__COVERITY__))
-@@ -79,9 +85,9 @@ extern int tsconfiglex(YYSTYPE* yylval, yyscan_t lexer);
- 
- 
- 
--/* Line 349 of yacc.c  */
--#line 84 "TsConfigGrammar.c"
- 
-+/* Line 171 of yacc.c  */
-+#line 91 "TsConfigGrammar.c"
- /* Substitute the variable and function names.  */
- #define yyparse         tsconfigparse
- #define yylex           tsconfiglex
-@@ -91,18 +97,17 @@ extern int tsconfiglex(YYSTYPE* yylval, yyscan_t lexer);
- #define yydebug         tsconfigdebug
- #define yynerrs         tsconfignerrs
- 
-+
- /* Copy the first part of user declarations.  */
- 
--/* Line 371 of yacc.c  */
--#line 98 "TsConfigGrammar.c"
- 
--# ifndef YY_NULL
--#  if defined __cplusplus && 201103L <= __cplusplus
--#   define YY_NULL nullptr
--#  else
--#   define YY_NULL 0
--#  endif
--# endif
-+/* Line 189 of yacc.c  */
-+#line 106 "TsConfigGrammar.c"
-+
-+/* Enabling traces.  */
-+#ifndef YYDEBUG
-+# define YYDEBUG 0
-+#endif
- 
- /* Enabling verbose error messages.  */
- #ifdef YYERROR_VERBOSE
-@@ -112,19 +117,14 @@ extern int tsconfiglex(YYSTYPE* yylval, yyscan_t lexer);
- # define YYERROR_VERBOSE 1
- #endif
- 
--/* In a future release of Bison, this section will be replaced
--   by #include "y.tab.h".  */
--#ifndef YY_TSCONFIG_TSCONFIGGRAMMAR_H_INCLUDED
--# define YY_TSCONFIG_TSCONFIGGRAMMAR_H_INCLUDED
--/* Enabling traces.  */
--#ifndef YYDEBUG
--# define YYDEBUG 0
--#endif
--#if YYDEBUG
--extern int tsconfigdebug;
-+/* Enabling the token table.  */
-+#ifndef YYTOKEN_TABLE
-+# define YYTOKEN_TABLE 0
- #endif
-+
- /* "%code requires" blocks.  */
--/* Line 387 of yacc.c  */
-+
-+/* Line 209 of yacc.c  */
- #line 1 "TsConfigGrammar.y"
- 
- /** @file
-@@ -151,8 +151,9 @@ extern int tsconfigdebug;
-  */
- 
- 
--/* Line 387 of yacc.c  */
--#line 156 "TsConfigGrammar.c"
-+
-+/* Line 209 of yacc.c  */
-+#line 157 "TsConfigGrammar.c"
- 
- /* Tokens.  */
- #ifndef YYTOKENTYPE
-@@ -190,6 +191,7 @@ extern int tsconfigdebug;
- 
- 
- 
-+
- #if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
- typedef int YYSTYPE;
- # define YYSTYPE_IS_TRIVIAL 1
-@@ -198,28 +200,14 @@ typedef int YYSTYPE;
- #endif
- 
- 
--#ifdef YYPARSE_PARAM
--#if defined __STDC__ || defined __cplusplus
--int tsconfigparse (void *YYPARSE_PARAM);
--#else
--int tsconfigparse ();
--#endif
--#else /* ! YYPARSE_PARAM */
--#if defined __STDC__ || defined __cplusplus
--int tsconfigparse (yyscan_t lexer, struct TsConfigHandlers* handlers);
--#else
--int tsconfigparse ();
--#endif
--#endif /* ! YYPARSE_PARAM */
--
--#endif /* !YY_TSCONFIG_TSCONFIGGRAMMAR_H_INCLUDED  */
--
- /* Copy the second part of user declarations.  */
- 
--/* Line 390 of yacc.c  */
--#line 221 "TsConfigGrammar.c"
-+
-+/* Line 264 of yacc.c  */
-+#line 208 "TsConfigGrammar.c"
- /* Unqualified %code blocks.  */
--/* Line 391 of yacc.c  */
-+
-+/* Line 265 of yacc.c  */
- #line 44 "TsConfigGrammar.y"
- 
- 
-@@ -242,8 +230,9 @@ int tsconfigerror(
- 
- 
- 
--/* Line 391 of yacc.c  */
--#line 247 "TsConfigGrammar.c"
-+
-+/* Line 265 of yacc.c  */
-+#line 236 "TsConfigGrammar.c"
- 
- #ifdef short
- # undef short
-@@ -293,27 +282,27 @@ typedef short int yytype_int16;
- #define YYSIZE_MAXIMUM ((YYSIZE_T) -1)
- 
- #ifndef YY_
--# if defined YYENABLE_NLS && YYENABLE_NLS
-+# if YYENABLE_NLS
- #  if ENABLE_NLS
- #   include <libintl.h> /* INFRINGES ON USER NAME SPACE */
--#   define YY_(Msgid) dgettext ("bison-runtime", Msgid)
-+#   define YY_(msgid) dgettext ("bison-runtime", msgid)
- #  endif
- # endif
- # ifndef YY_
--#  define YY_(Msgid) Msgid
-+#  define YY_(msgid) msgid
- # endif
- #endif
- 
- /* Suppress unused-variable warnings by "using" E.  */
- #if ! defined lint || defined __GNUC__
--# define YYUSE(E) ((void) (E))
-+# define YYUSE(e) ((void) (e))
- #else
--# define YYUSE(E) /* empty */
-+# define YYUSE(e) /* empty */
- #endif
- 
- /* Identity function, used to suppress warnings about constant conditions.  */
- #ifndef lint
--# define YYID(N) (N)
-+# define YYID(n) (n)
- #else
- #if (defined __STDC__ || defined __C99__FUNC__ \
-      || defined __cplusplus || defined _MSC_VER)
-@@ -346,12 +335,11 @@ YYID (yyi)
- #    define alloca _alloca
- #   else
- #    define YYSTACK_ALLOC alloca
--#    if ! defined _ALLOCA_H && ! defined EXIT_SUCCESS && (defined __STDC__ || defined __C99__FUNC__ \
-+#    if ! defined _ALLOCA_H && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \
-      || defined __cplusplus || defined _MSC_VER)
- #     include <stdlib.h> /* INFRINGES ON USER NAME SPACE */
--      /* Use EXIT_SUCCESS as a witness for stdlib.h.  */
--#     ifndef EXIT_SUCCESS
--#      define EXIT_SUCCESS 0
-+#     ifndef _STDLIB_H
-+#      define _STDLIB_H 1
- #     endif
- #    endif
- #   endif
-@@ -374,24 +362,24 @@ YYID (yyi)
- #  ifndef YYSTACK_ALLOC_MAXIMUM
- #   define YYSTACK_ALLOC_MAXIMUM YYSIZE_MAXIMUM
- #  endif
--#  if (defined __cplusplus && ! defined EXIT_SUCCESS \
-+#  if (defined __cplusplus && ! defined _STDLIB_H \
-        && ! ((defined YYMALLOC || defined malloc) \
- 	     && (defined YYFREE || defined free)))
- #   include <stdlib.h> /* INFRINGES ON USER NAME SPACE */
--#   ifndef EXIT_SUCCESS
--#    define EXIT_SUCCESS 0
-+#   ifndef _STDLIB_H
-+#    define _STDLIB_H 1
- #   endif
- #  endif
- #  ifndef YYMALLOC
- #   define YYMALLOC malloc
--#   if ! defined malloc && ! defined EXIT_SUCCESS && (defined __STDC__ || defined __C99__FUNC__ \
-+#   if ! defined malloc && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \
-      || defined __cplusplus || defined _MSC_VER)
- void *malloc (YYSIZE_T); /* INFRINGES ON USER NAME SPACE */
- #   endif
- #  endif
- #  ifndef YYFREE
- #   define YYFREE free
--#   if ! defined free && ! defined EXIT_SUCCESS && (defined __STDC__ || defined __C99__FUNC__ \
-+#   if ! defined free && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \
-      || defined __cplusplus || defined _MSC_VER)
- void free (void *); /* INFRINGES ON USER NAME SPACE */
- #   endif
-@@ -420,7 +408,23 @@ union yyalloc
-      ((N) * (sizeof (yytype_int16) + sizeof (YYSTYPE)) \
-       + YYSTACK_GAP_MAXIMUM)
- 
--# define YYCOPY_NEEDED 1
-+/* Copy COUNT objects from FROM to TO.  The source and destination do
-+   not overlap.  */
-+# ifndef YYCOPY
-+#  if defined __GNUC__ && 1 < __GNUC__
-+#   define YYCOPY(To, From, Count) \
-+      __builtin_memcpy (To, From, (Count) * sizeof (*(From)))
-+#  else
-+#   define YYCOPY(To, From, Count)		\
-+      do					\
-+	{					\
-+	  YYSIZE_T yyi;				\
-+	  for (yyi = 0; yyi < (Count); yyi++)	\
-+	    (To)[yyi] = (From)[yyi];		\
-+	}					\
-+      while (YYID (0))
-+#  endif
-+# endif
- 
- /* Relocate STACK from its old location to the new one.  The
-    local variables YYSIZE and YYSTACKSIZE give the old and new number of
-@@ -440,26 +444,6 @@ union yyalloc
- 
- #endif
- 
--#if defined YYCOPY_NEEDED && YYCOPY_NEEDED
--/* Copy COUNT objects from SRC to DST.  The source and destination do
--   not overlap.  */
--# ifndef YYCOPY
--#  if defined __GNUC__ && 1 < __GNUC__
--#   define YYCOPY(Dst, Src, Count) \
--      __builtin_memcpy (Dst, Src, (Count) * sizeof (*(Src)))
--#  else
--#   define YYCOPY(Dst, Src, Count)              \
--      do                                        \
--        {                                       \
--          YYSIZE_T yyi;                         \
--          for (yyi = 0; yyi < (Count); yyi++)   \
--            (Dst)[yyi] = (Src)[yyi];            \
--        }                                       \
--      while (YYID (0))
--#  endif
--# endif
--#endif /* !YYCOPY_NEEDED */
--
- /* YYFINAL -- State number of the termination state.  */
- #define YYFINAL  3
- /* YYLAST -- Last index in YYTABLE.  */
-@@ -547,7 +531,7 @@ static const yytype_uint8 yyrline[] =
- };
- #endif
- 
--#if YYDEBUG || YYERROR_VERBOSE || 1
-+#if YYDEBUG || YYERROR_VERBOSE || YYTOKEN_TABLE
- /* YYTNAME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM.
-    First, the terminals, then, starting at YYNTOKENS, nonterminals.  */
- static const char *const yytname[] =
-@@ -558,7 +542,7 @@ static const char *const yytname[] =
-   "config", "group", "group_open", "group_close", "group_items", "assign",
-   "$@1", "list", "list_open", "list_close", "list_items", "value",
-   "literal", "separator", "path", "path_open", "path_close", "path_item",
--  "path_tag", YY_NULL
-+  "path_tag", 0
- };
- #endif
- 
-@@ -590,8 +574,8 @@ static const yytype_uint8 yyr2[] =
-        3,     1,     1
- };
- 
--/* YYDEFACT[STATE-NAME] -- Default reduction number in state STATE-NUM.
--   Performed when YYTABLE doesn't specify something else to do.  Zero
-+/* YYDEFACT[STATE-NAME] -- Default rule to reduce with in state
-+   STATE-NUM when YYTABLE doesn't specify something else to do.  Zero
-    means the default is an error.  */
- static const yytype_uint8 yydefact[] =
- {
-@@ -630,7 +614,8 @@ static const yytype_int8 yypgoto[] =
- 
- /* YYTABLE[YYPACT[STATE-NUM]].  What to do in state STATE-NUM.  If
-    positive, shift that token.  If negative, reduce the rule which
--   number is the opposite.  If YYTABLE_NINF, syntax error.  */
-+   number is the opposite.  If zero, do what YYDEFACT says.
-+   If YYTABLE_NINF, syntax error.  */
- #define YYTABLE_NINF -3
- static const yytype_int8 yytable[] =
- {
-@@ -640,12 +625,6 @@ static const yytype_int8 yytable[] =
-       26,    42,     0,    37
- };
- 
--#define yypact_value_is_default(Yystate) \
--  (!!((Yystate) == (-11)))
--
--#define yytable_value_is_error(Yytable_value) \
--  YYID (0)
--
- static const yytype_int8 yycheck[] =
- {
-        6,     1,     0,     3,     4,     5,     6,     7,     8,     1,
-@@ -677,50 +656,78 @@ static const yytype_uint8 yystos[] =
- 
- /* Like YYERROR except do call yyerror.  This remains here temporarily
-    to ease the transition to the new meaning of YYERROR, for GCC.
--   Once GCC version 2 has supplanted version 1, this can go.  However,
--   YYFAIL appears to be in use.  Nevertheless, it is formally deprecated
--   in Bison 2.4.2's NEWS entry, where a plan to phase it out is
--   discussed.  */
-+   Once GCC version 2 has supplanted version 1, this can go.  */
- 
- #define YYFAIL		goto yyerrlab
--#if defined YYFAIL
--  /* This is here to suppress warnings from the GCC cpp's
--     -Wunused-macros.  Normally we don't worry about that warning, but
--     some users do, and we want to make it easy for users to remove
--     YYFAIL uses, which will produce warnings from Bison 2.5.  */
--#endif
- 
- #define YYRECOVERING()  (!!yyerrstatus)
- 
--#define YYBACKUP(Token, Value)                                  \
--do                                                              \
--  if (yychar == YYEMPTY)                                        \
--    {                                                           \
--      yychar = (Token);                                         \
--      yylval = (Value);                                         \
--      YYPOPSTACK (yylen);                                       \
--      yystate = *yyssp;                                         \
--      goto yybackup;                                            \
--    }                                                           \
--  else                                                          \
--    {                                                           \
-+#define YYBACKUP(Token, Value)					\
-+do								\
-+  if (yychar == YYEMPTY && yylen == 1)				\
-+    {								\
-+      yychar = (Token);						\
-+      yylval = (Value);						\
-+      yytoken = YYTRANSLATE (yychar);				\
-+      YYPOPSTACK (1);						\
-+      goto yybackup;						\
-+    }								\
-+  else								\
-+    {								\
-       yyerror (lexer, handlers, YY_("syntax error: cannot back up")); \
-       YYERROR;							\
-     }								\
- while (YYID (0))
- 
--/* Error token number */
-+
- #define YYTERROR	1
- #define YYERRCODE	256
- 
- 
--/* This macro is provided for backward compatibility. */
-+/* YYLLOC_DEFAULT -- Set CURRENT to span from RHS[1] to RHS[N].
-+   If N is 0, then set CURRENT to the empty location which ends
-+   the previous symbol: RHS[0] (always defined).  */
-+
-+#define YYRHSLOC(Rhs, K) ((Rhs)[K])
-+#ifndef YYLLOC_DEFAULT
-+# define YYLLOC_DEFAULT(Current, Rhs, N)				\
-+    do									\
-+      if (YYID (N))                                                    \
-+	{								\
-+	  (Current).first_line   = YYRHSLOC (Rhs, 1).first_line;	\
-+	  (Current).first_column = YYRHSLOC (Rhs, 1).first_column;	\
-+	  (Current).last_line    = YYRHSLOC (Rhs, N).last_line;		\
-+	  (Current).last_column  = YYRHSLOC (Rhs, N).last_column;	\
-+	}								\
-+      else								\
-+	{								\
-+	  (Current).first_line   = (Current).last_line   =		\
-+	    YYRHSLOC (Rhs, 0).last_line;				\
-+	  (Current).first_column = (Current).last_column =		\
-+	    YYRHSLOC (Rhs, 0).last_column;				\
-+	}								\
-+    while (YYID (0))
-+#endif
-+
-+
-+/* YY_LOCATION_PRINT -- Print the location on the stream.
-+   This macro was not mandated originally: define only if we know
-+   we won't break user code: when these are the locations we know.  */
-+
- #ifndef YY_LOCATION_PRINT
--# define YY_LOCATION_PRINT(File, Loc) ((void) 0)
-+# if YYLTYPE_IS_TRIVIAL
-+#  define YY_LOCATION_PRINT(File, Loc)			\
-+     fprintf (File, "%d.%d-%d.%d",			\
-+	      (Loc).first_line, (Loc).first_column,	\
-+	      (Loc).last_line,  (Loc).last_column)
-+# else
-+#  define YY_LOCATION_PRINT(File, Loc) ((void) 0)
-+# endif
- #endif
- 
- 
- /* YYLEX -- calling `yylex' with the right arguments.  */
-+
- #ifdef YYLEX_PARAM
- # define YYLEX yylex (&yylval, YYLEX_PARAM)
- #else
-@@ -772,8 +779,6 @@ yy_symbol_value_print (yyoutput, yytype, yyvaluep, lexer, handlers)
-     struct TsConfigHandlers* handlers;
- #endif
- {
--  FILE *yyo = yyoutput;
--  YYUSE (yyo);
-   if (!yyvaluep)
-     return;
-   YYUSE (lexer);
-@@ -787,7 +792,7 @@ yy_symbol_value_print (yyoutput, yytype, yyvaluep, lexer, handlers)
-   switch (yytype)
-     {
-       default:
--        break;
-+	break;
-     }
- }
- 
-@@ -917,6 +922,7 @@ int yydebug;
- # define YYMAXDEPTH 10000
- #endif
- 
-+
- 
- #if YYERROR_VERBOSE
- 
-@@ -1019,145 +1025,115 @@ yytnamerr (char *yyres, const char *yystr)
- }
- # endif
- 
--/* Copy into *YYMSG, which is of size *YYMSG_ALLOC, an error message
--   about the unexpected token YYTOKEN for the state stack whose top is
--   YYSSP.
--
--   Return 0 if *YYMSG was successfully written.  Return 1 if *YYMSG is
--   not large enough to hold the message.  In that case, also set
--   *YYMSG_ALLOC to the required number of bytes.  Return 2 if the
--   required number of bytes is too large to store.  */
--static int
--yysyntax_error (YYSIZE_T *yymsg_alloc, char **yymsg,
--                yytype_int16 *yyssp, int yytoken)
-+/* Copy into YYRESULT an error message about the unexpected token
-+   YYCHAR while in state YYSTATE.  Return the number of bytes copied,
-+   including the terminating null byte.  If YYRESULT is null, do not
-+   copy anything; just return the number of bytes that would be
-+   copied.  As a special case, return 0 if an ordinary "syntax error"
-+   message will do.  Return YYSIZE_MAXIMUM if overflow occurs during
-+   size calculation.  */
-+static YYSIZE_T
-+yysyntax_error (char *yyresult, int yystate, int yychar)
- {
--  YYSIZE_T yysize0 = yytnamerr (YY_NULL, yytname[yytoken]);
--  YYSIZE_T yysize = yysize0;
--  enum { YYERROR_VERBOSE_ARGS_MAXIMUM = 5 };
--  /* Internationalized format string. */
--  const char *yyformat = YY_NULL;
--  /* Arguments of yyformat. */
--  char const *yyarg[YYERROR_VERBOSE_ARGS_MAXIMUM];
--  /* Number of reported tokens (one for the "unexpected", one per
--     "expected"). */
--  int yycount = 0;
--
--  /* There are many possibilities here to consider:
--     - Assume YYFAIL is not used.  It's too flawed to consider.  See
--       <http://lists.gnu.org/archive/html/bison-patches/2009-12/msg00024.html>
--       for details.  YYERROR is fine as it does not invoke this
--       function.
--     - If this state is a consistent state with a default action, then
--       the only way this function was invoked is if the default action
--       is an error action.  In that case, don't check for expected
--       tokens because there are none.
--     - The only way there can be no lookahead present (in yychar) is if
--       this state is a consistent state with a default action.  Thus,
--       detecting the absence of a lookahead is sufficient to determine
--       that there is no unexpected or expected token to report.  In that
--       case, just report a simple "syntax error".
--     - Don't assume there isn't a lookahead just because this state is a
--       consistent state with a default action.  There might have been a
--       previous inconsistent state, consistent state with a non-default
--       action, or user semantic action that manipulated yychar.
--     - Of course, the expected token list depends on states to have
--       correct lookahead information, and it depends on the parser not
--       to perform extra reductions after fetching a lookahead from the
--       scanner and before detecting a syntax error.  Thus, state merging
--       (from LALR or IELR) and default reductions corrupt the expected
--       token list.  However, the list is correct for canonical LR with
--       one exception: it will still contain any token that will not be
--       accepted due to an error action in a later state.
--  */
--  if (yytoken != YYEMPTY)
--    {
--      int yyn = yypact[*yyssp];
--      yyarg[yycount++] = yytname[yytoken];
--      if (!yypact_value_is_default (yyn))
--        {
--          /* Start YYX at -YYN if negative to avoid negative indexes in
--             YYCHECK.  In other words, skip the first -YYN actions for
--             this state because they are default actions.  */
--          int yyxbegin = yyn < 0 ? -yyn : 0;
--          /* Stay within bounds of both yycheck and yytname.  */
--          int yychecklim = YYLAST - yyn + 1;
--          int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS;
--          int yyx;
--
--          for (yyx = yyxbegin; yyx < yyxend; ++yyx)
--            if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR
--                && !yytable_value_is_error (yytable[yyx + yyn]))
--              {
--                if (yycount == YYERROR_VERBOSE_ARGS_MAXIMUM)
--                  {
--                    yycount = 1;
--                    yysize = yysize0;
--                    break;
--                  }
--                yyarg[yycount++] = yytname[yyx];
--                {
--                  YYSIZE_T yysize1 = yysize + yytnamerr (YY_NULL, yytname[yyx]);
--                  if (! (yysize <= yysize1
--                         && yysize1 <= YYSTACK_ALLOC_MAXIMUM))
--                    return 2;
--                  yysize = yysize1;
--                }
--              }
--        }
--    }
-+  int yyn = yypact[yystate];
- 
--  switch (yycount)
-+  if (! (YYPACT_NINF < yyn && yyn <= YYLAST))
-+    return 0;
-+  else
-     {
--# define YYCASE_(N, S)                      \
--      case N:                               \
--        yyformat = S;                       \
--      break
--      YYCASE_(0, YY_("syntax error"));
--      YYCASE_(1, YY_("syntax error, unexpected %s"));
--      YYCASE_(2, YY_("syntax error, unexpected %s, expecting %s"));
--      YYCASE_(3, YY_("syntax error, unexpected %s, expecting %s or %s"));
--      YYCASE_(4, YY_("syntax error, unexpected %s, expecting %s or %s or %s"));
--      YYCASE_(5, YY_("syntax error, unexpected %s, expecting %s or %s or %s or %s"));
--# undef YYCASE_
--    }
-+      int yytype = YYTRANSLATE (yychar);
-+      YYSIZE_T yysize0 = yytnamerr (0, yytname[yytype]);
-+      YYSIZE_T yysize = yysize0;
-+      YYSIZE_T yysize1;
-+      int yysize_overflow = 0;
-+      enum { YYERROR_VERBOSE_ARGS_MAXIMUM = 5 };
-+      char const *yyarg[YYERROR_VERBOSE_ARGS_MAXIMUM];
-+      int yyx;
-+
-+# if 0
-+      /* This is so xgettext sees the translatable formats that are
-+	 constructed on the fly.  */
-+      YY_("syntax error, unexpected %s");
-+      YY_("syntax error, unexpected %s, expecting %s");
-+      YY_("syntax error, unexpected %s, expecting %s or %s");
-+      YY_("syntax error, unexpected %s, expecting %s or %s or %s");
-+      YY_("syntax error, unexpected %s, expecting %s or %s or %s or %s");
-+# endif
-+      char *yyfmt;
-+      char const *yyf;
-+      static char const yyunexpected[] = "syntax error, unexpected %s";
-+      static char const yyexpecting[] = ", expecting %s";
-+      static char const yyor[] = " or %s";
-+      char yyformat[sizeof yyunexpected
-+		    + sizeof yyexpecting - 1
-+		    + ((YYERROR_VERBOSE_ARGS_MAXIMUM - 2)
-+		       * (sizeof yyor - 1))];
-+      char const *yyprefix = yyexpecting;
-+
-+      /* Start YYX at -YYN if negative to avoid negative indexes in
-+	 YYCHECK.  */
-+      int yyxbegin = yyn < 0 ? -yyn : 0;
-+
-+      /* Stay within bounds of both yycheck and yytname.  */
-+      int yychecklim = YYLAST - yyn + 1;
-+      int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS;
-+      int yycount = 1;
-+
-+      yyarg[0] = yytname[yytype];
-+      yyfmt = yystpcpy (yyformat, yyunexpected);
-+
-+      for (yyx = yyxbegin; yyx < yyxend; ++yyx)
-+	if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR)
-+	  {
-+	    if (yycount == YYERROR_VERBOSE_ARGS_MAXIMUM)
-+	      {
-+		yycount = 1;
-+		yysize = yysize0;
-+		yyformat[sizeof yyunexpected - 1] = '\0';
-+		break;
-+	      }
-+	    yyarg[yycount++] = yytname[yyx];
-+	    yysize1 = yysize + yytnamerr (0, yytname[yyx]);
-+	    yysize_overflow |= (yysize1 < yysize);
-+	    yysize = yysize1;
-+	    yyfmt = yystpcpy (yyfmt, yyprefix);
-+	    yyprefix = yyor;
-+	  }
- 
--  {
--    YYSIZE_T yysize1 = yysize + yystrlen (yyformat);
--    if (! (yysize <= yysize1 && yysize1 <= YYSTACK_ALLOC_MAXIMUM))
--      return 2;
--    yysize = yysize1;
--  }
-+      yyf = YY_(yyformat);
-+      yysize1 = yysize + yystrlen (yyf);
-+      yysize_overflow |= (yysize1 < yysize);
-+      yysize = yysize1;
- 
--  if (*yymsg_alloc < yysize)
--    {
--      *yymsg_alloc = 2 * yysize;
--      if (! (yysize <= *yymsg_alloc
--             && *yymsg_alloc <= YYSTACK_ALLOC_MAXIMUM))
--        *yymsg_alloc = YYSTACK_ALLOC_MAXIMUM;
--      return 1;
--    }
-+      if (yysize_overflow)
-+	return YYSIZE_MAXIMUM;
- 
--  /* Avoid sprintf, as that infringes on the user's name space.
--     Don't have undefined behavior even if the translation
--     produced a string with the wrong number of "%s"s.  */
--  {
--    char *yyp = *yymsg;
--    int yyi = 0;
--    while ((*yyp = *yyformat) != '\0')
--      if (*yyp == '%' && yyformat[1] == 's' && yyi < yycount)
--        {
--          yyp += yytnamerr (yyp, yyarg[yyi++]);
--          yyformat += 2;
--        }
--      else
--        {
--          yyp++;
--          yyformat++;
--        }
--  }
--  return 0;
-+      if (yyresult)
-+	{
-+	  /* Avoid sprintf, as that infringes on the user's name space.
-+	     Don't have undefined behavior even if the translation
-+	     produced a string with the wrong number of "%s"s.  */
-+	  char *yyp = yyresult;
-+	  int yyi = 0;
-+	  while ((*yyp = *yyf) != '\0')
-+	    {
-+	      if (*yyp == '%' && yyf[1] == 's' && yyi < yycount)
-+		{
-+		  yyp += yytnamerr (yyp, yyarg[yyi++]);
-+		  yyf += 2;
-+		}
-+	      else
-+		{
-+		  yyp++;
-+		  yyf++;
-+		}
-+	    }
-+	}
-+      return yysize;
-+    }
- }
- #endif /* YYERROR_VERBOSE */
-+
- 
- /*-----------------------------------------------.
- | Release the memory associated to this symbol.  |
-@@ -1190,16 +1166,32 @@ yydestruct (yymsg, yytype, yyvaluep, lexer, handlers)
-     {
- 
-       default:
--        break;
-+	break;
-     }
- }
- 
-+/* Prevent warnings from -Wmissing-prototypes.  */
-+#ifdef YYPARSE_PARAM
-+#if defined __STDC__ || defined __cplusplus
-+int yyparse (void *YYPARSE_PARAM);
-+#else
-+int yyparse ();
-+#endif
-+#else /* ! YYPARSE_PARAM */
-+#if defined __STDC__ || defined __cplusplus
-+int yyparse (yyscan_t lexer, struct TsConfigHandlers* handlers);
-+#else
-+int yyparse ();
-+#endif
-+#endif /* ! YYPARSE_PARAM */
-+
- 
- 
- 
--/*----------.
--| yyparse.  |
--`----------*/
-+
-+/*-------------------------.
-+| yyparse or yypush_parse.  |
-+`-------------------------*/
- 
- #ifdef YYPARSE_PARAM
- #if (defined __STDC__ || defined __C99__FUNC__ \
-@@ -1227,31 +1219,8 @@ yyparse (lexer, handlers)
- /* The lookahead symbol.  */
- int yychar;
- 
--
--#if defined __GNUC__ && 407 <= __GNUC__ * 100 + __GNUC_MINOR__
--/* Suppress an incorrect diagnostic about yylval being uninitialized.  */
--# define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN \
--    _Pragma ("GCC diagnostic push") \
--    _Pragma ("GCC diagnostic ignored \"-Wuninitialized\"")\
--    _Pragma ("GCC diagnostic ignored \"-Wmaybe-uninitialized\"")
--# define YY_IGNORE_MAYBE_UNINITIALIZED_END \
--    _Pragma ("GCC diagnostic pop")
--#else
--/* Default value used for initialization, for pacifying older GCCs
--   or non-GCC compilers.  */
--static YYSTYPE yyval_default;
--# define YY_INITIAL_VALUE(Value) = Value
--#endif
--#ifndef YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
--# define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
--# define YY_IGNORE_MAYBE_UNINITIALIZED_END
--#endif
--#ifndef YY_INITIAL_VALUE
--# define YY_INITIAL_VALUE(Value) /* Nothing. */
--#endif
--
- /* The semantic value of the lookahead symbol.  */
--YYSTYPE yylval YY_INITIAL_VALUE(yyval_default);
-+YYSTYPE yylval;
- 
-     /* Number of syntax errors so far.  */
-     int yynerrs;
-@@ -1264,7 +1233,7 @@ YYSTYPE yylval YY_INITIAL_VALUE(yyval_default);
-        `yyss': related to states.
-        `yyvs': related to semantic values.
- 
--       Refer to the stacks through separate pointers, to allow yyoverflow
-+       Refer to the stacks thru separate pointers, to allow yyoverflow
-        to reallocate them elsewhere.  */
- 
-     /* The state stack.  */
-@@ -1282,7 +1251,7 @@ YYSTYPE yylval YY_INITIAL_VALUE(yyval_default);
-   int yyn;
-   int yyresult;
-   /* Lookahead token as an internal (translated) token number.  */
--  int yytoken = 0;
-+  int yytoken;
-   /* The variables used to return semantic value and location from the
-      action routines.  */
-   YYSTYPE yyval;
-@@ -1300,8 +1269,9 @@ YYSTYPE yylval YY_INITIAL_VALUE(yyval_default);
-      Keep to zero when no symbol should be popped.  */
-   int yylen = 0;
- 
--  yyssp = yyss = yyssa;
--  yyvsp = yyvs = yyvsa;
-+  yytoken = 0;
-+  yyss = yyssa;
-+  yyvs = yyvsa;
-   yystacksize = YYINITDEPTH;
- 
-   YYDPRINTF ((stderr, "Starting parse\n"));
-@@ -1310,6 +1280,14 @@ YYSTYPE yylval YY_INITIAL_VALUE(yyval_default);
-   yyerrstatus = 0;
-   yynerrs = 0;
-   yychar = YYEMPTY; /* Cause a token to be read.  */
-+
-+  /* Initialize stack pointers.
-+     Waste one element of value and location stack
-+     so that they stay on the same level as the state stack.
-+     The wasted elements are never initialized.  */
-+  yyssp = yyss;
-+  yyvsp = yyvs;
-+
-   goto yysetstate;
- 
- /*------------------------------------------------------------.
-@@ -1401,7 +1379,7 @@ yybackup:
- 
-   /* First try to decide what to do without reference to lookahead token.  */
-   yyn = yypact[yystate];
--  if (yypact_value_is_default (yyn))
-+  if (yyn == YYPACT_NINF)
-     goto yydefault;
- 
-   /* Not known => get a lookahead token if don't already have one.  */
-@@ -1432,8 +1410,8 @@ yybackup:
-   yyn = yytable[yyn];
-   if (yyn <= 0)
-     {
--      if (yytable_value_is_error (yyn))
--        goto yyerrlab;
-+      if (yyn == 0 || yyn == YYTABLE_NINF)
-+	goto yyerrlab;
-       yyn = -yyn;
-       goto yyreduce;
-     }
-@@ -1450,9 +1428,7 @@ yybackup:
-   yychar = YYEMPTY;
- 
-   yystate = yyn;
--  YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
-   *++yyvsp = yylval;
--  YY_IGNORE_MAYBE_UNINITIALIZED_END
- 
-   goto yynewstate;
- 
-@@ -1489,81 +1465,81 @@ yyreduce:
-   switch (yyn)
-     {
-         case 4:
--/* Line 1792 of yacc.c  */
-+
-+/* Line 1455 of yacc.c  */
- #line 90 "TsConfigGrammar.y"
-     { HANDLE_EVENT(GroupOpen, (yyvsp[(1) - (1)])); }
-     break;
- 
-   case 5:
--/* Line 1792 of yacc.c  */
-+
-+/* Line 1455 of yacc.c  */
- #line 92 "TsConfigGrammar.y"
-     { HANDLE_EVENT(GroupClose, (yyvsp[(1) - (1)])); }
-     break;
- 
-   case 9:
--/* Line 1792 of yacc.c  */
-+
-+/* Line 1455 of yacc.c  */
- #line 96 "TsConfigGrammar.y"
-     { HANDLE_EVENT(GroupName, (yyvsp[(1) - (2)])); }
-     break;
- 
-   case 12:
--/* Line 1792 of yacc.c  */
-+
-+/* Line 1455 of yacc.c  */
- #line 100 "TsConfigGrammar.y"
-     { HANDLE_EVENT(ListOpen, (yyvsp[(1) - (1)])); }
-     break;
- 
-   case 13:
--/* Line 1792 of yacc.c  */
-+
-+/* Line 1455 of yacc.c  */
- #line 102 "TsConfigGrammar.y"
-     { HANDLE_EVENT(ListClose, (yyvsp[(1) - (1)])); }
-     break;
- 
-   case 17:
--/* Line 1792 of yacc.c  */
-+
-+/* Line 1455 of yacc.c  */
- #line 106 "TsConfigGrammar.y"
-     { HANDLE_EVENT(LiteralValue, (yyvsp[(1) - (1)])); }
-     break;
- 
-   case 27:
--/* Line 1792 of yacc.c  */
-+
-+/* Line 1455 of yacc.c  */
- #line 114 "TsConfigGrammar.y"
-     { HANDLE_EVENT(PathOpen, (yyvsp[(1) - (1)])); }
-     break;
- 
-   case 28:
--/* Line 1792 of yacc.c  */
-+
-+/* Line 1455 of yacc.c  */
- #line 116 "TsConfigGrammar.y"
-     { HANDLE_EVENT(PathClose, (yyvsp[(1) - (1)])); }
-     break;
- 
-   case 31:
--/* Line 1792 of yacc.c  */
-+
-+/* Line 1455 of yacc.c  */
- #line 120 "TsConfigGrammar.y"
-     { HANDLE_EVENT(PathTag, (yyvsp[(1) - (1)])); }
-     break;
- 
-   case 32:
--/* Line 1792 of yacc.c  */
-+
-+/* Line 1455 of yacc.c  */
- #line 120 "TsConfigGrammar.y"
-     { HANDLE_EVENT(PathIndex, (yyvsp[(1) - (1)])); }
-     break;
- 
- 
--/* Line 1792 of yacc.c  */
--#line 1554 "TsConfigGrammar.c"
-+
-+/* Line 1455 of yacc.c  */
-+#line 1541 "TsConfigGrammar.c"
-       default: break;
-     }
--  /* User semantic actions sometimes alter yychar, and that requires
--     that yytoken be updated with the new translation.  We take the
--     approach of translating immediately before every use of yytoken.
--     One alternative is translating here after every semantic action,
--     but that translation would be missed if the semantic action invokes
--     YYABORT, YYACCEPT, or YYERROR immediately after altering yychar or
--     if it invokes YYBACKUP.  In the case of YYABORT or YYACCEPT, an
--     incorrect destructor might then be invoked immediately.  In the
--     case of YYERROR or YYBACKUP, subsequent parser actions might lead
--     to an incorrect destructor call or verbose syntax error message
--     before the lookahead is translated.  */
-   YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyn], &yyval, &yyloc);
- 
-   YYPOPSTACK (yylen);
-@@ -1591,10 +1567,6 @@ yyreduce:
- | yyerrlab -- here on detecting error |
- `------------------------------------*/
- yyerrlab:
--  /* Make sure we have latest lookahead translation.  See comments at
--     user semantic actions for why this is necessary.  */
--  yytoken = yychar == YYEMPTY ? YYEMPTY : YYTRANSLATE (yychar);
--
-   /* If not already recovering from an error, report this error.  */
-   if (!yyerrstatus)
-     {
-@@ -1602,36 +1574,37 @@ yyerrlab:
- #if ! YYERROR_VERBOSE
-       yyerror (lexer, handlers, YY_("syntax error"));
- #else
--# define YYSYNTAX_ERROR yysyntax_error (&yymsg_alloc, &yymsg, \
--                                        yyssp, yytoken)
-       {
--        char const *yymsgp = YY_("syntax error");
--        int yysyntax_error_status;
--        yysyntax_error_status = YYSYNTAX_ERROR;
--        if (yysyntax_error_status == 0)
--          yymsgp = yymsg;
--        else if (yysyntax_error_status == 1)
--          {
--            if (yymsg != yymsgbuf)
--              YYSTACK_FREE (yymsg);
--            yymsg = (char *) YYSTACK_ALLOC (yymsg_alloc);
--            if (!yymsg)
--              {
--                yymsg = yymsgbuf;
--                yymsg_alloc = sizeof yymsgbuf;
--                yysyntax_error_status = 2;
--              }
--            else
--              {
--                yysyntax_error_status = YYSYNTAX_ERROR;
--                yymsgp = yymsg;
--              }
--          }
--        yyerror (lexer, handlers, yymsgp);
--        if (yysyntax_error_status == 2)
--          goto yyexhaustedlab;
-+	YYSIZE_T yysize = yysyntax_error (0, yystate, yychar);
-+	if (yymsg_alloc < yysize && yymsg_alloc < YYSTACK_ALLOC_MAXIMUM)
-+	  {
-+	    YYSIZE_T yyalloc = 2 * yysize;
-+	    if (! (yysize <= yyalloc && yyalloc <= YYSTACK_ALLOC_MAXIMUM))
-+	      yyalloc = YYSTACK_ALLOC_MAXIMUM;
-+	    if (yymsg != yymsgbuf)
-+	      YYSTACK_FREE (yymsg);
-+	    yymsg = (char *) YYSTACK_ALLOC (yyalloc);
-+	    if (yymsg)
-+	      yymsg_alloc = yyalloc;
-+	    else
-+	      {
-+		yymsg = yymsgbuf;
-+		yymsg_alloc = sizeof yymsgbuf;
-+	      }
-+	  }
-+
-+	if (0 < yysize && yysize <= yymsg_alloc)
-+	  {
-+	    (void) yysyntax_error (yymsg, yystate, yychar);
-+	    yyerror (lexer, handlers, yymsg);
-+	  }
-+	else
-+	  {
-+	    yyerror (lexer, handlers, YY_("syntax error"));
-+	    if (yysize != 0)
-+	      goto yyexhaustedlab;
-+	  }
-       }
--# undef YYSYNTAX_ERROR
- #endif
-     }
- 
-@@ -1690,7 +1663,7 @@ yyerrlab1:
-   for (;;)
-     {
-       yyn = yypact[yystate];
--      if (!yypact_value_is_default (yyn))
-+      if (yyn != YYPACT_NINF)
- 	{
- 	  yyn += YYTERROR;
- 	  if (0 <= yyn && yyn <= YYLAST && yycheck[yyn] == YYTERROR)
-@@ -1713,9 +1686,7 @@ yyerrlab1:
-       YY_STACK_PRINT (yyss, yyssp);
-     }
- 
--  YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
-   *++yyvsp = yylval;
--  YY_IGNORE_MAYBE_UNINITIALIZED_END
- 
- 
-   /* Shift the error token.  */
-@@ -1739,7 +1710,7 @@ yyabortlab:
-   yyresult = 1;
-   goto yyreturn;
- 
--#if !defined yyoverflow || YYERROR_VERBOSE
-+#if !defined(yyoverflow) || YYERROR_VERBOSE
- /*-------------------------------------------------.
- | yyexhaustedlab -- memory exhaustion comes here.  |
- `-------------------------------------------------*/
-@@ -1751,13 +1722,8 @@ yyexhaustedlab:
- 
- yyreturn:
-   if (yychar != YYEMPTY)
--    {
--      /* Make sure we have latest lookahead translation.  See comments at
--         user semantic actions for why this is necessary.  */
--      yytoken = YYTRANSLATE (yychar);
--      yydestruct ("Cleanup: discarding lookahead",
--                  yytoken, &yylval, lexer, handlers);
--    }
-+     yydestruct ("Cleanup: discarding lookahead",
-+		 yytoken, &yylval, lexer, handlers);
-   /* Do not reclaim the symbols of the rule which action triggered
-      this YYABORT or YYACCEPT.  */
-   YYPOPSTACK (yylen);
-@@ -1781,8 +1747,10 @@ yyreturn:
- }
- 
- 
--/* Line 2055 of yacc.c  */
-+
-+/* Line 1675 of yacc.c  */
- #line 122 "TsConfigGrammar.y"
- 
- 
- # endif // __clang_analyzer__
-+
-diff --git a/lib/tsconfig/TsConfigGrammar.h b/lib/tsconfig/TsConfigGrammar.h
-index 52f083b..d3581d9 100644
---- a/lib/tsconfig/TsConfigGrammar.h
-+++ b/lib/tsconfig/TsConfigGrammar.h
-@@ -1,19 +1,21 @@
--/* A Bison parser, made by GNU Bison 2.7.  */
- 
--/* Bison interface for Yacc-like parsers in C
--
--      Copyright (C) 1984, 1989-1990, 2000-2012 Free Software Foundation, Inc.
-+/* A Bison parser, made by GNU Bison 2.4.1.  */
- 
-+/* Skeleton interface for Bison's Yacc-like parsers in C
-+   
-+      Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006
-+   Free Software Foundation, Inc.
-+   
-    This program is free software: you can redistribute it and/or modify
-    it under the terms of the GNU General Public License as published by
-    the Free Software Foundation, either version 3 of the License, or
-    (at your option) any later version.
--
-+   
-    This program is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU General Public License for more details.
--
-+   
-    You should have received a copy of the GNU General Public License
-    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
- 
-@@ -26,21 +28,13 @@
-    special exception, which will cause the skeleton and the resulting
-    Bison output files to be licensed under the GNU General Public
-    License without this special exception.
--
-+   
-    This special exception was added by the Free Software Foundation in
-    version 2.2 of Bison.  */
- 
--#ifndef YY_TSCONFIG_TSCONFIGGRAMMAR_H_INCLUDED
--# define YY_TSCONFIG_TSCONFIGGRAMMAR_H_INCLUDED
--/* Enabling traces.  */
--#ifndef YYDEBUG
--# define YYDEBUG 0
--#endif
--#if YYDEBUG
--extern int tsconfigdebug;
--#endif
- /* "%code requires" blocks.  */
--/* Line 2058 of yacc.c  */
-+
-+/* Line 1676 of yacc.c  */
- #line 1 "TsConfigGrammar.y"
- 
- /** @file
-@@ -67,8 +61,9 @@ extern int tsconfigdebug;
-  */
- 
- 
--/* Line 2058 of yacc.c  */
--#line 72 "TsConfigGrammar.h"
-+
-+/* Line 1676 of yacc.c  */
-+#line 67 "TsConfigGrammar.h"
- 
- /* Tokens.  */
- #ifndef YYTOKENTYPE
-@@ -106,6 +101,7 @@ extern int tsconfigdebug;
- 
- 
- 
-+
- #if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
- typedef int YYSTYPE;
- # define YYSTYPE_IS_TRIVIAL 1
-@@ -114,18 +110,5 @@ typedef int YYSTYPE;
- #endif
- 
- 
--#ifdef YYPARSE_PARAM
--#if defined __STDC__ || defined __cplusplus
--int tsconfigparse (void *YYPARSE_PARAM);
--#else
--int tsconfigparse ();
--#endif
--#else /* ! YYPARSE_PARAM */
--#if defined __STDC__ || defined __cplusplus
--int tsconfigparse (yyscan_t lexer, struct TsConfigHandlers* handlers);
--#else
--int tsconfigparse ();
--#endif
--#endif /* ! YYPARSE_PARAM */
- 
--#endif /* !YY_TSCONFIG_TSCONFIGGRAMMAR_H_INCLUDED  */
-+
-diff --git a/plugins/cacheurl/cacheurl.cc b/plugins/cacheurl/cacheurl.cc
-index 52565fc..d17c732 100644
---- a/plugins/cacheurl/cacheurl.cc
-+++ b/plugins/cacheurl/cacheurl.cc
-@@ -28,8 +28,8 @@
- #include "ts/ts.h"
- #include "ts/remap.h"
- #include "ink_defs.h"
-+#include "ink_memory.h"
- 
--#include <memory>
- #include <string>
- #include <vector>
- 
-@@ -205,7 +205,7 @@ load_config_file(const char *config_file)
-   char buffer[1024];
-   std::string path;
-   TSFile fh;
--  std::auto_ptr<pr_list> prl(new pr_list());
-+  ats_scoped_obj<pr_list> prl(new pr_list());
- 
-   /* locations in a config file line, end of line, split start, split end */
-   char *eol, *spstart, *spend;
-diff --git a/plugins/experimental/Makefile.am b/plugins/experimental/Makefile.am
-index 52fef44..adb6da8 100644
---- a/plugins/experimental/Makefile.am
-+++ b/plugins/experimental/Makefile.am
-@@ -19,6 +19,7 @@ SUBDIRS = \
-  background_fetch \
-  balancer \
-  buffer_upload \
-+ cache_promote \
-  cache_range_requests \
-  channel_stats \
-  collapsed_connection \
-@@ -38,6 +39,7 @@ SUBDIRS = \
-  ssl_cert_loader \
-  sslheaders \
-  stale_while_revalidate \
-+ stream_editor \
-  url_sig \
-  xdebug
- 
-diff --git a/plugins/experimental/cache_promote/Makefile.am b/plugins/experimental/cache_promote/Makefile.am
-new file mode 100644
-index 0000000..8170aed
---- /dev/null
-+++ b/plugins/experimental/cache_promote/Makefile.am
-@@ -0,0 +1,21 @@
-+#  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 $(top_srcdir)/build/plugins.mk
-+
-+pkglib_LTLIBRARIES = cache_promote.la
-+cache_promote_la_SOURCES = cache_promote.cc
-+cache_promote_la_LDFLAGS = $(TS_PLUGIN_LDFLAGS)
-diff --git a/plugins/experimental/cache_promote/README b/plugins/experimental/cache_promote/README
-new file mode 100644
-index 0000000..26d4500
---- /dev/null
-+++ b/plugins/experimental/cache_promote/README
-@@ -0,0 +1,30 @@
-+LRU Design
-+==========
-+
-+This got slightly complex, because I tried to be clever. But the concept is easy, a
-+list and an unordered map keeps the LRU state.
-+
-+
-+                                                    +-----------------------+    +----------------------------------+
-+                                                    |        LRUList        |    |              LRUMap              |
-+                                                    |        -------        |    |              ------              |
-+                                                    |+---------------------+|    |+--------------------------------+|
-++---------------------+   +---------------------+   ||      LRUEntry       <+----+| {LRUHash *, LRUList::iterator} ||
-+|       LRUHash       |   |      LRUEntry       |   |+---------------------+|    |+--------------------------------+|
-+|      --------       |<--+      --------       |<--+|      LRUEntry       <+----+| {LRUHash *, LRUList::iterator} ||
-+|  u_char _hash[20]   |   | <LRUHash, unsigned> |   |+---------------------+|    |+--------------------------------+|
-++---------------------+   +---------------------+   ||      LRUEntry       <+----+| {LRUHash *, LRUList::iterator} ||
-+                            +-----------------+     |+---------------------+|    |+--------------------------------+|
-+                            | first = LRUHash |     |                       |    |                                  |
-+                            |second = unsigned|     |           *           |    |                *                 |
-+                            +-----------------+     |           *           |    |                *                 |
-+                                                    |           *           |    |                *                 |
-+                                                    |                       |    |                                  |
-+                                                    |+---------------------+|    |+--------------------------------+|
-+                                                    ||      LRUEntry       ||    || {LRUHash *, LRUList::iterator} ||
-+                                                    |+---------------------+|    |+--------------------------------+|
-+                                                    +-----------------------+    +----------------------------------+
-+                                                                                     +--------------------------+
-+                                                                                     |    first  = LRUHash*     |
-+                                                                                     |second = LRUList::iterator|
-+                                                                                     +--------------------------+
-diff --git a/plugins/experimental/cache_promote/cache_promote.cc b/plugins/experimental/cache_promote/cache_promote.cc
-new file mode 100644
-index 0000000..c601927
---- /dev/null
-+++ b/plugins/experimental/cache_promote/cache_promote.cc
-@@ -0,0 +1,515 @@
-+/*
-+  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 <stdio.h>
-+#include <string.h>
-+#include <unistd.h>
-+#include <getopt.h>
-+#include <stdlib.h>
-+#include <time.h>
-+#include <openssl/sha.h>
-+
-+#include <string>
-+#include <unordered_map>
-+#include <list>
-+
-+#include "ts/ts.h"
-+#include "ts/remap.h"
-+#include "ts/ink_config.h"
-+
-+
-+static const char *PLUGIN_NAME = "cache_promote";
-+TSCont gNocacheCont;
-+
-+
-+//////////////////////////////////////////////////////////////////////////////////////////////
-+// Note that all options for all policies has to go here. Not particularly pretty...
-+//
-+static const struct option longopt[] = {{const_cast<char *>("policy"), required_argument, NULL, 'p'},
-+                                        // This is for both Chance and LRU (optional) policy
-+                                        {const_cast<char *>("sample"), required_argument, NULL, 's'},
-+                                        // For the LRU policy
-+                                        {const_cast<char *>("buckets"), required_argument, NULL, 'b'},
-+                                        {const_cast<char *>("hits"), required_argument, NULL, 'h'},
-+                                        // EOF
-+                                        {NULL, no_argument, NULL, '\0'}};
-+
-+
-+//////////////////////////////////////////////////////////////////////////////////////////////
-+// Abstract base class for all policies.
-+//
-+class PromotionPolicy
-+{
-+public:
-+  PromotionPolicy() : _sample(0.0)
-+  {
-+    // This doesn't have to be perfect, since this is just chance sampling.
-+    // coverity[dont_call]
-+    srand48((long)time(NULL));
-+  }
-+
-+  void
-+  setSample(char *s)
-+  {
-+    _sample = strtof(s, NULL) / 100.0;
-+  }
-+
-+  float
-+  getSample() const
-+  {
-+    return _sample;
-+  }
-+
-+  bool
-+  doSample() const
-+  {
-+    if (_sample > 0) {
-+      // coverity[dont_call]
-+      double r = drand48();
-+
-+      if (_sample > r) {
-+        TSDebug(PLUGIN_NAME, "checking sampling, is %f > %f? Yes!", _sample, r);
-+      } else {
-+        TSDebug(PLUGIN_NAME, "checking sampling, is %f > %f? No!", _sample, r);
-+        return false;
-+      }
-+    }
-+    return true;
-+  }
-+
-+  virtual ~PromotionPolicy(){};
-+
-+  virtual bool
-+  parseOption(int opt, char *optarg)
-+  {
-+    return false;
-+  }
-+
-+  // These are pure virtual
-+  virtual bool doPromote(TSHttpTxn txnp) = 0;
-+  virtual const char *policyName() const = 0;
-+  virtual void usage() const = 0;
-+
-+private:
-+  float _sample;
-+};
-+
-+
-+//////////////////////////////////////////////////////////////////////////////////////////////
-+// This is the simplest of all policies, just give each request a (small)
-+// percentage chance to be promoted to cache.
-+//
-+class ChancePolicy : public PromotionPolicy
-+{
-+public:
-+  bool doPromote(TSHttpTxn /* txnp ATS_UNUSED */)
-+  {
-+    TSDebug(PLUGIN_NAME, "ChancePolicy::doPromote(%f)", getSample());
-+    return true;
-+  }
-+
-+  void
-+  usage() const
-+  {
-+    TSError("[%s] Usage: @plugin=%s.so @pparam=--policy=chance @pparam=--sample=<x>%%", PLUGIN_NAME, PLUGIN_NAME);
-+  }
-+
-+  const char *
-+  policyName() const
-+  {
-+    return "chance";
-+  }
-+};
-+
-+
-+//////////////////////////////////////////////////////////////////////////////////////////////
-+// The LRU based policy keeps track of <bucket> number of URLs, with a counter for each slot.
-+// Objects are not promoted unless the counter reaches <hits> before it gets evicted. An
-+// optional <chance> parameter can be used to sample hits, this can reduce contention and
-+// churning in the LRU as well.
-+//
-+class LRUHash
-+{
-+  friend struct LRUHashHasher;
-+
-+public:
-+  LRUHash() { TSDebug(PLUGIN_NAME, "In LRUHash()"); }
-+
-+  ~LRUHash() { TSDebug(PLUGIN_NAME, "In ~LRUHash()"); }
-+
-+  LRUHash &operator=(const LRUHash &h)
-+  {
-+    TSDebug(PLUGIN_NAME, "copying an LRUHash object");
-+    memcpy(_hash, h._hash, sizeof(_hash));
-+    return *this;
-+  }
-+
-+  void
-+  init(char *data, int len)
-+  {
-+    SHA_CTX sha;
-+
-+    SHA1_Init(&sha);
-+    SHA1_Update(&sha, data, len);
-+    SHA1_Final(_hash, &sha);
-+  }
-+
-+private:
-+  u_char _hash[SHA_DIGEST_LENGTH];
-+};
-+
-+struct LRUHashHasher {
-+  bool operator()(const LRUHash *s1, const LRUHash *s2) const { return 0 == memcmp(s1->_hash, s2->_hash, sizeof(s2->_hash)); }
-+
-+  size_t operator()(const LRUHash *s) const { return *((size_t *)s->_hash) ^ *((size_t *)(s->_hash + 9)); }
-+};
-+
-+typedef std::pair<LRUHash, unsigned> LRUEntry;
-+typedef std::list<LRUEntry> LRUList;
-+typedef std::unordered_map<const LRUHash *, LRUList::iterator, LRUHashHasher, LRUHashHasher> LRUMap;
-+
-+static LRUEntry NULL_LRU_ENTRY; // Used to create an "empty" new LRUEntry
-+
-+class LRUPolicy : public PromotionPolicy
-+{
-+public:
-+  LRUPolicy() : PromotionPolicy(), _buckets(1000), _hits(10), _lock(TSMutexCreate()) {}
-+
-+  ~LRUPolicy()
-+  {
-+    TSDebug(PLUGIN_NAME, "deleting LRUPolicy object");
-+    TSMutexLock(_lock);
-+
-+    _map.clear();
-+    _list.clear();
-+    _freelist.clear();
-+
-+    TSMutexUnlock(_lock);
-+    TSMutexDestroy(_lock);
-+  }
-+
-+  bool
-+  parseOption(int opt, char *optarg)
-+  {
-+    switch (opt) {
-+    case 'b':
-+      _buckets = static_cast<unsigned>(strtol(optarg, NULL, 10));
-+      break;
-+    case 'h':
-+      _hits = static_cast<unsigned>(strtol(optarg, NULL, 10));
-+      break;
-+    default:
-+      // All other options are unsupported for this policy
-+      return false;
-+    }
-+
-+    // This doesn't have to be perfect, since this is just chance sampling.
-+    // coverity[dont_call]
-+    srand48((long)time(NULL) ^ (long)getpid() ^ (long)getppid());
-+
-+    return true;
-+  }
-+
-+  bool
-+  doPromote(TSHttpTxn txnp)
-+  {
-+    LRUHash hash;
-+    LRUMap::iterator map_it;
-+    int url_len = 0;
-+    char *url = TSHttpTxnEffectiveUrlStringGet(txnp, &url_len);
-+    bool ret = false;
-+
-+    // Generally shouldn't happen ...
-+    if (!url) {
-+      return false;
-+    }
-+
-+    TSDebug(PLUGIN_NAME, "LRUPolicy::doPromote(%.*s ...)", url_len > 30 ? 30 : url_len, url);
-+    hash.init(url, url_len);
-+    TSfree(url);
-+
-+    // We have to hold the lock across all list and hash access / updates
-+    TSMutexLock(_lock);
-+
-+    map_it = _map.find(&hash);
-+    if (_map.end() != map_it) {
-+      // We have an entry in the LRU
-+      if (++(map_it->second->second) >= _hits) {
-+        // Promoted! Cleanup the LRU, and signal success. Save the promoted entry on the freelist.
-+        TSDebug(PLUGIN_NAME, "saving the LRUEntry to the freelist");
-+        _freelist.splice(_freelist.begin(), _list, map_it->second);
-+        _map.erase(map_it->first);
-+        ret = true;
-+      } else {
-+        // It's still not promoted, make sure it's moved to the front of the list
-+        TSDebug(PLUGIN_NAME, "still not promoted, got %d hits so far", map_it->second->second);
-+        _list.splice(_list.begin(), _list, map_it->second);
-+      }
-+    } else {
-+      // New LRU entry for the URL, try to repurpose the list entry as much as possible
-+      if (_list.size() >= _buckets) {
-+        TSDebug(PLUGIN_NAME, "repurposing last LRUHash entry");
-+        _list.splice(_list.begin(), _list, --_list.end());
-+        _map.erase(&(_list.begin()->first));
-+      } else if (_freelist.size() > 0) {
-+        TSDebug(PLUGIN_NAME, "reusing LRUEntry from freelist");
-+        _list.splice(_list.begin(), _freelist, _freelist.begin());
-+      } else {
-+        TSDebug(PLUGIN_NAME, "creating new LRUEntry");
-+        _list.push_front(NULL_LRU_ENTRY);
-+      }
-+      // Update the "new" LRUEntry and add it to the hash
-+      _list.begin()->first = hash;
-+      _list.begin()->second = 1;
-+      _map[&(_list.begin()->first)] = _list.begin();
-+    }
-+
-+    TSMutexUnlock(_lock);
-+
-+    return ret;
-+  }
-+
-+  void
-+  usage() const
-+  {
-+    TSError("[%s] Usage: @plugin=%s.so @pparam=--policy=lru @pparam=--buckets=<n> --hits=<m> --sample=<x>", PLUGIN_NAME,
-+            PLUGIN_NAME);
-+  }
-+
-+  const char *
-+  policyName() const
-+  {
-+    return "LRU";
-+  }
-+
-+private:
-+  unsigned _buckets;
-+  unsigned _hits;
-+  // For the LRU
-+  TSMutex _lock;
-+  LRUMap _map;
-+  LRUList _list, _freelist;
-+};
-+
-+
-+//////////////////////////////////////////////////////////////////////////////////////////////
-+// This holds the configuration for a remap rule, as well as parses the configurations.
-+//
-+class PromotionConfig
-+{
-+public:
-+  PromotionConfig() : _policy(NULL) {}
-+
-+  ~PromotionConfig() { delete _policy; }
-+
-+  PromotionPolicy *
-+  getPolicy() const
-+  {
-+    return _policy;
-+  }
-+
-+  // Parse the command line arguments to the plugin, and instantiate the appropriate policy
-+  bool
-+  factory(int argc, char *argv[])
-+  {
-+    optind = 0;
-+    while (true) {
-+      int opt = getopt_long(argc, (char *const *)argv, "psbh", longopt, NULL);
-+
-+      if (opt == -1) {
-+        break;
-+      } else if (opt == 'p') {
-+        if (0 == strncasecmp(optarg, "chance", 6)) {
-+          _policy = new ChancePolicy();
-+        } else if (0 == strncasecmp(optarg, "lru", 3)) {
-+          _policy = new LRUPolicy();
-+        } else {
-+          TSError("[%s] Unknown policy --policy=%s", PLUGIN_NAME, optarg);
-+          return false;
-+        }
-+        if (_policy) {
-+          TSDebug(PLUGIN_NAME, "created remap with cache promotion policy = %s", _policy->policyName());
-+        }
-+      } else {
-+        if (_policy) {
-+          // The --sample (-s) option is allowed for all configs, but only after --policy is specified.
-+          if (opt == 's') {
-+            _policy->setSample(optarg);
-+          } else {
-+            if (!_policy->parseOption(opt, optarg)) {
-+              TSError("[%s] The specified policy (%s) does not support the -%c option", PLUGIN_NAME, _policy->policyName(), opt);
-+              delete _policy;
-+              _policy = NULL;
-+              return false;
-+            }
-+          }
-+        } else {
-+          TSError("[%s] The --policy=<n> parameter must come first on the remap configuration", PLUGIN_NAME);
-+          return false;
-+        }
-+      }
-+    }
-+
-+    return true;
-+  }
-+
-+private:
-+  PromotionPolicy *_policy;
-+};
-+
-+
-+//////////////////////////////////////////////////////////////////////////////////////////////
-+// Little helper continuation, to turn off writing to the cache. ToDo: when we have proper
-+// APIs to make requests / responses, we can remove this completely.
-+static int
-+cont_nocache_response(TSCont contp, TSEvent event, void *edata)
-+{
-+  TSHttpTxn txnp = static_cast<TSHttpTxn>(edata);
-+
-+  TSHttpTxnServerRespNoStoreSet(txnp, 1);
-+  // Reenable and continue with the state machine.
-+  TSHttpTxnReenable(txnp, TS_EVENT_HTTP_CONTINUE);
-+  return 0;
-+}
-+
-+//////////////////////////////////////////////////////////////////////////////////////////////
-+// Main "plugin", a TXN hook in the TS_HTTP_READ_CACHE_HDR_HOOK. Unless the policy allows
-+// caching, we will turn off the cache from here on for the TXN.
-+//
-+// NOTE: This is not optimal, the goal was to handle this before we lock the URL in the
-+// cache. However, that does not work. Hence, for now, we also schedule the continuation
-+// for READ_RESPONSE_HDR such that we can turn off  the actual cache write.
-+//
-+static int
-+cont_handle_policy(TSCont contp, TSEvent event, void *edata)
-+{
-+  TSHttpTxn txnp = static_cast<TSHttpTxn>(edata);
-+  PromotionConfig *config = static_cast<PromotionConfig *>(TSContDataGet(contp));
-+
-+  switch (event) {
-+  // Main HOOK
-+  case TS_EVENT_HTTP_CACHE_LOOKUP_COMPLETE:
-+    if (TS_SUCCESS != TSHttpIsInternalRequest(txnp)) {
-+      int obj_status;
-+
-+      if (TS_ERROR != TSHttpTxnCacheLookupStatusGet(txnp, &obj_status)) {
-+        switch (obj_status) {
-+        case TS_CACHE_LOOKUP_MISS:
-+        case TS_CACHE_LOOKUP_SKIPPED:
-+          if (config->getPolicy()->doSample() && config->getPolicy()->doPromote(txnp)) {
-+            TSDebug(PLUGIN_NAME, "cache-status is %d, and leaving cache on (promoted)", obj_status);
-+          } else {
-+            TSDebug(PLUGIN_NAME, "cache-status is %d, and turning off the cache (not promoted)", obj_status);
-+            TSHttpTxnHookAdd(txnp, TS_HTTP_READ_RESPONSE_HDR_HOOK, gNocacheCont);
-+          }
-+          break;
-+        default:
-+          // Do nothing, just let it handle the lookup.
-+          TSDebug(PLUGIN_NAME, "cache-status is %d (hit), nothing to do", obj_status);
-+          break;
-+        }
-+      }
-+    } else {
-+      TSDebug(PLUGIN_NAME, "Request is an internal (plugin) request, implicitly promoted");
-+    }
-+    break;
-+
-+  // Should not happen
-+  default:
-+    TSDebug(PLUGIN_NAME, "Unhandled event %d", (int)event);
-+    break;
-+  }
-+
-+  // Reenable and continue with the state machine.
-+  TSHttpTxnReenable(txnp, TS_EVENT_HTTP_CONTINUE);
-+  return 0;
-+}
-+
-+
-+//////////////////////////////////////////////////////////////////////////////////////////////
-+// Initialize the plugin as a remap plugin.
-+//
-+TSReturnCode
-+TSRemapInit(TSRemapInterface *api_info, char *errbuf, int errbuf_size)
-+{
-+  if (api_info->size < sizeof(TSRemapInterface)) {
-+    strncpy(errbuf, "[tsremap_init] - Incorrect size of TSRemapInterface structure", errbuf_size - 1);
-+    return TS_ERROR;
-+  }
-+
-+  if (api_info->tsremap_version < TSREMAP_VERSION) {
-+    snprintf(errbuf, errbuf_size - 1, "[tsremap_init] - Incorrect API version %ld.%ld", api_info->tsremap_version >> 16,
-+             (api_info->tsremap_version & 0xffff));
-+    return TS_ERROR;
-+  }
-+
-+  gNocacheCont = TSContCreate(cont_nocache_response, NULL);
-+
-+  TSDebug(PLUGIN_NAME, "remap plugin is successfully initialized");
-+  return TS_SUCCESS; /* success */
-+}
-+
-+
-+TSReturnCode
-+TSRemapNewInstance(int argc, char *argv[], void **ih, char * /* errbuf */, int /* errbuf_size */)
-+{
-+  PromotionConfig *config = new PromotionConfig;
-+
-+  --argc;
-+  ++argv;
-+  if (config->factory(argc, argv)) {
-+    TSCont contp = TSContCreate(cont_handle_policy, NULL);
-+
-+    TSContDataSet(contp, static_cast<void *>(config));
-+    *ih = static_cast<void *>(contp);
-+
-+    return TS_SUCCESS;
-+  } else {
-+    delete config;
-+    return TS_ERROR;
-+  }
-+}
-+
-+void
-+TSRemapDeleteInstance(void *ih)
-+{
-+  TSCont contp = static_cast<TSCont>(ih);
-+  PromotionConfig *config = static_cast<PromotionConfig *>(TSContDataGet(contp));
-+
-+  delete config;
-+  TSContDestroy(contp);
-+}
-+
-+
-+//////////////////////////////////////////////////////////////////////////////////////////////
-+// Schedule the cache-read continuation for this remap rule.
-+//
-+TSRemapStatus
-+TSRemapDoRemap(void *ih, TSHttpTxn rh, TSRemapRequestInfo * /* ATS_UNUSED rri */)
-+{
-+  if (NULL == ih) {
-+    TSDebug(PLUGIN_NAME, "No promotion rules configured, this is probably a plugin bug");
-+  } else {
-+    TSCont contp = static_cast<TSCont>(ih);
-+
-+    TSDebug(PLUGIN_NAME, "scheduling a TS_HTTP_CACHE_LOOKUP_COMPLETE_HOOK hook");
-+    TSHttpTxnHookAdd(rh, TS_HTTP_CACHE_LOOKUP_COMPLETE_HOOK, contp);
-+  }
-+
-+  return TSREMAP_NO_REMAP;
-+}
-diff --git a/plugins/experimental/money_trace/Makefile.am b/plugins/experimental/money_trace/Makefile.am
-new file mode 100644
-index 0000000..d63485f
---- /dev/null
-+++ b/plugins/experimental/money_trace/Makefile.am
-@@ -0,0 +1,22 @@
-+#  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 $(top_srcdir)/build/plugins.mk
-+
-+pkglib_LTLIBRARIES = money_trace.la
-+money_trace_la_SOURCES = money_trace.cc 
-+money_trace_la_LDFLAGS = $(TS_PLUGIN_LDFLAGS)
-+
-diff --git a/plugins/experimental/money_trace/README b/plugins/experimental/money_trace/README
-new file mode 100644
-index 0000000..a495897
---- /dev/null
-+++ b/plugins/experimental/money_trace/README
-@@ -0,0 +1,8 @@
-+
-+Author: John J. Rushford, John_Rushford@cable.comcast.com
-+
-+Money trace plugin 
-+  This is a remap plugin used to add and update a "X-MoneyTrace" used to trace and monitor http transactions in support system logs.
-+
-+See the documentation on this header at https://github.com/Comcast/money/wiki.
-+
-diff --git a/plugins/experimental/money_trace/money_trace.cc b/plugins/experimental/money_trace/money_trace.cc
-new file mode 100644
-index 0000000..adb8980
---- /dev/null
-+++ b/plugins/experimental/money_trace/money_trace.cc
-@@ -0,0 +1,365 @@
-+/*
-+ * 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.
-+ */
-+
-+/*
-+ * This plugin looks for range requests and then creates a new
-+ * cache key url so that each individual range requests is written
-+ * to the cache as a individual object so that subsequent range
-+ * requests are read accross different disk drives reducing I/O
-+ * wait and load averages when there are large numbers of range
-+ * requests.
-+ */
-+
-+#include <iostream>
-+#include <sstream>
-+#include <stdio.h>
-+#include <string.h>
-+#include "ts/ts.h"
-+#include "ts/remap.h"
-+
-+#include "money_trace.h"
-+
-+/**
-+ * Allocate transaction data structure.
-+ */
-+static struct txndata *
-+allocTransactionData()
-+{
-+  LOG_DEBUG("allocating transaction state data.");
-+  struct txndata *txn_data = (struct txndata *)TSmalloc(sizeof(struct txndata));
-+  txn_data->client_request_mt_header = NULL;
-+  txn_data->new_span_mt_header = NULL;
-+  return txn_data;
-+}
-+
-+/**
-+ * free any previously allocated transaction data.
-+ */
-+static void
-+freeTransactionData(struct txndata *txn_data)
-+{
-+  LOG_DEBUG("de-allocating transaction state data.");
-+  if (txn_data->client_request_mt_header != NULL) {
-+    LOG_DEBUG("freeing txn_data->client_request_mt_header");
-+    TSfree(txn_data->client_request_mt_header);
-+  }
-+  if (txn_data->new_span_mt_header != NULL) {
-+    LOG_DEBUG("freeing txn_data->new_span_mt_header.");
-+    TSfree(txn_data->new_span_mt_header);
-+  }
-+  if (txn_data != NULL) {
-+    LOG_DEBUG("freeing txn_data.");
-+    TSfree(txn_data);
-+  }
-+}
-+
-+/**
-+ * The TS_EVENT_HTTP_CACHE_LOOKUP_COMPLETE event callback.
-+ * 
-+ * If there is a cache hit only schedule a TS_HTTP_SEND_RESPONSE_HDR_HOOK
-+ * continuation to send back the money trace header in the response to the
-+ * client.
-+ *
-+ * If there is a cache miss, a new money trace header is created and a
-+ * TS_HTTP_SEND_REQUES_HDR_HOOK continuation is scheduled to add the
-+ * new mon

<TRUNCATED>


[9/9] incubator-trafficcontrol git commit: Added license header to documentation files that required one,

Posted by da...@apache.org.
Added license header to documentation files that required one,

(cherry picked from commit 97a81b196add4cab3553e6d0757e083f3d277dd5)


Project: http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/commit/1d9d13f3
Tree: http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/tree/1d9d13f3
Diff: http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/diff/1d9d13f3

Branch: refs/heads/1.8.x
Commit: 1d9d13f36bb51ebc1a2ac01bb7b461abef2537f6
Parents: 63dc2fb
Author: Chris Lemmons <Ch...@comcast.com>
Authored: Thu Jan 12 15:09:48 2017 -0700
Committer: Dan Kirkwood <da...@gmail.com>
Committed: Fri Jan 13 11:46:09 2017 -0700

----------------------------------------------------------------------
 docs/Makefile            | 17 +++++++++++++++++
 docs/source/glossary.rst | 15 +++++++++++++++
 2 files changed, 32 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/1d9d13f3/docs/Makefile
----------------------------------------------------------------------
diff --git a/docs/Makefile b/docs/Makefile
index dd463af..61e97ed 100644
--- a/docs/Makefile
+++ b/docs/Makefile
@@ -1,5 +1,22 @@
 # Makefile for Sphinx documentation
 #
+# 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.
+#
 
 # You can set these variables from the command line.
 SPHINXOPTS    = 

http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/1d9d13f3/docs/source/glossary.rst
----------------------------------------------------------------------
diff --git a/docs/source/glossary.rst b/docs/source/glossary.rst
index b32bea9..a932579 100644
--- a/docs/source/glossary.rst
+++ b/docs/source/glossary.rst
@@ -1,3 +1,18 @@
+..
+..
+.. Licensed 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.
+..
+
 .. _glossary:
 
 Glossary


[6/9] incubator-trafficcontrol git commit: Removed ATS patches.

Posted by da...@apache.org.
Removed ATS patches.

(cherry picked from commit 0d874bf16285dac91744283e918b7835f2442d51)


Project: http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/commit/927e4892
Tree: http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/tree/927e4892
Diff: http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/diff/927e4892

Branch: refs/heads/1.8.x
Commit: 927e4892b081b06148822061d054706875f05678
Parents: 37325da
Author: Chris Lemmons <Ch...@comcast.com>
Authored: Thu Jan 12 15:04:03 2017 -0700
Committer: Dan Kirkwood <da...@gmail.com>
Committed: Fri Jan 13 11:46:09 2017 -0700

----------------------------------------------------------------------
 traffic_server/README.md                        |    2 +-
 .../patches/trafficserver-5.2.0-791ddc4.patch   | 4315 -----------
 .../patches/trafficserver-5.3.2-089d585.diff    | 5157 -------------
 .../patches/trafficserver-5.3.2-f914e70.diff    | 7230 ------------------
 4 files changed, 1 insertion(+), 16703 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/927e4892/traffic_server/README.md
----------------------------------------------------------------------
diff --git a/traffic_server/README.md b/traffic_server/README.md
index 7fc14bc..9c52fba 100644
--- a/traffic_server/README.md
+++ b/traffic_server/README.md
@@ -1,4 +1,4 @@
 You can download the trafficserver 5.2.0 source here:
 http://archive.apache.org/dist/trafficserver/trafficserver-5.2.0.tar.bz2
 
-Then with the patch and spec file you can build an RPM for trafficserver and astats_over_http.
+Then with the spec file you can build an RPM for trafficserver and astats_over_http.


[5/9] incubator-trafficcontrol git commit: Removed ATS patches.

Posted by da...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/927e4892/traffic_server/patches/trafficserver-5.2.0-791ddc4.patch
----------------------------------------------------------------------
diff --git a/traffic_server/patches/trafficserver-5.2.0-791ddc4.patch b/traffic_server/patches/trafficserver-5.2.0-791ddc4.patch
deleted file mode 100644
index 68b4673..0000000
--- a/traffic_server/patches/trafficserver-5.2.0-791ddc4.patch
+++ /dev/null
@@ -1,4315 +0,0 @@
-diff --git a/CHANGES b/CHANGES
-index b4019fe..6fa1115 100644
---- a/CHANGES
-+++ b/CHANGES
-@@ -1,6 +1,13 @@
-                                                          -*- coding: utf-8 -*-
- Changes with Apache Traffic Server 5.2.0
- 
-+  *) [TS-3504] Only read "proxy.config.cache.ram_cache.use_seen_filter" once.
-+    Do not set up a callback.
-+
-+  *) [TS-3304] Add NULL check to ink_inet_addr() input.
-+
-+  *) [TS-3349] Add DscpSet API's.
-+
-   *) [TS-3280] Segfault in new freelist bulk freeing (in debug mode).
- 
-   *) [TS-3276] Fix cache backwards compatibility issue.
-diff --git a/doc/reference/api/TSHttpOverridableConfig.en.rst b/doc/reference/api/TSHttpOverridableConfig.en.rst
-index 837df9f..009447b 100644
---- a/doc/reference/api/TSHttpOverridableConfig.en.rst
-+++ b/doc/reference/api/TSHttpOverridableConfig.en.rst
-@@ -100,6 +100,7 @@ The following configurations (from ``records.config``) are overridable: ::
-     proxy.config.http.keep_alive_no_activity_timeout_out
-     proxy.config.http.transaction_no_activity_timeout_in
-     proxy.config.http.transaction_no_activity_timeout_out
-+    proxy.config.http.transaction_active_timeout_in
-     proxy.config.http.transaction_active_timeout_out
-     proxy.config.http.origin_max_connections
-     proxy.config.http.connect_attempts_max_retries
-@@ -136,7 +137,6 @@ The following configurations (from ``records.config``) are overridable: ::
-     proxy.config.http.cache.range.write
-     proxy.config.http.global_user_agent_header
- 
--
- Examples
- ========
- 
-diff --git a/doc/reference/api/TSHttpTxnClientPacketDscpSet.en.rst b/doc/reference/api/TSHttpTxnClientPacketDscpSet.en.rst
-new file mode 100644
-index 0000000..eb3368c
---- /dev/null
-+++ b/doc/reference/api/TSHttpTxnClientPacketDscpSet.en.rst
-@@ -0,0 +1,45 @@
-+.. 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.
-+
-+
-+TSHttpTxnClientPacketDscpSet
-+============================
-+
-+Change packet DSCP for the client side connection.
-+
-+
-+Synopsis
-+--------
-+
-+`#include <ts/ts.h>`
-+
-+.. c:function:: TSReturnCode TSHttpTxnClientPacketDscpSet(TSHttpTxn txnp, int dscp)
-+
-+
-+Description
-+-----------
-+
-+.. note::
-+
-+   The change takes effect immediately
-+
-+
-+See Also
-+--------
-+
-+`Traffic Shaping`_
-+
-+.. _Traffic Shaping:
-+                 https://cwiki.apache.org/confluence/display/TS/Traffic+Shaping
-diff --git a/doc/reference/api/TSHttpTxnServerPacketDscpSet.en.rst b/doc/reference/api/TSHttpTxnServerPacketDscpSet.en.rst
-new file mode 100644
-index 0000000..a3f19fe
---- /dev/null
-+++ b/doc/reference/api/TSHttpTxnServerPacketDscpSet.en.rst
-@@ -0,0 +1,47 @@
-+.. 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.
-+
-+
-+TSHttpTxnServerPacketDscpSet
-+============================
-+
-+Change packet DSCP for the server side connection.
-+
-+
-+Synopsis
-+--------
-+
-+`#include <ts/ts.h>`
-+
-+.. c:function:: TSReturnCode TSHttpTxnServerPacketDscpSet(TSHttpTxn txnp, int dscp)
-+
-+
-+Description
-+-----------
-+
-+.. note::
-+
-+   The change takes effect immediately, if no OS connection has been
-+   made, then this sets the mark that will be used IF an OS connection
-+   is established
-+
-+
-+See Also
-+--------
-+
-+`Traffic Shaping`_
-+
-+.. _Traffic Shaping:
-+                 https://cwiki.apache.org/confluence/display/TS/Traffic+Shaping
-diff --git a/iocore/cache/Cache.cc b/iocore/cache/Cache.cc
-index 9aece93..93777fd 100644
---- a/iocore/cache/Cache.cc
-+++ b/iocore/cache/Cache.cc
-@@ -2185,7 +2185,7 @@ CacheProcessor::mark_storage_offline( CacheDisk* d ///< Target disk
-     Warning("All storage devices offline, cache disabled");
-     CacheProcessor::cache_ready = 0;
-   } else { // check cache types specifically
--    if (theCache && !theCache->hosttable->gen_host_rec.vol_hash_table) {
-+    if (theCache && !theCache->getHosttable(__func__)->gen_host_rec.vol_hash_table) {
-       unsigned int caches_ready = 0;
-       caches_ready = caches_ready | (1 << CACHE_FRAG_TYPE_HTTP);
-       caches_ready = caches_ready | (1 << CACHE_FRAG_TYPE_NONE);
-@@ -2193,7 +2193,7 @@ CacheProcessor::mark_storage_offline( CacheDisk* d ///< Target disk
-       CacheProcessor::cache_ready &= caches_ready;
-       Warning("all volumes for http cache are corrupt, http cache disabled");
-     }
--    if (theStreamCache && !theStreamCache->hosttable->gen_host_rec.vol_hash_table) {
-+    if (theStreamCache && !theStreamCache->getHosttable(__func__)->gen_host_rec.vol_hash_table) {
-       unsigned int caches_ready = 0;
-       caches_ready = caches_ready | (1 << CACHE_FRAG_TYPE_RTSP);
-       caches_ready = ~caches_ready;
-@@ -3368,9 +3368,10 @@ create_volume(int volume_number, off_t size_in_blocks, int scheme, CacheVol *cp)
- void
- rebuild_host_table(Cache *cache)
- {
--  build_vol_hash_table(&cache->hosttable->gen_host_rec);
--  if (cache->hosttable->m_numEntries != 0) {
--    CacheHostMatcher *hm = cache->hosttable->getHostMatcher();
-+  CacheHostTable* hosttable = cache->getHosttable(__func__);
-+  build_vol_hash_table(&hosttable->gen_host_rec);
-+  if (hosttable->m_numEntries != 0) {
-+    CacheHostMatcher *hm = hosttable->getHostMatcher();
-     CacheHostRecord *h_rec = hm->getDataArray();
-     int h_rec_len = hm->getNumElements();
-     int i;
-@@ -3385,8 +3386,9 @@ Vol *
- Cache::key_to_vol(CacheKey *key, char const* hostname, int host_len)
- {
-   uint32_t h = (key->slice32(2) >> DIR_TAG_WIDTH) % VOL_HASH_TABLE_SIZE;
-+  CacheHostTable* hosttable = getHosttable(__func__);
-   unsigned short *hash_table = hosttable->gen_host_rec.vol_hash_table;
--  CacheHostRecord *host_rec = &hosttable->gen_host_rec;
-+  CacheHostRecord *host_rec = &(hosttable->gen_host_rec);
- 
-   if (hosttable->m_numEntries > 0 && host_len) {
-     CacheHostResult res;
-@@ -3394,21 +3396,13 @@ Cache::key_to_vol(CacheKey *key, char const* hostname, int host_len)
-     if (res.record) {
-       unsigned short *host_hash_table = res.record->vol_hash_table;
-       if (host_hash_table) {
--        if (is_debug_tag_set("cache_hosting")) {
--          char format_str[50];
--          snprintf(format_str, sizeof(format_str), "Volume: %%xd for host: %%.%ds", host_len);
--          Debug("cache_hosting", format_str, res.record, hostname);
--        }
-+        Debug("cache_hosting", "Volume: %p for host: %.*s", res.record, host_len, hostname);
-         return res.record->vols[host_hash_table[h]];
-       }
-     }
-   }
-   if (hash_table) {
--    if (is_debug_tag_set("cache_hosting")) {
--      char format_str[50];
--      snprintf(format_str, sizeof(format_str), "Generic volume: %%xd for host: %%.%ds", host_len);
--      Debug("cache_hosting", format_str, host_rec, hostname);
--    }
-+    Debug("cache_hosting", "Generic volume: %p for host: %.*s", host_rec, host_len, hostname);
-     return host_rec->vols[hash_table[h]];
-   } else
-     return host_rec->vols[0];
-@@ -3494,7 +3488,7 @@ ink_cache_init(ModuleVersion v)
-   REC_EstablishStaticConfigInt32(cache_config_ram_cache_algorithm, "proxy.config.cache.ram_cache.algorithm");
-   REC_EstablishStaticConfigInt32(cache_config_ram_cache_compress, "proxy.config.cache.ram_cache.compress");
-   REC_EstablishStaticConfigInt32(cache_config_ram_cache_compress_percent, "proxy.config.cache.ram_cache.compress_percent");
--  REC_EstablishStaticConfigInt32(cache_config_ram_cache_use_seen_filter, "proxy.config.cache.ram_cache.use_seen_filter");
-+  REC_ReadConfigInt32(cache_config_ram_cache_use_seen_filter, "proxy.config.cache.ram_cache.use_seen_filter");
- 
-   REC_EstablishStaticConfigInt32(cache_config_http_max_alts, "proxy.config.cache.limits.http.max_alts");
-   Debug("cache_init", "proxy.config.cache.limits.http.max_alts = %d", cache_config_http_max_alts);
-diff --git a/iocore/cache/CacheVol.cc b/iocore/cache/CacheVol.cc
-index 7acbd95..cd5b82a 100644
---- a/iocore/cache/CacheVol.cc
-+++ b/iocore/cache/CacheVol.cc
-@@ -58,10 +58,11 @@ CacheVC::scanVol(int /* event ATS_UNUSED */, Event * /* e ATS_UNUSED */)
-   Debug("cache_scan_truss", "inside %p:scanVol", this);
-   if (_action.cancelled)
-     return free_CacheVC(this);
--  CacheHostRecord *rec = &theCache->hosttable->gen_host_rec;
-+  CacheHostTable* hosttable = theCache->getHosttable(__func__);
-+  CacheHostRecord *rec = &hosttable->gen_host_rec;
-   if (host_len) {
-     CacheHostResult res;
--    theCache->hosttable->Match(hostname, host_len, &res);
-+    hosttable->Match(hostname, host_len, &res);
-     if (res.record)
-       rec = res.record;
-   }
-diff --git a/iocore/cache/P_CacheHosting.h b/iocore/cache/P_CacheHosting.h
-index ce376cc..1ed306c 100644
---- a/iocore/cache/P_CacheHosting.h
-+++ b/iocore/cache/P_CacheHosting.h
-@@ -147,7 +147,8 @@ struct CacheHostTableConfig: public Continuation
-     (void) e;
-     (void) event;
-     CacheHostTable *t = new CacheHostTable((*ppt)->cache, (*ppt)->type);
--    CacheHostTable *old = (CacheHostTable *) ink_atomic_swap(&t, *ppt);
-+    CacheHostTable *old = (CacheHostTable *) ink_atomic_swap(ppt, t);
-+    Debug("cache_hosting", "swapped: old=%p, new=%p", old, t);
-     new_Deleter(old, CACHE_MEM_FREE_TIMEOUT);
-     return EVENT_DONE;
-   }
-diff --git a/iocore/cache/P_CacheInternal.h b/iocore/cache/P_CacheInternal.h
-index 57c5b0b..7db2436 100644
---- a/iocore/cache/P_CacheInternal.h
-+++ b/iocore/cache/P_CacheInternal.h
-@@ -1065,6 +1065,10 @@ struct Cache
-     : cache_read_done(0), total_good_nvol(0), total_nvol(0), ready(CACHE_INITIALIZING), cache_size(0),  // in store block size
-       hosttable(NULL), total_initialized_vol(0), scheme(CACHE_NONE_TYPE)
-     { }
-+  CacheHostTable* getHosttable(const char* callfunc) {
-+    Debug("cache_hosting", "getHosttable() from: %s", callfunc);
-+    return hosttable;
-+  }
- };
- 
- extern Cache *theCache;
-diff --git a/iocore/net/UnixConnection.cc b/iocore/net/UnixConnection.cc
-index 375ae98..9ea3c8a 100644
---- a/iocore/net/UnixConnection.cc
-+++ b/iocore/net/UnixConnection.cc
-@@ -386,7 +386,11 @@ Connection::apply_options(NetVCOptions const& opt)
- 
- #if TS_HAS_IP_TOS
-   uint32_t tos = opt.packet_tos;
--  safe_setsockopt(fd, IPPROTO_IP, IP_TOS, reinterpret_cast<char *>(&tos), sizeof(uint32_t));
-+  if (addr.isIp4()) {
-+    safe_setsockopt(fd, IPPROTO_IP, IP_TOS, reinterpret_cast<char *>(&tos), sizeof(uint32_t));
-+  } else if (addr.isIp6()) {
-+    safe_setsockopt(fd, IPPROTO_IPV6, IPV6_TCLASS, reinterpret_cast<char *>(&tos), sizeof(uint32_t));
-+  }
- #endif
- 
- }
-diff --git a/iocore/net/UnixNetAccept.cc b/iocore/net/UnixNetAccept.cc
-index 5ba79fc..d10f74f 100644
---- a/iocore/net/UnixNetAccept.cc
-+++ b/iocore/net/UnixNetAccept.cc
-@@ -275,18 +275,6 @@ NetAccept::do_blocking_accept(EThread * t)
-       return -1;
-     }
- 
--#if TS_HAS_SO_MARK
--      if (packet_mark != 0) {
--        safe_setsockopt(con.fd, SOL_SOCKET, SO_MARK, reinterpret_cast<char *>(&packet_mark), sizeof(uint32_t));
--      }
--#endif
--
--#if TS_HAS_IP_TOS
--      if (packet_tos != 0) {
--        safe_setsockopt(con.fd, IPPROTO_IP, IP_TOS, reinterpret_cast<char *>(&packet_tos), sizeof(uint32_t));
--      }
--#endif
--
-     // Use 'NULL' to Bypass thread allocator
-     vc = (UnixNetVConnection *)this->getNetProcessor()->allocate_vc(NULL);
-     if (!vc) {
-@@ -294,6 +282,9 @@ NetAccept::do_blocking_accept(EThread * t)
-       return -1;
-     }
-     vc->con = con;
-+    vc->options.packet_mark = packet_mark;
-+    vc->options.packet_tos = packet_tos;
-+    vc->apply_options();
-     vc->from_accept_thread = true;
-     vc->id = net_next_connection_number();
-     alloc_cache = NULL;
-@@ -412,17 +403,6 @@ NetAccept::acceptFastEvent(int event, void *ep)
-         safe_setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, SOCKOPT_ON, sizeof(int));
-         Debug("socket", "::acceptFastEvent: setsockopt() SO_KEEPALIVE on socket");
-       }
--#if TS_HAS_SO_MARK
--      if (packet_mark != 0) {
--        safe_setsockopt(fd, SOL_SOCKET, SO_MARK, reinterpret_cast<char *>(&packet_mark), sizeof(uint32_t));
--      }
--#endif
--
--#if TS_HAS_IP_TOS
--      if (packet_tos != 0) {
--        safe_setsockopt(fd, IPPROTO_IP, IP_TOS, reinterpret_cast<char *>(&packet_tos), sizeof(uint32_t));
--      }
--#endif
-       do {
-         res = safe_nonblocking(fd);
-       } while (res < 0 && (errno == EAGAIN || errno == EINTR));
-@@ -435,6 +415,9 @@ NetAccept::acceptFastEvent(int event, void *ep)
- 
-       vc->con = con;
- 
-+      vc->options.packet_mark = packet_mark;
-+      vc->options.packet_tos = packet_tos;
-+      vc->apply_options();
-     } else {
-       res = fd;
-     }
-diff --git a/lib/ts/ConsistentHash.cc b/lib/ts/ConsistentHash.cc
-index e39edbd..0e33b0c 100644
---- a/lib/ts/ConsistentHash.cc
-+++ b/lib/ts/ConsistentHash.cc
-@@ -68,13 +68,19 @@ ATSConsistentHash::insert(ATSConsistentHashNode * node, float weight, ATSHash64
- }
- 
- ATSConsistentHashNode *
--ATSConsistentHash::lookup(const char *url, ATSConsistentHashIter *i, bool *w, ATSHash64 *h)
-+ATSConsistentHash::lookup(const char *url, size_t url_len, ATSConsistentHashIter *i, bool *w, ATSHash64 *h)
- {
-   uint64_t url_hash;
-   ATSConsistentHashIter NodeMapIterUp, *iter;
-   ATSHash64 *thash;
-   bool *wptr, wrapped = false;
- 
-+  if (url_len <= 0 && url) {
-+    url_len = strlen(url);
-+  } else {
-+    url_len = 0;
-+  }
-+
-   if (h) {
-     thash = h;
-   } else if (hash) {
-@@ -96,7 +102,7 @@ ATSConsistentHash::lookup(const char *url, ATSConsistentHashIter *i, bool *w, AT
-   }
- 
-   if (url) {
--    thash->update(url, strlen(url));
-+    thash->update(url, url_len);
-     thash->final();
-     url_hash = thash->get();
-     thash->clear();
-@@ -125,13 +131,19 @@ ATSConsistentHash::lookup(const char *url, ATSConsistentHashIter *i, bool *w, AT
- }
- 
- ATSConsistentHashNode *
--ATSConsistentHash::lookup_available(const char *url, ATSConsistentHashIter *i, bool *w, ATSHash64 *h)
-+ATSConsistentHash::lookup_available(const char *url, size_t url_len, ATSConsistentHashIter *i, bool *w, ATSHash64 *h)
- {
-   uint64_t url_hash;
-   ATSConsistentHashIter NodeMapIterUp, *iter;
-   ATSHash64 *thash;
-   bool *wptr, wrapped = false;
- 
-+  if (url_len <= 0 && url) {
-+    url_len = strlen(url);
-+  } else {
-+    url_len = 0;
-+  }
-+
-   if (h) {
-     thash = h;
-   } else if (hash) {
-@@ -153,7 +165,7 @@ ATSConsistentHash::lookup_available(const char *url, ATSConsistentHashIter *i, b
-   }
- 
-   if (url) {
--    thash->update(url, strlen(url));
-+    thash->update(url, url_len);
-     thash->final();
-     url_hash = thash->get();
-     thash->clear();
-@@ -180,6 +192,34 @@ ATSConsistentHash::lookup_available(const char *url, ATSConsistentHashIter *i, b
-   return (*iter)->second;
- }
- 
-+ATSConsistentHashNode *
-+ATSConsistentHash::lookup_by_hashval(uint64_t hashval, ATSConsistentHashIter *i, bool *w)
-+{
-+  ATSConsistentHashIter NodeMapIterUp, *iter;
-+  bool *wptr, wrapped = false;
-+
-+  if (w) {
-+    wptr = w;
-+  } else {
-+    wptr = &wrapped;
-+  }
-+
-+  if (i) {
-+    iter = i;
-+  } else {
-+    iter = &NodeMapIterUp;
-+  }
-+
-+  *iter = NodeMap.lower_bound(hashval);
-+
-+  if (*iter == NodeMap.end()) {
-+    *wptr = true;
-+    *iter = NodeMap.begin();
-+  }
-+
-+  return (*iter)->second;
-+}
-+
- ATSConsistentHash::~ATSConsistentHash()
- {
-   if (hash) {
-diff --git a/lib/ts/ConsistentHash.h b/lib/ts/ConsistentHash.h
-index 7704c7a..a201b92 100644
---- a/lib/ts/ConsistentHash.h
-+++ b/lib/ts/ConsistentHash.h
-@@ -52,8 +52,9 @@ struct ATSConsistentHash
- {
-   ATSConsistentHash(int r = 1024, ATSHash64 *h = NULL);
-   void insert(ATSConsistentHashNode *node, float weight = 1.0, ATSHash64 *h = NULL);
--  ATSConsistentHashNode *lookup(const char *url = NULL, ATSConsistentHashIter *i = NULL, bool *w = NULL, ATSHash64 *h = NULL);
--  ATSConsistentHashNode *lookup_available(const char *url = NULL, ATSConsistentHashIter *i = NULL, bool *w = NULL, ATSHash64 *h = NULL);
-+  ATSConsistentHashNode *lookup(const char *url = NULL, size_t url_len = 0, ATSConsistentHashIter *i = NULL, bool *w = NULL, ATSHash64 *h = NULL);
-+  ATSConsistentHashNode *lookup_available(const char *url = NULL, size_t url_len = 0, ATSConsistentHashIter *i = NULL, bool *w = NULL, ATSHash64 *h = NULL);
-+  ATSConsistentHashNode *lookup_by_hashval(uint64_t hashval, ATSConsistentHashIter *i = NULL, bool *w = NULL);
-   ~ATSConsistentHash();
- 
- private:
-diff --git a/lib/ts/Makefile.am b/lib/ts/Makefile.am
-index 150182d..ff6fcad 100644
---- a/lib/ts/Makefile.am
-+++ b/lib/ts/Makefile.am
-@@ -108,6 +108,8 @@ libtsutil_la_SOURCES = \
-   defalloc.h \
-   fastlz.c \
-   fastlz.h \
-+  hugepages.cc \
-+  hugepages.h \
-   ink_aiocb.h \
-   ink_align.h \
-   ink_apidefs.h \
-diff --git a/lib/ts/apidefs.h.in b/lib/ts/apidefs.h.in
-index 93f473f..d6e78bd 100644
---- a/lib/ts/apidefs.h.in
-+++ b/lib/ts/apidefs.h.in
-@@ -746,6 +746,7 @@ extern "C"
-     TS_CONFIG_HTTP_CACHE_RANGE_WRITE,
-     TS_CONFIG_HTTP_POST_CHECK_CONTENT_LENGTH_ENABLED,
-     TS_CONFIG_HTTP_GLOBAL_USER_AGENT_HEADER,
-+    TS_CONFIG_HTTP_TRANSACTION_ACTIVE_TIMEOUT_IN,
-     TS_CONFIG_LAST_ENTRY
-   } TSOverridableConfigKey;
- 
-diff --git a/lib/ts/hugepages.cc b/lib/ts/hugepages.cc
-new file mode 100644
-index 0000000..900c32d
---- /dev/null
-+++ b/lib/ts/hugepages.cc
-@@ -0,0 +1,127 @@
-+/** @file
-+
-+  @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 <cstdio>
-+#include <sys/mman.h>
-+#include "Diags.h"
-+#include "ink_align.h"
-+
-+#define DEBUG_TAG "hugepages"
-+#define MEMINFO_PATH "/proc/meminfo"
-+#define LINE_SIZE 256
-+#define TOKEN "Hugepagesize:"
-+#define TOKEN_SIZE (strlen(TOKEN))
-+
-+static int hugepage_size = -1;
-+static bool hugepage_enabled;
-+
-+size_t
-+ats_hugepage_size(void)
-+{
-+#ifdef MAP_HUGETLB
-+  return hugepage_size;
-+#else
-+  Debug(DEBUG_TAG, "MAP_HUGETLB not defined");
-+  return 0;
-+#endif
-+}
-+
-+bool
-+ats_hugepage_enabled(void)
-+{
-+#ifdef MAP_HUGETLB
-+  return hugepage_enabled;
-+#else
-+  return false;
-+#endif
-+}
-+
-+void
-+ats_hugepage_init(int enabled)
-+{
-+#ifdef MAP_HUGETLB
-+  FILE *fp;
-+  char line[LINE_SIZE];
-+  char *p, *ep;
-+
-+  hugepage_size = 0;
-+
-+  if (!enabled) {
-+    Debug(DEBUG_TAG, "hugepages not enabled");
-+    return;
-+  }
-+
-+  fp = fopen(MEMINFO_PATH, "r");
-+
-+  if (fp == NULL) {
-+    Debug(DEBUG_TAG, "Cannot open file %s", MEMINFO_PATH);
-+    return;
-+  }
-+
-+  while (fgets(line, sizeof(line), fp)) {
-+    if (strncmp(line, TOKEN, TOKEN_SIZE) == 0) {
-+      p = line + TOKEN_SIZE;
-+      while (*p == ' ') {
-+        p++;
-+      }
-+      hugepage_size = strtol(p, &ep, 10);
-+      // What other values can this be?
-+      if (strncmp(ep, " kB", 4)) {
-+        hugepage_size *= 1024;
-+      }
-+      break;
-+    }
-+  }
-+
-+  fclose(fp);
-+
-+  if (hugepage_size) {
-+    hugepage_enabled = true;
-+  }
-+
-+  Debug(DEBUG_TAG, "Hugepage size = %d", hugepage_size);
-+#else
-+  Debug(DEBUG_TAG, "MAP_HUGETLB not defined");
-+#endif
-+}
-+
-+void *
-+ats_alloc_hugepage(size_t s ATS_UNUSED)
-+{
-+#ifdef MAP_HUGETLB
-+  size_t size;
-+  void *mem;
-+
-+  size = INK_ALIGN(s, ats_hugepage_size());
-+
-+  mem = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS | MAP_HUGETLB, -1, 0);
-+
-+  if (mem == NULL) {
-+    Debug(DEBUG_TAG, "Could not allocate hugepages size = %zu", size);
-+  }
-+
-+  return mem;
-+#else
-+  (void)s;
-+  Debug(DEBUG_TAG, "MAP_HUGETLB not defined");
-+  return NULL;
-+#endif
-+}
-diff --git a/lib/ts/hugepages.h b/lib/ts/hugepages.h
-new file mode 100644
-index 0000000..5217ca5
---- /dev/null
-+++ b/lib/ts/hugepages.h
-@@ -0,0 +1,31 @@
-+/** @file
-+
-+  @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.
-+ */
-+#ifndef _hugepages_h_
-+#define _hugepages_h_
-+
-+#include <cstring>
-+
-+size_t ats_hugepage_size(void);
-+bool ats_hugepage_enabled(void);
-+void ats_hugepage_init(int);
-+void *ats_alloc_hugepage(size_t);
-+
-+#endif
-diff --git a/lib/ts/ink_inet.cc b/lib/ts/ink_inet.cc
-index a841a76..e920240 100644
---- a/lib/ts/ink_inet.cc
-+++ b/lib/ts/ink_inet.cc
-@@ -97,6 +97,10 @@ ink_inet_addr(const char *s)
-   int n = 0;
-   uint32_t base = 10;
- 
-+  if (NULL == s) {
-+    return htonl((uint32_t) - 1);
-+  }
-+
-   while (n < 4) {
- 
-     u[n] = 0;
-diff --git a/lib/ts/ink_queue.cc b/lib/ts/ink_queue.cc
-index 7847b2d..fbeedf3 100644
---- a/lib/ts/ink_queue.cc
-+++ b/lib/ts/ink_queue.cc
-@@ -50,6 +50,7 @@
- #include "ink_assert.h"
- #include "ink_queue_ext.h"
- #include "ink_align.h"
-+#include "hugepages.h"
- 
- inkcoreapi volatile int64_t fastalloc_mem_in_use = 0;
- inkcoreapi volatile int64_t fastalloc_mem_total = 0;
-@@ -102,9 +103,13 @@ ink_freelist_init(InkFreeList **fl, const char *name, uint32_t type_size,
-   /* quick test for power of 2 */
-   ink_assert(!(alignment & (alignment - 1)));
-   f->alignment = alignment;
--  f->chunk_size = chunk_size;
-   // Make sure we align *all* the objects in the allocation, not just the first one
-   f->type_size = INK_ALIGN(type_size, alignment);
-+  if (ats_hugepage_enabled()) {
-+    f->chunk_size = INK_ALIGN(chunk_size * f->type_size, ats_hugepage_size()) / f->type_size;
-+  } else {
-+    f->chunk_size = chunk_size;
-+  }
-   SET_FREELIST_POINTER_VERSION(f->head, FROM_PTR(0), 0);
- 
-   f->used = 0;
-@@ -161,10 +166,15 @@ ink_freelist_new(InkFreeList * f)
- #ifdef DEBUG
-       char *oldsbrk = (char *) sbrk(0), *newsbrk = NULL;
- #endif
--      if (f->alignment)
--        newp = ats_memalign(f->alignment, f->chunk_size * type_size);
--      else
--        newp = ats_malloc(f->chunk_size * type_size);
-+      if (ats_hugepage_enabled())
-+        newp = ats_alloc_hugepage(f->chunk_size * type_size);
-+
-+      if (newp == NULL) {
-+        if (f->alignment)
-+          newp = ats_memalign(f->alignment, f->chunk_size * type_size);
-+        else
-+          newp = ats_malloc(f->chunk_size * type_size);
-+      }
-       fl_memadd(f->chunk_size * type_size);
- #ifdef DEBUG
-       newsbrk = (char *) sbrk(0);
-diff --git a/lib/ts/libts.h b/lib/ts/libts.h
-index c7cbc5e..01712d5 100644
---- a/lib/ts/libts.h
-+++ b/lib/ts/libts.h
-@@ -41,6 +41,7 @@
- #define std *** _FIXME_REMOVE_DEPENDENCY_ON_THE_STL_ ***
- */
- 
-+#include "hugepages.h"
- #include "ink_config.h"
- #include "ink_platform.h"
- #include "ink_align.h"
-diff --git a/mgmt/RecordsConfig.cc b/mgmt/RecordsConfig.cc
-index 3fbbfdd..c28a21b 100644
---- a/mgmt/RecordsConfig.cc
-+++ b/mgmt/RecordsConfig.cc
-@@ -2030,6 +2030,8 @@ static const RecordElement RecordsConfig[] =
-   ,
-   {RECT_CONFIG, "proxy.config.allocator.debug_filter", RECD_INT, "0", RECU_NULL, RR_NULL, RECC_NULL, "[0-3]", RECA_NULL}
-   ,
-+  {RECT_CONFIG, "proxy.config.allocator.hugepages", RECD_INT, "0", RECU_NULL, RR_NULL, RECC_NULL, "[0-1]", RECA_NULL}
-+  ,
- 
-   //############
-   //#
-diff --git a/plugins/cacheurl/Makefile.am b/plugins/cacheurl/Makefile.am
-index f5907fe..68391cf 100644
---- a/plugins/cacheurl/Makefile.am
-+++ b/plugins/cacheurl/Makefile.am
-@@ -17,5 +17,7 @@
- include $(top_srcdir)/build/plugins.mk
- 
- pkglib_LTLIBRARIES = cacheurl.la
--cacheurl_la_SOURCES = cacheurl.cc
-+cacheurl_la_SOURCES = \
-+  pluginconfig.cc \
-+  cacheurl.cc
- cacheurl_la_LDFLAGS = $(TS_PLUGIN_LDFLAGS)
-diff --git a/plugins/cacheurl/cacheurl.cc b/plugins/cacheurl/cacheurl.cc
-index a1a01c3..5322075 100644
---- a/plugins/cacheurl/cacheurl.cc
-+++ b/plugins/cacheurl/cacheurl.cc
-@@ -31,6 +31,8 @@
- #include <string>
- #include <vector>
- 
-+#include "pluginconfig.h"
-+
- #ifdef HAVE_PCRE_PCRE_H
- #include <pcre/pcre.h>
- #else
-@@ -51,8 +53,9 @@ struct regex_info
-   int *tokenoffset;             /* Array of $x token offsets */
- };
- 
--struct pr_list
-+class pr_list : public PluginConfig
- {
-+public:
-   std::vector<regex_info*>pr;
- 
-   pr_list()
-@@ -68,7 +71,12 @@ struct pr_list
-       TSfree(*info);
-     }
-   }
-+
-+  virtual pr_list* load(TSFile fh);
- };
-+static pr_list* load_pr_list(TSFile fh);
-+
-+#define DEFAULT_CONFIG_NAME     "cacheurl.config"
- 
- static int
- regex_substitute(char **buf, char *str, regex_info * info)
-@@ -202,16 +210,8 @@ regex_compile(regex_info ** buf, char *pattern, char *replacement)
- static pr_list *
- load_config_file(const char *config_file)
- {
--  char buffer[1024];
-   std::string path;
-   TSFile fh;
--  pr_list *prl = new pr_list();
--
--  /* locations in a config file line, end of line, split start, split end */
--  char *eol, *spstart, *spend;
--  int lineno = 0;
--  int retval;
--  regex_info *info = 0;
- 
-   if (config_file == NULL) {
-     /* Default config file of plugins/cacheurl.config */
-@@ -232,59 +232,15 @@ load_config_file(const char *config_file)
- 
-   if (!fh) {
-     TSError("[%s] Unable to open %s. No patterns will be loaded\n", PLUGIN_NAME, path.c_str());
--    return prl;
-+    return new pr_list();
-   }
- 
--  while (TSfgets(fh, buffer, sizeof(buffer) - 1)) {
--    lineno++;
--    if (*buffer == '#') {
--      /* # Comments, only at line beginning */
--      continue;
--    }
--    eol = strstr(buffer, "\n");
--    if (eol) {
--      *eol = 0;                 /* Terminate string at newline */
--    } else {
--      /* Malformed line - skip */
--      continue;
--    }
--    /* Split line into two parts based on whitespace */
--    /* Find first whitespace */
--    spstart = strstr(buffer, " ");
--    if (!spstart) {
--      spstart = strstr(buffer, "\t");
--    }
--    if (!spstart) {
--      TSError("[%s] ERROR: Invalid format on line %d. Skipping\n", PLUGIN_NAME, lineno);
--      continue;
--    }
--    /* Find part of the line after any whitespace */
--    spend = spstart + 1;
--    while (*spend == ' ' || *spend == '\t') {
--      spend++;
--    }
--    if (*spend == 0) {
--      /* We reached the end of the string without any non-whitepace */
--      TSError("[%s] ERROR: Invalid format on line %d. Skipping\n", PLUGIN_NAME, lineno);
--      continue;
--    }
-+  pr_list* config = load_pr_list(fh);
- 
--    *spstart = 0;
--    /* We have the pattern/replacement, now do precompilation.
--     * buffer is the first part of the line. spend is the second part just
--     * after the whitespace */
--    TSDebug(PLUGIN_NAME, "Adding pattern/replacement pair: '%s' -> '%s'", buffer, spend);
--    retval = regex_compile(&info, buffer, spend);
--    if (!retval) {
--      TSError("[%s] Error precompiling regex/replacement. Skipping.\n", PLUGIN_NAME);
--    }
--
--    prl->pr.push_back(info);
--  }
-   TSfclose(fh);
- 
--  TSDebug(PLUGIN_NAME, "loaded %u regexes", (unsigned) prl->pr.size());
--  return prl;
-+  TSDebug(PLUGIN_NAME, "loaded %u regexes", (unsigned) config->pr.size());
-+  return config;
- }
- 
- static int
-@@ -312,8 +268,7 @@ rewrite_cacheurl(pr_list * prl, TSHttpTxn txnp)
-     }
-     if (newurl) {
-       TSDebug(PLUGIN_NAME, "Rewriting cache URL for %s to %s", url, newurl);
--      if (TSCacheUrlSet(txnp, newurl, strlen(newurl))
--          != TS_SUCCESS) {
-+      if (TSCacheUrlSet(txnp, newurl, strlen(newurl)) != TS_SUCCESS) {
-         TSError("[%s] Unable to modify cache url from " "%s to %s\n", PLUGIN_NAME, url, newurl);
-         ok = 0;
-       }
-@@ -336,7 +291,7 @@ handle_hook(TSCont contp, TSEvent event, void *edata)
-   pr_list *prl;
-   int ok = 1;
- 
--  prl = (pr_list *) TSContDataGet(contp);
-+  prl = (pr_list*)ConfigHolder::get_config(contp);
- 
-   switch (event) {
-   case TS_EVENT_HTTP_READ_REQUEST_HDR:
-@@ -375,7 +330,7 @@ TSRemapInit(TSRemapInterface * api_info, char *errbuf, int errbuf_size)
- 
-   if (api_info->tsremap_version < TSREMAP_VERSION) {
-     snprintf(errbuf, errbuf_size - 1, "[tsremap_init] Incorrect API version %ld.%ld",
--             api_info->tsremap_version >> 16, (api_info->tsremap_version & 0xffff));
-+        api_info->tsremap_version >> 16, (api_info->tsremap_version & 0xffff));
-     return TS_ERROR;
-   }
- 
-@@ -390,7 +345,6 @@ TSRemapNewInstance(int argc, char *argv[], void **ih, char *errbuf ATS_UNUSED, i
-   return TS_SUCCESS;
- }
- 
--
- void
- TSRemapDeleteInstance(void *ih)
- {
-@@ -417,9 +371,13 @@ TSRemapDoRemap(void *ih, TSHttpTxn rh, TSRemapRequestInfo * rri ATS_UNUSED)
- void
- TSPluginInit(int argc, const char *argv[])
- {
-+  TSCont main_cont;
-+  ConfigHolder* config_holder;
-+  const char* path;
-+
-   TSPluginRegistrationInfo info;
--  TSCont contp;
--  pr_list *prl;
-+
-+  TSDebug(PLUGIN_NAME, "TSPluginInit");
- 
-   info.plugin_name = (char *) PLUGIN_NAME;
-   info.vendor_name = (char *) "Apache Software Foundation";
-@@ -430,10 +388,91 @@ TSPluginInit(int argc, const char *argv[])
-     return;
-   }
- 
--  prl = load_config_file(argc > 1 ? argv[1] : NULL);
-+  //  prl = load_config_file(argc > 1 ? argv[1] : NULL);
-+  path = argc > 1 ? argv[1] : NULL;
-+  config_holder = new ConfigHolder(new pr_list(), DEFAULT_CONFIG_NAME, PLUGIN_NAME);
-+  TSDebug(PLUGIN_NAME, "before init_config_holder");
-+  config_holder = config_holder->init(path);
-+  TSDebug(PLUGIN_NAME, "after init_config_holder");
- 
--  contp = TSContCreate((TSEventFunc) handle_hook, NULL);
-+  main_cont = TSContCreate((TSEventFunc) handle_hook, NULL);
-   /* Store the pattern replacement list in the continuation */
--  TSContDataSet(contp, prl);
--  TSHttpHookAdd(TS_HTTP_READ_REQUEST_HDR_HOOK, contp);
-+  TSContDataSet(main_cont, config_holder);
-+  TSHttpHookAdd(TS_HTTP_READ_REQUEST_HDR_HOOK, main_cont);
-+  // TODO make configurable TS_HTTP_POST_REMAP_HOOK / TS_HTTP_READ_REQUEST_HDR_HOOK
-+
-+  config_holder->addUpdateRegister();
-+
-+}
-+static pr_list* load_pr_list(TSFile fh) {
-+  char buffer[1024];
-+  /* locations in a config file line, end of line, split start, split end */
-+  char *eol, *spstart, *spend;
-+  int lineno = 0;
-+  int retval;
-+  regex_info *info = 0;
-+  pr_list *prl = new pr_list();
-+  TSDebug(PLUGIN_NAME, "new_config");
-+
-+  if(!fh) {
-+    TSDebug(PLUGIN_NAME, "No config, using defaults");
-+    return prl;
-+  }
-+
-+  TSDebug(PLUGIN_NAME, "new_config: before loop, fh=%p", fh);
-+  while (TSfgets(fh, buffer, sizeof(buffer) - 1)) {
-+    TSDebug(PLUGIN_NAME, "new_config: enter loop, lineno=%d", lineno);
-+    lineno++;
-+    if (*buffer == '#') {
-+      /* # Comments, only at line beginning */
-+      continue;
-+    }
-+    eol = strstr(buffer, "\n");
-+    if (eol) {
-+      *eol = 0;                 /* Terminate string at newline */
-+    } else {
-+      /* Malformed line - skip */
-+      continue;
-+    }
-+    /* Split line into two parts based on whitespace */
-+    /* Find first whitespace */
-+    spstart = strstr(buffer, " ");
-+    if (!spstart) {
-+      spstart = strstr(buffer, "\t");
-+    }
-+    if (!spstart) {
-+      TSError("[%s] ERROR: Invalid format on line %d. Skipping\n", PLUGIN_NAME, lineno);
-+      continue;
-+    }
-+    /* Find part of the line after any whitespace */
-+    spend = spstart + 1;
-+    while (*spend == ' ' || *spend == '\t') {
-+      spend++;
-+    }
-+    if (*spend == 0) {
-+      /* We reached the end of the string without any non-whitepace */
-+      TSError("[%s] ERROR: Invalid format on line %d. Skipping\n", PLUGIN_NAME, lineno);
-+      continue;
-+    }
-+
-+    *spstart = 0;
-+    /* We have the pattern/replacement, now do precompilation.
-+     * buffer is the first part of the line. spend is the second part just
-+     * after the whitespace */
-+    TSDebug(PLUGIN_NAME, "Adding pattern/replacement pair: '%s' -> '%s'", buffer, spend);
-+    retval = regex_compile(&info, buffer, spend);
-+    if (!retval) {
-+      TSError("[%s] Error precompiling regex/replacement. Skipping.\n", PLUGIN_NAME);
-+    }
-+
-+    prl->pr.push_back(info);
-+  }
-+
-+  return prl;
-+}
-+
-+pr_list* pr_list::load(TSFile fh) {
-+  TSDebug(PLUGIN_NAME, "pr_list::load(TSFile fh)");
-+  return load_pr_list(fh);
-+  //  return 0;
- }
-diff --git a/plugins/cacheurl/pluginconfig.cc b/plugins/cacheurl/pluginconfig.cc
-new file mode 100644
-index 0000000..b1ad203
---- /dev/null
-+++ b/plugins/cacheurl/pluginconfig.cc
-@@ -0,0 +1,147 @@
-+/** @file
-+
-+  A brief file description
-+
-+  @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.
-+ */
-+
-+/*
-+ * pluginconfig.cc
-+ *
-+ *  Created on: Jul 15, 2014
-+ *      Author: jlaue
-+ */
-+
-+#include <sys/stat.h>
-+#include <time.h>
-+#include <stdio.h>
-+
-+#include "ink_defs.h"
-+#include "ts/ts.h"
-+#include "pluginconfig.h"
-+
-+#define FREE_TMOUT              300000
-+
-+
-+static int free_handler(TSCont cont, TSEvent event, void *edata);
-+
-+PluginConfig* ConfigHolder::get_config(TSCont cont) {
-+  ConfigHolder* configh = (ConfigHolder *) TSContDataGet(cont);
-+  if(!configh) {
-+      return 0;
-+  }
-+  return configh->config;
-+}
-+void ConfigHolder::load_config_file() {
-+  TSFile fh;
-+  struct stat s;
-+
-+  PluginConfig *newconfig, *oldconfig;
-+  TSCont free_cont;
-+
-+  TSDebug(pluginName, "load_config_file() here");
-+
-+  // check date
-+  if (stat(config_path, &s) < 0) {
-+      TSDebug(pluginName, "Could not stat %s", config_path);
-+      if(config) {
-+          return;
-+      }
-+  } else {
-+      TSDebug(pluginName, "s.st_mtime=%lu, last_load=%lu", s.st_mtime, last_load);
-+      if (s.st_mtime < last_load) {
-+          return;
-+      }
-+  }
-+
-+  TSDebug(pluginName, "Opening config file: %s", config_path);
-+  fh = TSfopen(config_path, "r");
-+
-+  if (!fh) {
-+      TSError("[%s] Unable to open config: %s.\n",
-+          pluginName, config_path);
-+      return;
-+  }
-+
-+  TSDebug(pluginName, "Calling new_config: %s / %p", config_path, config);
-+  newconfig = config->load(fh);
-+  TSDebug(pluginName, "after new_config: %s", config_path);
-+  if(newconfig) {
-+      last_load = time(NULL);
-+      PluginConfig ** confp = &(config);
-+      oldconfig = __sync_lock_test_and_set(confp, newconfig);
-+      if (oldconfig) {
-+          TSDebug(pluginName, "scheduling free: %p (%p)", oldconfig, newconfig);
-+          free_cont = TSContCreate(free_handler, NULL);
-+          TSContDataSet(free_cont, (void *) oldconfig);
-+          TSContSchedule(free_cont, FREE_TMOUT, TS_THREAD_POOL_TASK);
-+      }
-+  }
-+  if(fh)
-+    TSfclose(fh);
-+  TSDebug(pluginName, "load_config_file end");
-+  return;
-+}
-+ConfigHolder* ConfigHolder::init(const char* path) {
-+  char default_config_file[1024];
-+  //      TSmalloc(32);
-+  //
-+  if(path) {
-+      config_path = TSstrdup(path);
-+  } else {
-+      /* Default config file of plugins/cacheurl.config */
-+      //              sprintf(default_config_file, "%s/astats.config", TSPluginDirGet());
-+      sprintf(default_config_file, "%s/%s", TSConfigDirGet(), default_config_name);
-+      config_path = TSstrdup(default_config_file);
-+  }
-+  TSDebug(pluginName, "calling load_config_file()");
-+  load_config_file();
-+  return this;
-+}
-+
-+
-+static int free_handler(TSCont cont, TSEvent event, void *edata) {
-+  (void) event;
-+  (void) edata;
-+  PluginConfig *config;
-+
-+  TSDebug("free_handler", "Freeing old config");
-+  config = (PluginConfig *) TSContDataGet(cont);
-+  delete (config);
-+  TSContDestroy(cont);
-+  return 0;
-+}
-+int ConfigHolder::config_handler(TSCont cont, TSEvent event, void *edata) {
-+  (void) event;
-+  (void) edata;
-+  ConfigHolder *ch;
-+
-+  ch = (ConfigHolder *) TSContDataGet(cont);
-+  TSDebug(ch->getPluginName(), "In config Handler");
-+  ch->load_config_file();
-+  return 0;
-+}
-+
-+bool ConfigHolder::addUpdateRegister() {
-+  TSCont config_cont;
-+  config_cont = TSContCreate(config_handler, TSMutexCreate());
-+  TSContDataSet(config_cont, (void *) this);
-+  TSMgmtUpdateRegister(config_cont, uniqueID);
-+  return true;
-+}
-diff --git a/plugins/cacheurl/pluginconfig.h b/plugins/cacheurl/pluginconfig.h
-new file mode 100644
-index 0000000..4a8e0a2
---- /dev/null
-+++ b/plugins/cacheurl/pluginconfig.h
-@@ -0,0 +1,77 @@
-+/** @file
-+
-+  A brief file description
-+
-+  @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.
-+ */
-+
-+/*
-+ * pluginconfig.h
-+ *
-+ *  Created on: Jul 15, 2014
-+ *      Author: jlaue
-+ */
-+
-+#define UID_LEN 32
-+
-+class PluginConfig {
-+public:
-+  PluginConfig() {};
-+  virtual ~PluginConfig() {};
-+
-+  virtual PluginConfig* load(TSFile) {
-+    return 0;
-+  }
-+
-+};
-+
-+class ConfigHolder {
-+public:
-+  ConfigHolder(PluginConfig* config, const char* defaultConfigName, const char* pluginName) :
-+    config(config), log(0), config_path(0), last_load(0),
-+    default_config_name(defaultConfigName), pluginName(pluginName) {
-+    snprintf(uniqueID, UID_LEN, "%p", this);
-+  }
-+  ~ConfigHolder() {
-+    delete config;
-+    if (config_path)
-+      TSfree(config_path);
-+    if (log)
-+      TSTextLogObjectDestroy(log);
-+  }
-+  const char* getPluginName() { return pluginName; }
-+  ConfigHolder* init(const char* path);
-+  bool addUpdateRegister();
-+
-+  static PluginConfig* get_config(TSCont cont);
-+
-+private:
-+  PluginConfig* config;
-+  TSTextLogObject log;
-+  char *config_path;
-+  volatile time_t last_load;
-+  const char* default_config_name;
-+  const char *pluginName;
-+  char uniqueID[UID_LEN];
-+
-+  void load_config_file();
-+
-+  static int config_handler(TSCont cont, TSEvent event, void *edata);
-+
-+};
-diff --git a/plugins/experimental/background_fetch/background_fetch.cc b/plugins/experimental/background_fetch/background_fetch.cc
-index 4b00179..10897d9 100644
---- a/plugins/experimental/background_fetch/background_fetch.cc
-+++ b/plugins/experimental/background_fetch/background_fetch.cc
-@@ -84,8 +84,13 @@ read_config(char* config_file, BgFetchRuleMap* ri)
-     snprintf(file_path, sizeof(file_path), "%s/%s", TSInstallDirGet(), config_file);
-     file = TSfopen(file_path, "r");
-     if (file == NULL) {
--      TSError("%s: invalid config file", PLUGIN_NAME);
--      return false;
-+      TSDebug(PLUGIN_NAME, "Failed to open config file %s, trying config path", config_file);
-+      snprintf(file_path, sizeof(file_path), "%s/%s", TSConfigDirGet(), config_file);
-+      file = TSfopen(file_path, "r");
-+      if (file == NULL) {
-+        TSError("%s: invalid config file", PLUGIN_NAME);
-+        return false;
-+      }
-     }
-   }
- 
-@@ -296,6 +301,8 @@ public:
-     }
-     TSMutexUnlock(_lock);
- 
-+    TSDebug (PLUGIN_NAME, "BGFetchConfig.acquire(): ret = %d, url = %s\n", ret, url.c_str());
-+
-     return ret;
-   }
- 
-@@ -334,14 +341,14 @@ static int cont_bg_fetch(TSCont contp, TSEvent event, void* edata);
- struct BGFetchData
- {
-   BGFetchData(BGFetchConfig* cfg=gConfig)
--    : hdr_loc(TS_NULL_MLOC), url_loc(TS_NULL_MLOC), vc(NULL), _bytes(0), _cont(NULL),  _config(cfg)
-+    : hdr_loc(TS_NULL_MLOC), url_loc(TS_NULL_MLOC), vc(NULL), _bytes(0), _cont(NULL),  _config(cfg), scheduled (0)
-   {
-     mbuf = TSMBufferCreate();
-   }
- 
-   ~BGFetchData()
-   {
--    release_url();
-+    if (scheduled) release_url();
- 
-     TSHandleMLocRelease(mbuf, TS_NULL_MLOC, hdr_loc);
-     TSHandleMLocRelease(mbuf, TS_NULL_MLOC, url_loc);
-@@ -391,6 +398,7 @@ private:
-   int64_t _bytes;
-   TSCont _cont;
-   BGFetchConfig* _config;
-+  bool scheduled;
- };
- 
- 
-@@ -477,6 +485,7 @@ BGFetchData::schedule()
- 
-   // Schedule
-   TSContSchedule(_cont, 0, TS_THREAD_POOL_NET);
-+  scheduled = true;
- }
- 
- 
-diff --git a/plugins/experimental/regex_revalidate/regex_revalidate.c b/plugins/experimental/regex_revalidate/regex_revalidate.c
-index fd86a22..74d4ba1 100644
---- a/plugins/experimental/regex_revalidate/regex_revalidate.c
-+++ b/plugins/experimental/regex_revalidate/regex_revalidate.c
-@@ -40,555 +40,596 @@
- #  include <pcre.h>
- #endif
- 
--#define LOG_PREFIX        "regex_revalidate"
--#define CONFIG_TMOUT      60000
--#define FREE_TMOUT        300000
--#define OVECTOR_SIZE      30
--#define LOG_ROLL_INTERVAL 86400
--#define LOG_ROLL_OFFSET   0
-+typedef struct invalidate_t
-+{
-+  const char *regex_text;
-+  pcre *regex;
-+  pcre_extra *regex_extra;
-+  time_t epoch;
-+  time_t expiry;
-+  struct invalidate_t * volatile next;
-+} invalidate_t;
-+
-+typedef invalidate_t config_t;
-+
-+typedef struct {
-+  char *config_path;
-+  volatile time_t last_load;
-+  config_t* config;
-+  TSTextLogObject log;
-+} config_holder_t;
-+
-+static int free_handler(TSCont cont, TSEvent event, void *edata);
-+static int config_handler(TSCont cont, TSEvent event, void *edata);
-+static config_t* get_config(TSCont cont);
-+static config_holder_t* new_config_holder();
-+static config_holder_t* init_config_holder(config_holder_t* config_holder, const char* path);
-+static void free_config_holder_t(config_holder_t *config_holder);
-+static void schedule_free_invalidate_t(invalidate_t * iptr);
-+
-+#define PLUGIN_TAG              "regex_revalidate"
-+#define DEFAULT_CONFIG_NAME     "regex_revalidate.config"
-+#define PRUNE_TMOUT             60000
-+#define FREE_TMOUT              300000
-+#define OVECTOR_SIZE            30
-+#define LOG_ROLL_INTERVAL       86400
-+#define LOG_ROLL_OFFSET         0
- 
- static inline void*
- ts_malloc(size_t s)
- {
--    return TSmalloc(s);
-+  return TSmalloc(s);
- }
- 
- static inline void
- ts_free(void *s)
- {
--    return TSfree(s);
-+  return TSfree(s);
- }
- 
--typedef struct invalidate_t
--{
--    const char *regex_text;
--    pcre *regex;
--    pcre_extra *regex_extra;
--    time_t epoch;
--    time_t expiry;
--    struct invalidate_t *next;
--} invalidate_t;
--
--typedef struct
--{
--    invalidate_t * volatile invalidate_list;
--    char *config_file;
--    volatile time_t last_load;
--    TSTextLogObject log;
--} plugin_state_t;
--
- static invalidate_t *
- init_invalidate_t(invalidate_t *i)
- {
--    i->regex_text = NULL;
--    i->regex = NULL;
--    i->regex_extra = NULL;
--    i->epoch = 0;
--    i->expiry = 0;
--    i->next = NULL;
--    return i;
-+  i->regex_text = NULL;
-+  i->regex = NULL;
-+  i->regex_extra = NULL;
-+  i->epoch = 0;
-+  i->expiry = 0;
-+  i->next = NULL;
-+  return i;
- }
- 
- static void
- free_invalidate_t(invalidate_t *i)
- {
--    if (i->regex_extra)
-+  if (i->regex_extra)
- #ifndef PCRE_STUDY_JIT_COMPILE
--        pcre_free(i->regex_extra);
-+    pcre_free(i->regex_extra);
- #else
--        pcre_free_study(i->regex_extra);
-+  pcre_free_study(i->regex_extra);
- #endif
--    if (i->regex)
--        pcre_free(i->regex);
--    if (i->regex_text)
--        pcre_free_substring(i->regex_text);
--    TSfree(i);
-+  if (i->regex)
-+    pcre_free(i->regex);
-+  if (i->regex_text)
-+    pcre_free_substring(i->regex_text);
-+  TSfree(i);
- }
- 
- static void
- free_invalidate_t_list(invalidate_t *i)
- {
--    if (i->next)
--        free_invalidate_t_list(i->next);
--    free_invalidate_t(i);
--}
--
--static plugin_state_t *
--init_plugin_state_t(plugin_state_t *pstate)
--{
--    pstate->invalidate_list = NULL;
--    pstate->config_file = NULL;
--    pstate->last_load = 0;
--    pstate->log = NULL;
--    return pstate;
--}
--
--static void
--free_plugin_state_t(plugin_state_t *pstate)
--{
--    if (pstate->invalidate_list)
--        free_invalidate_t_list(pstate->invalidate_list);
--    if (pstate->config_file)
--        TSfree(pstate->config_file);
--    if (pstate->log)
--        TSTextLogObjectDestroy(pstate->log);
--    TSfree(pstate);
--}
--
--static invalidate_t *
--copy_invalidate_t(invalidate_t *i)
--{
--    invalidate_t *iptr;
--    const char *errptr;
--    int erroffset;
--
--    iptr = (invalidate_t *) TSmalloc(sizeof(invalidate_t));
--    iptr->regex_text = TSstrdup(i->regex_text);
--    iptr->regex = pcre_compile(iptr->regex_text, 0, &errptr, &erroffset, NULL); // There is no pcre_copy :-(
--    iptr->regex_extra = pcre_study(iptr->regex, 0, &errptr);                    // Assuming no errors since this worked before :-/
--    iptr->epoch = i->epoch;
--    iptr->expiry = i->expiry;
--    iptr->next = NULL;
--    return iptr;
--}
--
--static invalidate_t *
--copy_config(invalidate_t *old_list)
--{
--    invalidate_t *new_list = NULL;
--    invalidate_t *iptr_old, *iptr_new;
--
--    if (old_list)
--    {
--        new_list = copy_invalidate_t(old_list);
--        iptr_old = old_list->next;
--        iptr_new = new_list;
--        while (iptr_old)
--        {
--            iptr_new->next = copy_invalidate_t(iptr_old);
--            iptr_new = iptr_new->next;
--            iptr_old = iptr_old->next;
--        }
--    }
--
--    return new_list;
-+  if (i->next)
-+    free_invalidate_t_list(i->next);
-+  free_invalidate_t(i);
- }
- 
- static bool
- prune_config(invalidate_t **i)
- {
--    invalidate_t *iptr, *ilast;
--    time_t now;
--    bool pruned = false;
-+  invalidate_t *iptr, *ilast;
-+  time_t now;
-+  bool pruned = false;
- 
--    now = time(NULL);
-+  now = time(NULL);
- 
--    if (*i)
-+  if (*i)
-+  {
-+    iptr = *i;
-+    ilast = NULL;
-+    while (iptr)
-     {
--        iptr = *i;
--        ilast = NULL;
--        while (iptr)
-+      if (difftime(iptr->expiry, now) < 0)
-+      {
-+        TSDebug(PLUGIN_TAG, "Removing %s expiry: %d now: %d", iptr->regex_text, (int) iptr->expiry, (int) now);
-+        TSError(PLUGIN_TAG " - Removing %s expiry: %d now: %d", iptr->regex_text, (int) iptr->expiry, (int) now);
-+        if (ilast)
-         {
--            if (difftime(iptr->expiry, now) < 0)
--            {
--                TSDebug(LOG_PREFIX, "Removing %s expiry: %d now: %d", iptr->regex_text, (int) iptr->expiry, (int) now);
--                if (ilast)
--                {
--                    ilast->next = iptr->next;
--                    free_invalidate_t(iptr);
--                    iptr = ilast->next;
--                }
--                else
--                {
--                    *i = iptr->next;
--                    free_invalidate_t(iptr);
--                    iptr = *i;
--                }
--                pruned = true;
--            }
--            else
--            {
--                ilast = iptr;
--                iptr = iptr->next;
--            }
--        }
--    }
--    return pruned;
--}
-+          // jlaue: TODO is this right?
-+          //                    iptr = __sync_val_compare_and_swap(&(ilast->next), ilast->next, iptr->next);
-+          ilast->next = iptr->next;
-+          //                    free_invalidate_t(iptr);
-+          schedule_free_invalidate_t(iptr);
-+          iptr = ilast->next;
- 
--static bool
--load_config(plugin_state_t *pstate, invalidate_t **ilist)
--{
--    FILE *fs;
--    struct stat s;
--    size_t path_len;
--    char *path;
--    char line[LINE_MAX];
--    time_t now;
--    pcre *config_re;
--    const char *errptr;
--    int erroffset, ovector[OVECTOR_SIZE], rc;
--    int ln = 0;
--    invalidate_t *iptr, *i;
--
--    if (pstate->config_file[0] != '/')
--    {
--        path_len = strlen(TSConfigDirGet()) + strlen(pstate->config_file) + 2;
--        path = alloca(path_len);
--        snprintf(path, path_len, "%s/%s", TSConfigDirGet(), pstate->config_file);
--    }
--    else
--        path = pstate->config_file;
--    if (stat(path, &s) < 0)
--    {
--        TSDebug(LOG_PREFIX, "Could not stat %s", path);
--        return false;
--    }
--    if (s.st_mtime > pstate->last_load)
--    {
--        now = time(NULL);
--        if (!(fs = fopen(path, "r")))
--        {
--            TSDebug(LOG_PREFIX, "Could not open %s for reading", path);
--            return false;
-         }
--        config_re = pcre_compile("^([^#].+?)\\s+(\\d+)\\s*$", 0, &errptr, &erroffset, NULL);
--        while (fgets(line, LINE_MAX, fs) != NULL)
-+        else
-         {
--            ln++;
--            TSDebug(LOG_PREFIX, "Processing: %d %s", ln, line);
--            rc = pcre_exec(config_re, NULL, line, strlen(line), 0, 0, ovector, OVECTOR_SIZE);
--            if (rc == 3)
--            {
--                i = (invalidate_t *) TSmalloc(sizeof(invalidate_t));
--                init_invalidate_t(i);
--                pcre_get_substring(line, ovector, rc, 1, &i->regex_text);
--                i->epoch = now;
--                i->expiry = atoi(line + ovector[4]);
--                i->regex = pcre_compile(i->regex_text, 0, &errptr, &erroffset, NULL);
--                if (i->expiry <= i->epoch)
--                {
--                    TSDebug(LOG_PREFIX, "Rule is already expired!");
--                    free_invalidate_t(i);
--                }
--                else if (i->regex == NULL)
--                {
--                    TSDebug(LOG_PREFIX, "%s did not compile", i->regex_text);
--                    free_invalidate_t(i);
--                }
--                else
--                {
--                    i->regex_extra = pcre_study(i->regex, 0, &errptr);
--                    if (!*ilist)
--                    {
--                        *ilist = i;
--                        TSDebug(LOG_PREFIX, "Created new list and Loaded %s %d %d", i->regex_text, (int) i->epoch, (int) i->expiry);
--                    }
--                    else
--                    {
--                        iptr = *ilist;
--                        while(1)
--                        {
--                            if (strcmp(i->regex_text, iptr->regex_text) == 0)
--                            {
--                                if (iptr->expiry != i->expiry)
--                                {
--                                    TSDebug(LOG_PREFIX, "Updating duplicate %s", i->regex_text);
--                                    iptr->epoch = i->epoch;
--                                    iptr->expiry = i->expiry;
--                                }
--                                free_invalidate_t(i);
--                                i = NULL;
--                                break;
--                            }
--                            else if (!iptr->next)
--                                break;
--                            else
--                                iptr = iptr->next;
--                        }
--                        if (i)
--                        {
--                            iptr->next = i;
--                            TSDebug(LOG_PREFIX, "Loaded %s %d %d", i->regex_text, (int) i->epoch, (int) i->expiry);
--                        }
--                    }
--                }
--            }
--            else
--                TSDebug(LOG_PREFIX, "Skipping line %d", ln);
-+          *i = iptr->next;
-+          //                    free_invalidate_t(iptr);
-+          schedule_free_invalidate_t(iptr);
-+          iptr = *i;
-         }
--        pcre_free(config_re);
--        fclose(fs);
--        pstate->last_load = s.st_mtime;
--        return true;
-+        pruned = true;
-+      }
-+      else
-+      {
-+        ilast = iptr;
-+        iptr = iptr->next;
-+      }
-     }
--    else
--        TSDebug(LOG_PREFIX, "File mod time is not newer: %d >= %d", (int) pstate->last_load, (int) s.st_mtime);
--    return false;
-+  }
-+  return pruned;
- }
- 
-+
- static void
--list_config(plugin_state_t *pstate, invalidate_t *i)
-+list_config(config_holder_t *config_holder, invalidate_t *i)
- {
--    invalidate_t *iptr;
--
--    TSDebug(LOG_PREFIX, "Current config:");
--    if (pstate->log)
--        TSTextLogObjectWrite(pstate->log, "Current config:");
--    if (i)
--    {
--        iptr = i;
--        while (iptr)
--        {
--            TSDebug(LOG_PREFIX, "%s epoch: %d expiry: %d", iptr->regex_text, (int) iptr->epoch, (int) iptr->expiry);
--            if (pstate->log)
--                TSTextLogObjectWrite(pstate->log, "%s epoch: %d expiry: %d", iptr->regex_text, (int) iptr->epoch, (int) iptr->expiry);
--            iptr = iptr->next;
--        }
--    }
--    else
-+  invalidate_t *iptr;
-+
-+  TSDebug(PLUGIN_TAG, "Current config:");
-+  if (config_holder->log)
-+    TSTextLogObjectWrite(config_holder->log, "Current config:");
-+  if (i)
-+  {
-+    iptr = i;
-+    while (iptr)
-     {
--        TSDebug(LOG_PREFIX, "EMPTY");
--        if (pstate->log)
--            TSTextLogObjectWrite(pstate->log, "EMPTY");
-+      TSDebug(PLUGIN_TAG, "%s epoch: %d expiry: %d", iptr->regex_text, (int) iptr->epoch, (int) iptr->expiry);
-+      if (config_holder->log)
-+        TSTextLogObjectWrite(config_holder->log, "%s epoch: %d expiry: %d", iptr->regex_text, (int) iptr->epoch, (int) iptr->expiry);
-+      iptr = iptr->next;
-     }
-+  }
-+  else
-+  {
-+    TSDebug(PLUGIN_TAG, "EMPTY");
-+    if (config_holder->log)
-+      TSTextLogObjectWrite(config_holder->log, "EMPTY");
-+  }
- }
- 
- static int
--free_handler(TSCont cont, TSEvent event ATS_UNUSED, void *edata ATS_UNUSED)
-+config_pruner(TSCont cont, TSEvent event ATS_UNUSED, void *edata ATS_UNUSED)
- {
--    invalidate_t *iptr;
-+  invalidate_t *i;
- 
--    TSDebug(LOG_PREFIX, "Freeing old config");
--    iptr = (invalidate_t *) TSContDataGet(cont);
--    free_invalidate_t_list(iptr);
--    TSContDestroy(cont);
--    return 0;
--}
--
--static int
--config_handler(TSCont cont, TSEvent event ATS_UNUSED, void *edata ATS_UNUSED)
--{
--    plugin_state_t *pstate;
--    invalidate_t *i, *iptr;
--    TSCont free_cont;
--    bool updated;
--
--    TSDebug(LOG_PREFIX, "In config Handler");
--    pstate = (plugin_state_t *) TSContDataGet(cont);
--    i = copy_config(pstate->invalidate_list);
-+  TSDebug(PLUGIN_TAG, "config_pruner");
-+  config_holder_t* configh = (config_holder_t *) TSContDataGet(cont);
-+  i = configh->config;
- 
--    updated = prune_config(&i);
--    updated = load_config(pstate, &i) || updated;
--
--    if (updated)
--    {
--        list_config(pstate, i);
--        iptr = __sync_val_compare_and_swap(&(pstate->invalidate_list), pstate->invalidate_list, i);
-+  prune_config(&i);
- 
--        if (iptr)
--        {
--            free_cont = TSContCreate(free_handler, NULL);
--            TSContDataSet(free_cont, (void *) iptr);
--            TSContSchedule(free_cont, FREE_TMOUT, TS_THREAD_POOL_TASK);
--        }
--    }
--    else
--    {
--        TSDebug(LOG_PREFIX, "No Changes");
--        if (i)
--            free_invalidate_t_list(i);
--    }
-+  configh->config = i;
- 
--    TSContSchedule(cont, CONFIG_TMOUT, TS_THREAD_POOL_TASK);
--    return 0;
-+  TSContSchedule(cont, PRUNE_TMOUT, TS_THREAD_POOL_TASK);
-+  return 0;
- }
- 
- static time_t
- get_date_from_cached_hdr(TSHttpTxn txn)
- {
--    TSMBuffer buf;
--    TSMLoc hdr_loc, date_loc;
--    time_t date = 0;
--
--    if (TSHttpTxnCachedRespGet(txn, &buf, &hdr_loc) == TS_SUCCESS)
-+  TSMBuffer buf;
-+  TSMLoc hdr_loc, date_loc;
-+  time_t date = 0;
-+
-+  if (TSHttpTxnCachedRespGet(txn, &buf, &hdr_loc) == TS_SUCCESS)
-+  {
-+    date_loc = TSMimeHdrFieldFind(buf, hdr_loc, TS_MIME_FIELD_DATE, TS_MIME_LEN_DATE);
-+    if (date_loc != TS_NULL_MLOC)
-     {
--        date_loc = TSMimeHdrFieldFind(buf, hdr_loc, TS_MIME_FIELD_DATE, TS_MIME_LEN_DATE);
--        if (date_loc != TS_NULL_MLOC)
--        {
--            date = TSMimeHdrFieldValueDateGet(buf, hdr_loc, date_loc);
--             TSHandleMLocRelease(buf, hdr_loc, date_loc);
--        }
--        TSHandleMLocRelease(buf, TS_NULL_MLOC, hdr_loc);
-+      date = TSMimeHdrFieldValueDateGet(buf, hdr_loc, date_loc);
-+      TSHandleMLocRelease(buf, hdr_loc, date_loc);
-     }
-+    TSHandleMLocRelease(buf, TS_NULL_MLOC, hdr_loc);
-+  }
- 
--    return date;
-+  return date;
- }
- 
- static int
- main_handler(TSCont cont, TSEvent event, void *edata)
- {
--    TSHttpTxn txn = (TSHttpTxn) edata;
--    int status;
--    invalidate_t *iptr;
--    plugin_state_t *pstate;
--
--    time_t date = 0, now = 0;
--    char *url = NULL;
--    int url_len = 0;
--
--    switch (event)
-+  TSHttpTxn txn = (TSHttpTxn) edata;
-+  int status;
-+  invalidate_t *iptr;
-+
-+  time_t date = 0, now = 0;
-+  char *url = NULL;
-+  int url_len = 0;
-+
-+  switch (event)
-+  {
-+  case TS_EVENT_HTTP_CACHE_LOOKUP_COMPLETE:
-+    if (TSHttpTxnCacheLookupStatusGet(txn, &status) == TS_SUCCESS)
-     {
--        case TS_EVENT_HTTP_CACHE_LOOKUP_COMPLETE:
--            if (TSHttpTxnCacheLookupStatusGet(txn, &status) == TS_SUCCESS)
-+      if (status == TS_CACHE_LOOKUP_HIT_FRESH)
-+      {
-+        iptr = get_config(cont);
-+        while (iptr)
-+        {
-+          if (!date)
-+          {
-+            date = get_date_from_cached_hdr(txn);
-+            now = time(NULL);
-+          }
-+          if ((difftime(iptr->epoch, date) >= 0) && (difftime(iptr->expiry, now) >= 0))
-+          {
-+            if (!url)
-+              url = TSHttpTxnEffectiveUrlStringGet(txn, &url_len);
-+            if (pcre_exec(iptr->regex, iptr->regex_extra, url, url_len, 0, 0, NULL, 0) >= 0)
-             {
--                if (status == TS_CACHE_LOOKUP_HIT_FRESH)
--                {
--                    pstate = (plugin_state_t *) TSContDataGet(cont);
--                    iptr = pstate->invalidate_list;
--                    while (iptr)
--                    {
--                        if (!date)
--                        {
--                            date = get_date_from_cached_hdr(txn);
--                            now = time(NULL);
--                        }
--                        if ((difftime(iptr->epoch, date) >= 0) && (difftime(iptr->expiry, now) >= 0))
--                        {
--                            if (!url)
--                                url = TSHttpTxnEffectiveUrlStringGet(txn, &url_len);
--                            if (pcre_exec(iptr->regex, iptr->regex_extra, url, url_len, 0, 0, NULL, 0) >= 0)
--                            {
--                                TSHttpTxnCacheLookupStatusSet(txn, TS_CACHE_LOOKUP_HIT_STALE);
--                                iptr = NULL;
--                                TSDebug(LOG_PREFIX, "Forced revalidate - %.*s", url_len, url);
--                            }
--                        }
--                        if (iptr)
--                            iptr = iptr->next;
--                    }
--                    if (url)
--                        TSfree(url);
--                }
-+              TSHttpTxnCacheLookupStatusSet(txn, TS_CACHE_LOOKUP_HIT_STALE);
-+              iptr = NULL;
-+              TSDebug(PLUGIN_TAG, "Forced revalidate - %.*s", url_len, url);
-             }
--            break;
--        default:
--            break;
-+          }
-+          if (iptr)
-+            iptr = iptr->next;
-+        }
-+        if (url)
-+          TSfree(url);
-+      }
-     }
-+    break;
-+  default:
-+    break;
-+  }
- 
--    TSHttpTxnReenable(txn, TS_EVENT_HTTP_CONTINUE);
--    return 0;
-+  TSHttpTxnReenable(txn, TS_EVENT_HTTP_CONTINUE);
-+  return 0;
- }
- 
- static bool
- check_ts_version()
- {
--    const char *ts_version = TSTrafficServerVersionGet();
-+  const char *ts_version = TSTrafficServerVersionGet();
- 
--    if (ts_version)
--    {
--        int major_ts_version = 0;
--        int minor_ts_version = 0;
--        int micro_ts_version = 0;
-+  if (ts_version)
-+  {
-+    int major_ts_version = 0;
-+    int minor_ts_version = 0;
-+    int micro_ts_version = 0;
- 
--        if (sscanf(ts_version, "%d.%d.%d", &major_ts_version, &minor_ts_version, &micro_ts_version) != 3)
--        {
--            return false;
--        }
-+    if (sscanf(ts_version, "%d.%d.%d", &major_ts_version, &minor_ts_version, &micro_ts_version) != 3)
-+    {
-+      return false;
-+    }
- 
--        if ((TS_VERSION_MAJOR == major_ts_version) && (TS_VERSION_MINOR == minor_ts_version) && (TS_VERSION_MICRO == micro_ts_version))
--        {
--            return true;
--        }
-+    if ((TS_VERSION_MAJOR == major_ts_version) && (TS_VERSION_MINOR == minor_ts_version) && (TS_VERSION_MICRO == micro_ts_version))
-+    {
-+      return true;
-     }
-+  }
- 
--    return false;
-+  return false;
- }
- 
- void
- TSPluginInit (int argc, const char *argv[])
- {
--    TSPluginRegistrationInfo info;
--    TSCont main_cont, config_cont;
--    plugin_state_t *pstate;
--    invalidate_t *iptr = NULL;
--
--    TSDebug(LOG_PREFIX, "Starting plugin init.");
--
--    pstate = (plugin_state_t *) TSmalloc(sizeof(plugin_state_t));
--    init_plugin_state_t(pstate);
--
--    int c;
--    optind = 1;
--    static const struct option longopts[] = {
--            { "config", required_argument, NULL, 'c' },
--            { "log", required_argument, NULL, 'l' },
--            { NULL, 0, NULL, 0 }
--        };
-+  TSPluginRegistrationInfo info;
-+  TSCont main_cont, config_cont;
-+  config_holder_t* config_holder;
-+  char* path = NULL;
-+
-+  TSDebug(PLUGIN_TAG, "Starting plugin init.");
-+
-+  config_holder = new_config_holder();
-+
-+  int c;
-+  optind = 1;
-+  static const struct option longopts[] = {
-+      { "config", required_argument, NULL, 'c' },
-+      { "log", required_argument, NULL, 'l' },
-+      { NULL, 0, NULL, 0 }
-+  };
-+
-+  while ((c = getopt_long(argc, (char * const*) argv, "c:l:", longopts, NULL)) != -1)
-+  {
-+    switch (c)
-+    {
-+    case 'c':
-+      path = TSstrdup(optarg);
-+      break;
-+    case 'l':
-+      TSTextLogObjectCreate(optarg, TS_LOG_MODE_ADD_TIMESTAMP, &config_holder->log);
-+      TSTextLogObjectRollingEnabledSet(config_holder->log, 1);
-+      TSTextLogObjectRollingIntervalSecSet(config_holder->log, LOG_ROLL_INTERVAL);
-+      TSTextLogObjectRollingOffsetHrSet(config_holder->log, LOG_ROLL_OFFSET);
-+      break;
-+    default:
-+      break;
-+    }
-+  }
-+  config_holder = init_config_holder(config_holder, path);
-+
-+  if (!config_holder->config_path)
-+  {
-+    TSError("Plugin requires a --config option along with a config file name.");
-+    free_config_holder_t(config_holder);
-+    return;
-+  }
-+
-+  //    if (!load_config(free_config_holder_t, &iptr))
-+  if(config_holder->config)
-+    TSDebug(PLUGIN_TAG, "Problem loading config from file %s", config_holder->config_path);
-+  else
-+  {
-+    //        config_holder->config = iptr;
-+    list_config(config_holder, config_holder->config);
-+  }
-+
-+  info.plugin_name = PLUGIN_TAG;
-+  info.vendor_name = "Apache Software Foundation";
-+  info.support_email = "dev@trafficserver.apache.org";
-+
-+  if (TSPluginRegister(TS_SDK_VERSION_3_0 , &info) != TS_SUCCESS)
-+  {
-+    TSError("Plugin registration failed.");
-+    free_config_holder_t(config_holder);
-+    return;
-+  }
-+  else
-+    TSDebug(PLUGIN_TAG, "Plugin registration succeeded.");
-+
-+  if (!check_ts_version())
-+  {
-+    TSError("Plugin requires Traffic Server %d.%d.%d", TS_VERSION_MAJOR, TS_VERSION_MINOR, TS_VERSION_MICRO);
-+    free_config_holder_t(config_holder);
-+    return;
-+  }
-+
-+  pcre_malloc = &ts_malloc;
-+  pcre_free = &ts_free;
-+
-+  main_cont = TSContCreate(main_handler, NULL);
-+  TSContDataSet(main_cont, (void *) config_holder);
-+  TSHttpHookAdd(TS_HTTP_CACHE_LOOKUP_COMPLETE_HOOK, main_cont);
-+
-+  config_cont = TSContCreate(config_pruner, TSMutexCreate());
-+  TSContDataSet(config_cont, (void *) config_holder);
-+  TSContSchedule(config_cont, PRUNE_TMOUT, TS_THREAD_POOL_TASK);
-+
-+  config_cont = TSContCreate(config_handler, TSMutexCreate());
-+  TSContDataSet(config_cont, (void *) config_holder);
-+  TSMgmtUpdateRegister(config_cont, PLUGIN_TAG);
-+
-+  TSDebug(PLUGIN_TAG, "Plugin Init Complete.");
-+}
- 
--    while ((c = getopt_long(argc, (char * const*) argv, "c:l:", longopts, NULL)) != -1)
-+static config_t*
-+new_config(TSFile fs) {
-+  char line[LINE_MAX];
-+  time_t now;
-+  pcre *config_re;
-+  const char *errptr;
-+  int erroffset, ovector[OVECTOR_SIZE], rc;
-+  int ln = 0;
-+  invalidate_t *iptr, *i, *config=0;
-+
-+  now = time(NULL);
-+
-+  config_re = pcre_compile("^([^#].+?)\\s+(\\d+)\\s*$", 0, &errptr, &erroffset, NULL);
-+  while (TSfgets(fs, line, LINE_MAX-1) != NULL)
-+  {
-+    ln++;
-+    TSDebug(PLUGIN_TAG, "Processing: %d %s", ln, line);
-+    rc = pcre_exec(config_re, NULL, line, strlen(line), 0, 0, ovector, OVECTOR_SIZE);
-+    if (rc == 3)
-     {
--        switch (c)
-+      i = (invalidate_t *) TSmalloc(sizeof(invalidate_t));
-+      init_invalidate_t(i);
-+      pcre_get_substring(line, ovector, rc, 1, &i->regex_text);
-+      i->epoch = now;
-+      i->expiry = atoi(line + ovector[4]);
-+      i->regex = pcre_compile(i->regex_text, 0, &errptr, &erroffset, NULL);
-+      if (i->expiry <= i->epoch)
-+      {
-+        TSDebug(PLUGIN_TAG, "NOT Loaded, already expired! %s %d %d", i->regex_text, (int) i->epoch, (int) i->expiry);
-+        TSError(PLUGIN_TAG " - NOT Loaded, already expired: %s %d %d", i->regex_text, (int) i->epoch, (int) i->expiry);
-+        free_invalidate_t(i);
-+      }
-+      else if (i->regex == NULL)
-+      {
-+        TSDebug(PLUGIN_TAG, "%s did not compile", i->regex_text);
-+        free_invalidate_t(i);
-+      }
-+      else
-+      {
-+        i->regex_extra = pcre_study(i->regex, 0, &errptr);
-+        if (!config)
-         {
--            case 'c':
--                pstate->config_file = TSstrdup(optarg);
--                break;
--            case 'l':
--                TSTextLogObjectCreate(optarg, TS_LOG_MODE_ADD_TIMESTAMP, &pstate->log);
--                TSTextLogObjectRollingEnabledSet(pstate->log, 1);
--                TSTextLogObjectRollingIntervalSecSet(pstate->log, LOG_ROLL_INTERVAL);
--                TSTextLogObjectRollingOffsetHrSet(pstate->log, LOG_ROLL_OFFSET);
--                break;
--            default:
--                break;
-+          config = i;
-+          TSDebug(PLUGIN_TAG, "Created new list and Loaded %s %d %d", i->regex_text, (int) i->epoch, (int) i->expiry);
-+          TSError(PLUGIN_TAG " - New Revalidate: %s %d %d", i->regex_text, (int) i->epoch, (int) i->expiry);
-+        }
-+        else
-+        {
-+          iptr = config;
-+          while(1)
-+          {
-+            if (strcmp(i->regex_text, iptr->regex_text) == 0)
-+            {
-+              if (iptr->expiry != i->expiry)
-+              {
-+                TSDebug(PLUGIN_TAG, "Updating duplicate %s", i->regex_text);
-+                iptr->epoch = i->epoch;
-+                iptr->expiry = i->expiry;
-+              }
-+              free_invalidate_t(i);
-+              i = NULL;
-+              break;
-+            }
-+            else if (!iptr->next)
-+              break;
-+            else
-+              iptr = iptr->next;
-+          }
-+          if (i)
-+          {
-+            iptr->next = i;
-+            TSDebug(PLUGIN_TAG, "Loaded %s %d %d", i->regex_text, (int) i->epoch, (int) i->expiry);
-+          }
-         }
-+      }
-     }
-+    else
-+      TSDebug(PLUGIN_TAG, "Skipping line %d", ln);
-+  }
-+  pcre_free(config_re);
- 
--    if (!pstate->config_file)
--    {
--        TSError("Plugin requires a --config option along with a config file name.");
--        free_plugin_state_t(pstate);
--        return;
--    }
-+  return config;
-+}
- 
--    if (!load_config(pstate, &iptr))
--        TSDebug(LOG_PREFIX, "Problem loading config from file %s", pstate->config_file);
--    else
--    {
--        pstate->invalidate_list = iptr;
--        list_config(pstate, iptr);
--    }
-+static void
-+delete_config(config_t* config) {
-+  TSDebug(PLUGIN_TAG, "Freeing config");
-+  free_invalidate_t_list(config);
-+}
- 
--    info.plugin_name = LOG_PREFIX;
--    info.vendor_name = "Apache Software Foundation";
--    info.support_email = "dev@trafficserver.apache.org";
-+static int
-+free_invalidate_handler(TSCont cont, TSEvent event ATS_UNUSED, void *edata ATS_UNUSED) {
-+  invalidate_t* i = (invalidate_t *) TSContDataGet(cont);
-+  free_invalidate_t(i);
-+  TSContDestroy(cont);
-+  return 0;
-+}
- 
--    if (TSPluginRegister(TS_SDK_VERSION_3_0 , &info) != TS_SUCCESS)
--    {
--        TSError("Plugin registration failed.");
--        free_plugin_state_t(pstate);
--        return;
--    }
--    else
--        TSDebug(LOG_PREFIX, "Plugin registration succeeded.");
-+static void
-+schedule_free_invalidate_t(invalidate_t * iptr) {
-+  TSCont free_cont;
-+  free_cont = TSContCreate(free_invalidate_handler, NULL);
-+  TSContDataSet(free_cont, (void *) iptr);
-+  TSContSchedule(free_cont, FREE_TMOUT, TS_THREAD_POOL_TASK);
-+  return;
-+}
- 
--    if (!check_ts_version())
--    {
--        TSError("Plugin requires Traffic Server %d.%d.%d", TS_VERSION_MAJOR, TS_VERSION_MINOR, TS_VERSION_MICRO);
--        free_plugin_state_t(pstate);
--        return;
-+static config_t*
-+get_config(TSCont cont) {
-+  config_holder_t* configh = (config_holder_t *) TSContDataGet(cont);
-+  if(!configh) {
-+    return 0;
-+  }
-+  return configh->config;
-+}
-+
-+static void
-+load_config_file(config_holder_t *config_holder) {
-+  TSFile fh;
-+  struct stat s;
-+
-+  config_t *newconfig, *oldconfig;
-+  TSCont free_cont;
-+
-+  // check date
-+  if (stat(config_holder->config_path, &s) < 0) {
-+    TSDebug(PLUGIN_TAG, "Could not stat %s", config_holder->config_path);
-+    if(config_holder->config) {
-+      return;
-+    }
-+  } else {
-+    TSDebug(PLUGIN_TAG, "s.st_mtime=%lu, last_load=%lu", s.st_mtime, config_holder->last_load);
-+    if (s.st_mtime < config_holder->last_load) {
-+      return;
-     }
-+  }
-+
-+  TSDebug(PLUGIN_TAG, "Opening config file: %s", config_holder->config_path);
-+  fh = TSfopen(config_holder->config_path, "r");
-+  TSError(PLUGIN_TAG " - Reading config: %s", config_holder->config_path);
-+
-+  if (!fh) {
-+    TSError("[%s] Unable to open config: %s.\n",
-+        PLUGIN_TAG, config_holder->config_path);
-+    return;
-+  }
-+
-+  newconfig = 0;
-+  newconfig = new_config(fh);
-+  if(newconfig) {
-+    config_holder->last_load = time(NULL);
-+    config_t ** confp = &(config_holder->config);
-+    oldconfig = __sync_lock_test_and_set(confp, newconfig);
-+    if (oldconfig) {
-+      TSDebug(PLUGIN_TAG, "scheduling free: %p (%p)", oldconfig, newconfig);
-+      free_cont = TSContCreate(free_handler, NULL);
-+      TSContDataSet(free_cont, (void *) oldconfig);
-+      TSContSchedule(free_cont, FREE_TMOUT, TS_THREAD_POOL_TASK);
-+    }
-+  }
-+  if(fh)
-+    TSfclose(fh);
-+  return;
-+}
- 
--    pcre_malloc = &ts_malloc;
--    pcre_free = &ts_free;
-+static config_holder_t*
-+new_config_holder(void) {
-+  config_holder_t* config_holder = TSmalloc(sizeof(config_holder_t));
-+  return config_holder;
-+}
- 
--    main_cont = TSContCreate(main_handler, NULL);
--    TSContDataSet(main_cont, (void *) pstate);
--    TSHttpHookAdd(TS_HTTP_CACHE_LOOKUP_COMPLETE_HOOK, main_cont);
-+static config_holder_t*
-+init_config_holder(config_holder_t* config_holder, const char* path) {
-+  int path_len = 0;
-+  config_holder->config_path = 0;
-+  config_holder->config = 0;
-+  config_holder->last_load = 0;
-+  config_holder->log = 0;
-+
-+  if(!path) path = DEFAULT_CONFIG_NAME;
-+  if (path[0] != '/')
-+  {
-+    path_len = strlen(TSConfigDirGet()) + strlen(path) + 2;
-+    config_holder->config_path = ts_malloc(path_len);
-+    snprintf(config_holder->config_path, path_len, "%s/%s", TSConfigDirGet(), path);
-+    TSDebug(PLUGIN_TAG, "path: '%s' len=%d", config_holder->config_path, path_len);
-+  } else
-+    config_holder->config_path = TSstrdup(path);
-+
-+  load_config_file(config_holder);
-+  return config_holder;
-+}
- 
--    config_cont = TSContCreate(config_handler, TSMutexCreate());
--    TSContDataSet(config_cont, (void *) pstate);
--    TSContSchedule(config_cont, CONFIG_TMOUT, TS_THREAD_POOL_TASK);
-+static void
-+free_config_holder_t(config_holder_t *config_holder)
-+{
-+  if (config_holder->config)
-+    free_invalidate_t_list(config_holder->config);
-+  if (config_holder->config_path)
-+    TSfree(config_holder->config_path);
-+  if (config_holder->log)
-+    TSTextLogObjectDestroy(config_holder->log);
-+  TSfree(config_holder);
-+}
-+
-+static int
-+free_handler(TSCont cont, TSEvent event ATS_UNUSED, void *edata ATS_UNUSED) {
-+  config_t *config;
-+
-+  TSDebug(PLUGIN_TAG, "Freeing old config");
-+  config = (config_t *) TSContDataGet(cont);
-+  delete_config(config);
-+  TSContDestroy(cont);
-+  return 0;
-+}
-+
-+static int
-+config_handler(TSCont cont, TSEvent event ATS_UNUSED, void *edata ATS_UNUSED) {
-+  config_holder_t *config_holder;
- 
--    TSDebug(LOG_PREFIX, "Plugin Init Complete.");
-+  TSDebug(PLUGIN_TAG, "In config Handler");
-+  config_holder = (config_holder_t *) TSContDataGet(cont);
-+  load_config_file(config_holder);
-+  return 0;
- }
-diff --git a/plugins/experimental/remap_stats/remap_stats.c b/plugins/experimental/remap_stats/remap_stats.c
-index 5efd52d..0d78bab 100644
---- a/plugins/experimental/remap_stats/remap_stats.c
-+++ b/plugins/experimental/remap_stats/remap_stats.c
-@@ -43,7 +43,6 @@ typedef struct
-   TSMutex stat_creation_mutex;
- } config_t;
- 
--
- static void
- stat_add(char *name, TSMgmtInt amount, TSStatPersistence persist_type, TSMutex create_mutex)
- {
-@@ -91,7 +90,6 @@ stat_add(char *name, TSMgmtInt amount, TSStatPersistence persist_type, TSMutex c
-     TSDebug(DEBUG_TAG, "stat error! stat_name: %s stat_id: %d", name, stat_id);
- }
- 
--
- static char *
- get_effective_host(TSHttpTxn txn)
- {
-@@ -114,7 +112,6 @@ get_effective_host(TSHttpTxn txn)
-   return tmp;
- }
- 
--
- static int
- handle_read_req_hdr(TSCont cont, TSEvent event ATS_UNUSED, void *edata)
- {
-@@ -131,7 +128,6 @@ handle_read_req_hdr(TSCont cont, TSEvent event ATS_UNUSED, void *edata)
-   return 0;
- }
- 
--
- static int
- handle_post_remap(TSCont cont, TSEvent event ATS_UNUSED, void *edata)
- {
-@@ -153,10 +149,8 @@ handle_post_remap(TSCont cont, TSEvent event ATS_UNUSED, void *edata)
-   return 0;
- }
- 
--
- #define CREATE_STAT_NAME(s,h,b) snprintf(s, MAX_STAT_LENGTH, "plugin.%s.%s.%s", PLUGIN_NAME, h, b)
- 
--
- static int
- handle_txn_close(TSCont cont, TSEvent event ATS_UNUSED, void *edata)
- {
-diff --git a/plugins/experimental/stale_while_revalidate/stale_while_revalidate.c b/plugins/experimental/stale_while_revalidate/stale_while_revalidate.c
-index 4b3ba98..2a4e363 100644
---- a/plugins/experimental/stale_while_revalidate/stale_while_revalidate.c
-+++ b/plugins/experimental/stale_while_revalidate/stale_while_revalidate.c
-@@ -293,6 +293,7 @@ consume_resource(TSCont cont, TSEvent event ATS_UNUSED, void *edata ATS_UNUSED)
-         case TS_EVENT_VCONN_WRITE_READY:
-             // We shouldn't get here because we specify the exact size of the buffer.
-             TSDebug(PLUGIN_NAME, "Write Ready");
-+            break;
-         case TS_EVENT_VCONN_WRITE_COMPLETE:
-             TSDebug(PLUGIN_NAME, "Write Complete");
-             //TSDebug(PLUGIN_NAME, "TSVConnShutdown()");
-@@ -509,6 +510,8 @@ main_plugin(TSCont cont, TSEvent event, void *edata)
-     TSHttpStatus http_status;
-     config_t *plugin_config;
- 
-+    TSDebug(PLUGIN_NAME, "main_plugin: %d", event);
-+
-     switch (event)
-     {
-         // Is this the proper event?
-@@ -651,6 +654,7 @@ main_plugin(TSCont cont, TSEvent event, void *edata)
-             TSHttpTxnReenable(txn, TS_EVENT_HTTP_CONTINUE);
-             break;
-         default:
-+            TSDebug(PLUGIN_NAME, "unknown event: %d", event);
-             TSHttpTxnReenable(txn, TS_EVENT_HTTP_CONTINUE);
-             break;
-     }
-@@ -674,10 +678,8 @@ TSPluginInit (int argc, const char *argv[])
-         TSError("Plugin registration failed.\n");
-         return;
-     }
--    else
--    {
--        TSDebug(PLUGIN_NAME, "Plugin registration succeeded.\n");
--    }
-+
-+    TSDebug(PLUGIN_NAME, "Plugin registration succeeded.\n");
- 
-     plugin_config = TSmalloc(sizeof(config_t));
- 
-@@ -736,6 +738,7 @@ TSPluginInit (int argc, const char *argv[])
-     main_cont = TSContCreate(main_plugin, NULL);
-     TSContDataSet(main_cont, (void *) plugin_config);
-     TSHttpHookAdd(TS_HTTP_READ_REQUEST_HDR_HOOK, main_cont);
-+//    TSHttpHookAdd(TS_HTTP_SELECT_ALT_HOOK, main_cont);
- 
-     TSDebug(PLUGIN_NAME, "Plugin Init Complete.\n");
- }
-diff --git a/plugins/experimental/url_sig/url_sig.c b/plugins/experimental/url_sig/url_sig.c
-index e063791..f5742bb 100644
---- a/plugins/experimental/url_sig/url_sig.c
-+++ b/plugins/experimental/url_sig/url_sig.c
-@@ -31,18 +31,24 @@
- #include <limits.h>
- #include <ctype.h>
- 
-+#ifdef HAVE_PCRE_PCRE_H
-+#include <pcre/pcre.h>
-+#else
-+#include <pcre.h>
-+#endif
-+
- #include <ts/ts.h>
- #include <ts/remap.h>
- 
--static const char *PLUGIN_NAME = "url_sig";
-+#define PLUGIN_NAME "url_sig"
- 
- struct config
- {
--  char *map_from;
--  char *map_to;
-   TSHttpStatus err_status;
-   char *err_url;
-   char keys[MAX_KEY_NUM][MAX_KEY_LEN];
-+  pcre *regex;
-+  pcre_extra *regex_extra;
- };
- 
- TSReturnCode
-@@ -68,25 +74,21 @@ TSReturnCode
- TSRemapNewInstance(int argc, char *argv[], void **ih, char *errbuf, int errbuf_size)
- {
-   char config_file[PATH_MAX];
-+  int i;
-   struct config *cfg;
- 
-   cfg = TSmalloc(sizeof(struct config));
-+  memset(cfg, 0, sizeof(struct config));
-   *ih = (void *) cfg;
- 
--  int i = 0;
--  for (i = 0; i < MAX_KEY_NUM; i++) {
--    cfg->keys[i][0] = '\0';
--  }
--
-   if (argc != 3) {
-     snprintf(errbuf, errbuf_size - 1,
-              "[TSRemapNewKeyInstance] - Argument count wrong (%d)... Need exactly two pparam= (config file name).",
-              argc);
-     return TS_ERROR;
-   }
-+
-   TSDebug(PLUGIN_NAME, "Initializing remap function of %s -> %s with config from %s", argv[0], argv[1], argv[2]);
--  cfg->map_from = TSstrndup(argv[0], strlen(argv[0]));
--  cfg->map_to = TSstrndup(argv[0], strlen(argv[1]));
- 
-   const char *install_dir = TSInstallDirGet();
-   snprintf(config_file, sizeof(config_file), "%s/%s/%s", install_dir, "etc/trafficserver", argv[2]);
-@@ -157,6 +159,25 @@ TSRemapNewInstance(int argc, char *argv[], void **ih, char *errbuf, int errbuf_s
-         cfg->err_url = TSstrndup(value, strlen(value));
-       else
-         cfg->err_url = NULL;
-+    } else if (strncmp(line, "excl_regex", 10) == 0) {
-+      // compile and study regex
-+      const char *errptr;
-+      int erroffset, options = 0;
-+
-+      if (cfg->regex) {
-+        TSDebug(PLUGIN_NAME, "Skipping duplicate excl_regex");
-+        continue;
-+      }
-+
-+      cfg->regex = pcre_compile(value, options, &errptr, &erroffset, NULL);
-+      if (cfg->regex == NULL) {
-+        TSDebug(PLUGIN_NAME, "Regex compilation failed with error (%s) at character %d.", errptr, erroffset);
-+      } else {
-+#ifdef PCRE_STUDY_JIT_COMPILE
-+        options = PCRE_STUDY_JIT_COMPILE;
-+#endif
-+        cfg->regex_extra = pcre_study(cfg->regex, options, &errptr); // We do not need to check the error here because we can still run without the studying?
-+      }
-     } else {
-       TSError("Error parsing line %d of file %s (%s).", line_no, config_file, line);
-     }
-@@ -199,13 +220,22 @@ TSRemapDeleteInstance(void *ih)
-   cfg = (struct config *) ih;
- 
-   TSError("Cleaning up...");
--  TSfree(cfg->map_from);
--  TSfree(cfg->map_to);
-   TSfree(cfg->err_url);
-+
-+  if (cfg->regex_extra)
-+#ifndef PCRE_STUDY_JIT_COMPILE
-+    pcre_free(cfg->regex_extra);
-+#else
-+    pcre_free_study(cfg->regex_extra);
-+#endif
-+
-+  if (cfg->regex)
-+        pcre_free(cfg->regex);
-+
-   TSfree(cfg);
- }
- 
--void
-+static void
- err_log(char *url, char *msg)
- {
-   if (msg && url) {
-@@ -262,6 +292,24 @@ TSRemapDoRemap(void *ih, TSHttpTxn txnp, TSRemapRequestInfo * rri)
-   TSDebug(PLUGIN_NAME, "%s", url);
- 
-   query = strstr(url, "?");
-+
-+  if (cfg->regex) {
-+    int offset = 0, options = 0;
-+    int ovector[30];
-+    int len = url_len;
-+    char *anchor = strstr(url, "#");
-+    if (query && !anchor) {
-+      len -= (query - url);
-+    } else if (anchor && !query) {
-+      len -= (anchor - url);
-+    } else if (anchor && query) {
-+      len -= ((query < anchor ? query : anchor) - url);
-+    }
-+    if (pcre_exec(cfg->regex, cfg->regex_extra, url, len, offset, options, ovector, 30) >= 0) {
-+      goto allow;
-+    }
-+  }
-+
-   if (query == NULL) {
-     err_log(url, "Has no query string.");
-     goto deny;
-diff --git a/plugins/header_rewrite/Examples/header_rewrite.config b/plugins/header_rewrite/Examples/header_rewrite.config
-new file mode 100644
-index 0000000..c1aa7a2
---- /dev/null
-+++ b/plugins/header_rewrite/Examples/header_rewrite.config
-@@ -0,0 +1,3 @@
-+include header_rewrite/Regression
-+include header_rewrite/YCS-EC
-+#include header_rewrite/Force-close
-diff --git a/plugins/header_rewrite/Makefile.am b/plugins/header_rewrite/Makefile.am
-index 4a6ca58..bd09044 100644
---- a/plugins/header_rewrite/Makefile.am
-+++ b/plugins/header_rewrite/Makefile.am
-@@ -28,6 +28,7 @@ header_rewrite_la_SOURCES = \
-   operator.cc \
-   operators.cc \
-   parser.cc \
-+  pluginconfig.cc \
-   regex_helper.cc \
-   resources.cc \
-   ruleset.cc \
-diff --git a/plugins/header_rewrite/conditions.cc b/plugins/header_rewrite/conditions.cc
-index be3d28b..04fb456 100644
---- a/plugins/header_rewrite/conditions.cc
-+++ b/plugins/header_rewrite/conditions.cc
-@@ -72,6 +72,49 @@ ConditionStatus::append_value(std::string& s, const Resources& res)
- }
- 
- 
-+// ConditionMethod
-+void
-+ConditionMethod::initialize(Parser& p)
-+{
-+  Condition::initialize(p);
-+
-+  Matchers<std::string>* match = new Matchers<std::string>(_cond_op);
-+  match->set(p.get_arg());
-+
-+  _matcher = match;
-+}
-+
-+bool
-+ConditionMethod::eval(const Resources& res)
-+{
-+  std::string s;
-+
-+  append_value(s, res);
-+  bool rval = static_cast<const Matchers<std::string>*>(_matcher)->test(s);
-+  TSDebug(PLUGIN_NAME, "Evaluating METHOD(): %s - rval: %d", s.c_str(), rval);
-+  return rval;
-+}
-+
-+
-+void
-+ConditionMethod::append_value(std::string& s, const Resources& res)
-+{
-+  TSMBuffer bufp;
-+  TSMLoc hdr_loc;
-+  const char* value;
-+  int len;
-+
-+  bufp = res.client_bufp;
-+  hdr_loc = res.client_hdr_loc;
-+
-+  if (bufp && hdr_loc) {
-+    value = TSHttpHdrMethodGet(bufp, hdr_loc, &len);
-+    TSDebug(PLUGIN_NAME, "Appending METHOD(%s) to evaluation value -> %.*s", _qualifier.c_str(), len, value);
-+    s.append(value, len);
-+  }
-+}
-+
-+
- // ConditionRandom: random 0 to (N-1)
- void
- ConditionRandom::initialize(Parser& p)
-diff --git a/plugins/header_rewrite/conditions.h b/plugins/header_rewrite/conditions.h
-index fbb843d..f540df1 100644
---- a/plugins/header_rewrite/conditions.h
-+++ b/plugins/header_rewrite/conditions.h
-@@ -101,6 +101,25 @@ private:
- };
- 
- 
-+// Check the HTTP method
-+class ConditionMethod : public Condition
-+{
-+public:
-+  ConditionMethod()
-+  {
-+    TSDebug(PLUGIN_NAME_DBG, "Calling CTOR for ConditionMethod");
-+  }
-+  void initialize(Parser& p);
-+  void append_value(std::string& s, const Resources& res);
-+
-+protected:
-+  bool eval(const Resources& res);
-+
-+private:
-+  DISALLOW_COPY_AND_ASSIGN(ConditionMethod);
-+};
-+
-+
- // Random 0 to (N-1)
- class ConditionRandom : public Condition
- {
-diff --git a/plugins/header_rewrite/factory.cc b/plugins/header_rewrite/factory.cc
-index eb44369..2db74df 100644
---- a/plugins/header_rewrite/factory.cc
-+++ b/plugins/header_rewrite/factory.cc
-@@ -59,6 +59,8 @@ operator_factory(const std::string& op)
-     o = new OperatorCounter();
-   } else if (op == "set-conn-dscp") {
-     o = new OperatorSetConnDSCP();
-+  } else if (op == "set-method") {
-+    o = new OperatorSetMethod();
-   } else {
-     TSError("%s: unknown operator: %s", PLUGIN_NAME, op.c_str());
-     return NULL;
-@@ -115,6 +117,8 @@ condition_factory(const std::string& cond)
-     c = new ConditionClientIp();
-   } else if (c_name == "INCOMING-PORT") {
-     c = new ConditionIncomingPort();
-+  } else if (c_name == "METHOD") {
-+    c = new ConditionMethod();
-   } else {
-     TSError("%s: unknown condition: %s", PLUGIN_NAME, c_name.c_str());
-     return NULL;
-diff --git a/plugins/header_rewrite/header_rewrite.cc b/plugins/header_rewrite/header_rewrite.cc
-index 1202545..f58cbd7 100644
---- a/plugins/header_rewrite/header_rewrite.cc
-+++ b/plugins/header_rewrite/header_rewrite.cc
-@@ -25,11 +25,14 @@
- #include "ruleset.h"
- #include "resources.h"
- 
-+#include "pluginconfig.h"
-+
- // Debugs
- const char PLUGIN_NAME[] = "header_rewrite";
- const char PLUGIN_NAME_DBG[] = "dbg_header_rewrite";
- 
- const char* HOOK_NAMES[] = {
-+  "TS_HTTP_TXN_START_HOOK",
-   "TS_HTTP_READ_REQUEST_HDR_HOOK",
-   "TS_HTTP_OS_DNS_HOOK",
-   "TS_HTTP_SEND_REQUEST_HDR_HOOK",
-@@ -47,26 +50,25 @@ const char* HOOK_NAMES[] = {
-   "TS_HTTP_PRE_REMAP_HOOK",
-   "TS_HTTP_POST_REMAP_HOOK",
-   "TS_HTTP_RESPONSE_CLIENT_HOOK",
-+  "TS_HTTP_TXN_CLOSE_HOOK",
-   "TS_HTTP_

<TRUNCATED>


[8/9] incubator-trafficcontrol git commit: Added license declarations for several components.

Posted by da...@apache.org.
Added license declarations for several components.

(cherry picked from commit eea627063719db33e62f7cc3fd56b27ce10fb248)


Project: http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/commit/45abd39c
Tree: http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/tree/45abd39c
Diff: http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/diff/45abd39c

Branch: refs/heads/1.8.x
Commit: 45abd39ccc0b76fb6b86fca252127678a9c9938c
Parents: 9cfbf92
Author: Chris Lemmons <Ch...@comcast.com>
Authored: Thu Jan 12 15:23:54 2017 -0700
Committer: Dan Kirkwood <da...@gmail.com>
Committed: Fri Jan 13 11:46:09 2017 -0700

----------------------------------------------------------------------
 LICENSE | 448 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 448 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/45abd39c/LICENSE
----------------------------------------------------------------------
diff --git a/LICENSE b/LICENSE
index 7da3bb4..db03aa5 100644
--- a/LICENSE
+++ b/LICENSE
@@ -841,3 +841,451 @@ For the avoidance of doubt, this Public License does not, and shall not be inter
 To the extent possible, if any provision of this Public License is deemed unenforceable, it shall be automatically reformed to the minimum extent necessary to make it enforceable. If the provision cannot be reformed, it shall be severed from this Public License without affecting the enforceability of the remaining terms and conditions.
 No term or condition of this Public License will be waived and no failure to comply consented to unless expressly agreed to by the Licensor.
 Nothing in this Public License constitutes or may be interpreted as a limitation upon, or waiver of, any privileges and immunities that apply to the Licensor or You, including from the legal processes of any jurisdiction or authority.
+
+For the NetPacket component:
+
+Copyright (c) 2003-2009 Joel Knight <kn...@gmail.com>
+
+Permission to use, copy, modify, and distribute this software for any
+purpose with or without fee is hereby granted, provided that the above
+copyright notice and this permission notice appear in all copies.
+
+THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+For the gofmt github hook:
+
+Copyright (c) 2009 The Go Authors. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+   * Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+   * Redistributions in binary form must reproduce the above
+copyright notice, this list of conditions and the following disclaimer
+in the documentation and/or other materials provided with the
+distribution.
+   * Neither the name of Google Inc. nor the names of its
+contributors may be used to endorse or promote products derived from
+this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+For the ssl-bundle.crt:
+
+This is derived from the Mozilla root CA list, which is licensed under
+the MPL, so the ssl-bundle.crt is likewise licensed under the MPL:
+
+Mozilla Public License Version 2.0
+==================================
+
+1. Definitions
+--------------
+
+1.1. "Contributor"
+    means each individual or legal entity that creates, contributes to
+    the creation of, or owns Covered Software.
+
+1.2. "Contributor Version"
+    means the combination of the Contributions of others (if any) used
+    by a Contributor and that particular Contributor's Contribution.
+
+1.3. "Contribution"
+    means Covered Software of a particular Contributor.
+
+1.4. "Covered Software"
+    means Source Code Form to which the initial Contributor has attached
+    the notice in Exhibit A, the Executable Form of such Source Code
+    Form, and Modifications of such Source Code Form, in each case
+    including portions thereof.
+
+1.5. "Incompatible With Secondary Licenses"
+    means
+
+    (a) that the initial Contributor has attached the notice described
+        in Exhibit B to the Covered Software; or
+
+    (b) that the Covered Software was made available under the terms of
+        version 1.1 or earlier of the License, but not also under the
+        terms of a Secondary License.
+
+1.6. "Executable Form"
+    means any form of the work other than Source Code Form.
+
+1.7. "Larger Work"
+    means a work that combines Covered Software with other material, in 
+    a separate file or files, that is not Covered Software.
+
+1.8. "License"
+    means this document.
+
+1.9. "Licensable"
+    means having the right to grant, to the maximum extent possible,
+    whether at the time of the initial grant or subsequently, any and
+    all of the rights conveyed by this License.
+
+1.10. "Modifications"
+    means any of the following:
+
+    (a) any file in Source Code Form that results from an addition to,
+        deletion from, or modification of the contents of Covered
+        Software; or
+
+    (b) any new file in Source Code Form that contains any Covered
+        Software.
+
+1.11. "Patent Claims" of a Contributor
+    means any patent claim(s), including without limitation, method,
+    process, and apparatus claims, in any patent Licensable by such
+    Contributor that would be infringed, but for the grant of the
+    License, by the making, using, selling, offering for sale, having
+    made, import, or transfer of either its Contributions or its
+    Contributor Version.
+
+1.12. "Secondary License"
+    means either the GNU General Public License, Version 2.0, the GNU
+    Lesser General Public License, Version 2.1, the GNU Affero General
+    Public License, Version 3.0, or any later versions of those
+    licenses.
+
+1.13. "Source Code Form"
+    means the form of the work preferred for making modifications.
+
+1.14. "You" (or "Your")
+    means an individual or a legal entity exercising rights under this
+    License. For legal entities, "You" includes any entity that
+    controls, is controlled by, or is under common control with You. For
+    purposes of this definition, "control" means (a) the power, direct
+    or indirect, to cause the direction or management of such entity,
+    whether by contract or otherwise, or (b) ownership of more than
+    fifty percent (50%) of the outstanding shares or beneficial
+    ownership of such entity.
+
+2. License Grants and Conditions
+--------------------------------
+
+2.1. Grants
+
+Each Contributor hereby grants You a world-wide, royalty-free,
+non-exclusive license:
+
+(a) under intellectual property rights (other than patent or trademark)
+    Licensable by such Contributor to use, reproduce, make available,
+    modify, display, perform, distribute, and otherwise exploit its
+    Contributions, either on an unmodified basis, with Modifications, or
+    as part of a Larger Work; and
+
+(b) under Patent Claims of such Contributor to make, use, sell, offer
+    for sale, have made, import, and otherwise transfer either its
+    Contributions or its Contributor Version.
+
+2.2. Effective Date
+
+The licenses granted in Section 2.1 with respect to any Contribution
+become effective for each Contribution on the date the Contributor first
+distributes such Contribution.
+
+2.3. Limitations on Grant Scope
+
+The licenses granted in this Section 2 are the only rights granted under
+this License. No additional rights or licenses will be implied from the
+distribution or licensing of Covered Software under this License.
+Notwithstanding Section 2.1(b) above, no patent license is granted by a
+Contributor:
+
+(a) for any code that a Contributor has removed from Covered Software;
+    or
+
+(b) for infringements caused by: (i) Your and any other third party's
+    modifications of Covered Software, or (ii) the combination of its
+    Contributions with other software (except as part of its Contributor
+    Version); or
+
+(c) under Patent Claims infringed by Covered Software in the absence of
+    its Contributions.
+
+This License does not grant any rights in the trademarks, service marks,
+or logos of any Contributor (except as may be necessary to comply with
+the notice requirements in Section 3.4).
+
+2.4. Subsequent Licenses
+
+No Contributor makes additional grants as a result of Your choice to
+distribute the Covered Software under a subsequent version of this
+License (see Section 10.2) or under the terms of a Secondary License (if
+permitted under the terms of Section 3.3).
+
+2.5. Representation
+
+Each Contributor represents that the Contributor believes its
+Contributions are its original creation(s) or it has sufficient rights
+to grant the rights to its Contributions conveyed by this License.
+
+2.6. Fair Use
+
+This License is not intended to limit any rights You have under
+applicable copyright doctrines of fair use, fair dealing, or other
+equivalents.
+
+2.7. Conditions
+
+Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted
+in Section 2.1.
+
+3. Responsibilities
+-------------------
+
+3.1. Distribution of Source Form
+
+All distribution of Covered Software in Source Code Form, including any
+Modifications that You create or to which You contribute, must be under
+the terms of this License. You must inform recipients that the Source
+Code Form of the Covered Software is governed by the terms of this
+License, and how they can obtain a copy of this License. You may not
+attempt to alter or restrict the recipients' rights in the Source Code
+Form.
+
+3.2. Distribution of Executable Form
+
+If You distribute Covered Software in Executable Form then:
+
+(a) such Covered Software must also be made available in Source Code
+    Form, as described in Section 3.1, and You must inform recipients of
+    the Executable Form how they can obtain a copy of such Source Code
+    Form by reasonable means in a timely manner, at a charge no more
+    than the cost of distribution to the recipient; and
+
+(b) You may distribute such Executable Form under the terms of this
+    License, or sublicense it under different terms, provided that the
+    license for the Executable Form does not attempt to limit or alter
+    the recipients' rights in the Source Code Form under this License.
+
+3.3. Distribution of a Larger Work
+
+You may create and distribute a Larger Work under terms of Your choice,
+provided that You also comply with the requirements of this License for
+the Covered Software. If the Larger Work is a combination of Covered
+Software with a work governed by one or more Secondary Licenses, and the
+Covered Software is not Incompatible With Secondary Licenses, this
+License permits You to additionally distribute such Covered Software
+under the terms of such Secondary License(s), so that the recipient of
+the Larger Work may, at their option, further distribute the Covered
+Software under the terms of either this License or such Secondary
+License(s).
+
+3.4. Notices
+
+You may not remove or alter the substance of any license notices
+(including copyright notices, patent notices, disclaimers of warranty,
+or limitations of liability) contained within the Source Code Form of
+the Covered Software, except that You may alter any license notices to
+the extent required to remedy known factual inaccuracies.
+
+3.5. Application of Additional Terms
+
+You may choose to offer, and to charge a fee for, warranty, support,
+indemnity or liability obligations to one or more recipients of Covered
+Software. However, You may do so only on Your own behalf, and not on
+behalf of any Contributor. You must make it absolutely clear that any
+such warranty, support, indemnity, or liability obligation is offered by
+You alone, and You hereby agree to indemnify every Contributor for any
+liability incurred by such Contributor as a result of warranty, support,
+indemnity or liability terms You offer. You may include additional
+disclaimers of warranty and limitations of liability specific to any
+jurisdiction.
+
+4. Inability to Comply Due to Statute or Regulation
+---------------------------------------------------
+
+If it is impossible for You to comply with any of the terms of this
+License with respect to some or all of the Covered Software due to
+statute, judicial order, or regulation then You must: (a) comply with
+the terms of this License to the maximum extent possible; and (b)
+describe the limitations and the code they affect. Such description must
+be placed in a text file included with all distributions of the Covered
+Software under this License. Except to the extent prohibited by statute
+or regulation, such description must be sufficiently detailed for a
+recipient of ordinary skill to be able to understand it.
+
+5. Termination
+--------------
+
+5.1. The rights granted under this License will terminate automatically
+if You fail to comply with any of its terms. However, if You become
+compliant, then the rights granted under this License from a particular
+Contributor are reinstated (a) provisionally, unless and until such
+Contributor explicitly and finally terminates Your grants, and (b) on an
+ongoing basis, if such Contributor fails to notify You of the
+non-compliance by some reasonable means prior to 60 days after You have
+come back into compliance. Moreover, Your grants from a particular
+Contributor are reinstated on an ongoing basis if such Contributor
+notifies You of the non-compliance by some reasonable means, this is the
+first time You have received notice of non-compliance with this License
+from such Contributor, and You become compliant prior to 30 days after
+Your receipt of the notice.
+
+5.2. If You initiate litigation against any entity by asserting a patent
+infringement claim (excluding declaratory judgment actions,
+counter-claims, and cross-claims) alleging that a Contributor Version
+directly or indirectly infringes any patent, then the rights granted to
+You by any and all Contributors for the Covered Software under Section
+2.1 of this License shall terminate.
+
+5.3. In the event of termination under Sections 5.1 or 5.2 above, all
+end user license agreements (excluding distributors and resellers) which
+have been validly granted by You or Your distributors under this License
+prior to termination shall survive termination.
+
+************************************************************************
+*                                                                      *
+*  6. Disclaimer of Warranty                                           *
+*  -------------------------                                           *
+*                                                                      *
+*  Covered Software is provided under this License on an "as is"       *
+*  basis, without warranty of any kind, either expressed, implied, or  *
+*  statutory, including, without limitation, warranties that the       *
+*  Covered Software is free of defects, merchantable, fit for a        *
+*  particular purpose or non-infringing. The entire risk as to the     *
+*  quality and performance of the Covered Software is with You.        *
+*  Should any Covered Software prove defective in any respect, You     *
+*  (not any Contributor) assume the cost of any necessary servicing,   *
+*  repair, or correction. This disclaimer of warranty constitutes an   *
+*  essential part of this License. No use of any Covered Software is   *
+*  authorized under this License except under this disclaimer.         *
+*                                                                      *
+************************************************************************
+
+************************************************************************
+*                                                                      *
+*  7. Limitation of Liability                                          *
+*  --------------------------                                          *
+*                                                                      *
+*  Under no circumstances and under no legal theory, whether tort      *
+*  (including negligence), contract, or otherwise, shall any           *
+*  Contributor, or anyone who distributes Covered Software as          *
+*  permitted above, be liable to You for any direct, indirect,         *
+*  special, incidental, or consequential damages of any character      *
+*  including, without limitation, damages for lost profits, loss of    *
+*  goodwill, work stoppage, computer failure or malfunction, or any    *
+*  and all other commercial damages or losses, even if such party      *
+*  shall have been informed of the possibility of such damages. This   *
+*  limitation of liability shall not apply to liability for death or   *
+*  personal injury resulting from such party's negligence to the       *
+*  extent applicable law prohibits such limitation. Some               *
+*  jurisdictions do not allow the exclusion or limitation of           *
+*  incidental or consequential damages, so this exclusion and          *
+*  limitation may not apply to You.                                    *
+*                                                                      *
+************************************************************************
+
+8. Litigation
+-------------
+
+Any litigation relating to this License may be brought only in the
+courts of a jurisdiction where the defendant maintains its principal
+place of business and such litigation shall be governed by laws of that
+jurisdiction, without reference to its conflict-of-law provisions.
+Nothing in this Section shall prevent a party's ability to bring
+cross-claims or counter-claims.
+
+9. Miscellaneous
+----------------
+
+This License represents the complete agreement concerning the subject
+matter hereof. If any provision of this License is held to be
+unenforceable, such provision shall be reformed only to the extent
+necessary to make it enforceable. Any law or regulation which provides
+that the language of a contract shall be construed against the drafter
+shall not be used to construe this License against a Contributor.
+
+10. Versions of the License
+---------------------------
+
+10.1. New Versions
+
+Mozilla Foundation is the license steward. Except as provided in Section
+10.3, no one other than the license steward has the right to modify or
+publish new versions of this License. Each version will be given a
+distinguishing version number.
+
+10.2. Effect of New Versions
+
+You may distribute the Covered Software under the terms of the version
+of the License under which You originally received the Covered Software,
+or under the terms of any subsequent version published by the license
+steward.
+
+10.3. Modified Versions
+
+If you create software not governed by this License, and you want to
+create a new license for such software, you may create and use a
+modified version of this License if you rename the license and remove
+any references to the name of the license steward (except to note that
+such modified license differs from this License).
+
+10.4. Distributing Source Code Form that is Incompatible With Secondary
+Licenses
+
+If You choose to distribute Source Code Form that is Incompatible With
+Secondary Licenses under the terms of this version of the License, the
+notice described in Exhibit B of this License must be attached.
+
+Exhibit A - Source Code Form License Notice
+-------------------------------------------
+
+  This Source Code Form is subject to the terms of the Mozilla Public
+  License, v. 2.0. If a copy of the MPL was not distributed with this
+  file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+If it is not possible or desirable to put the notice in a particular
+file, then You may include the notice in a location (such as a LICENSE
+file in a relevant directory) where a recipient would be likely to look
+for such a notice.
+
+You may add additional accurate notices of copyright ownership.
+
+Exhibit B - "Incompatible With Secondary Licenses" Notice
+---------------------------------------------------------
+
+  This Source Code Form is "Incompatible With Secondary Licenses", as
+  defined by the Mozilla Public License, v. 2.0.
+
+For the handlebars.js component:
+
+Copyright (C) 2011 by Yehuda Katz
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+


[4/9] incubator-trafficcontrol git commit: Removed ATS patches.

Posted by da...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/927e4892/traffic_server/patches/trafficserver-5.3.2-089d585.diff
----------------------------------------------------------------------
diff --git a/traffic_server/patches/trafficserver-5.3.2-089d585.diff b/traffic_server/patches/trafficserver-5.3.2-089d585.diff
deleted file mode 100644
index ede76cc..0000000
--- a/traffic_server/patches/trafficserver-5.3.2-089d585.diff
+++ /dev/null
@@ -1,5157 +0,0 @@
-diff --git a/README b/README
-index 78cce71..769f85a 100644
---- a/README
-+++ b/README
-@@ -1,5 +1,6 @@
- Apache Traffic Server
- 
-+
- Traffic Server is a high-performance building block for cloud services.
- It's more than just a caching proxy server; it also has support for
- plugins to build large scale web applications.
-diff --git a/configure.ac b/configure.ac
-index fe2af20..45c47fe 100644
---- a/configure.ac
-+++ b/configure.ac
-@@ -1948,6 +1948,7 @@ AS_IF([test "x$enable_experimental_plugins" = xyes], [
-     plugins/experimental/background_fetch/Makefile
-     plugins/experimental/balancer/Makefile
-     plugins/experimental/buffer_upload/Makefile
-+    plugins/experimental/cache_range_requests/Makefile
-     plugins/experimental/channel_stats/Makefile
-     plugins/experimental/collapsed_connection/Makefile
-     plugins/experimental/custom_redirect/Makefile
-diff --git a/doc/reference/api/TSHttpOverridableConfig.en.rst b/doc/reference/api/TSHttpOverridableConfig.en.rst
-index 837df9f..e53d371 100644
---- a/doc/reference/api/TSHttpOverridableConfig.en.rst
-+++ b/doc/reference/api/TSHttpOverridableConfig.en.rst
-@@ -57,6 +57,7 @@ Configurations
- The following configurations (from ``records.config``) are overridable: ::
- 
-     proxy.config.url_remap.pristine_host_hdr
-+    proxy.config.url_remap.remap_required
-     proxy.config.http.chunking_enabled
-     proxy.config.http.negative_caching_enabled
-     proxy.config.http.negative_caching_lifetime
-@@ -100,6 +101,7 @@ The following configurations (from ``records.config``) are overridable: ::
-     proxy.config.http.keep_alive_no_activity_timeout_out
-     proxy.config.http.transaction_no_activity_timeout_in
-     proxy.config.http.transaction_no_activity_timeout_out
-+    proxy.config.http.transaction_active_timeout_in
-     proxy.config.http.transaction_active_timeout_out
-     proxy.config.http.origin_max_connections
-     proxy.config.http.connect_attempts_max_retries
-@@ -135,7 +137,12 @@ The following configurations (from ``records.config``) are overridable: ::
-     proxy.config.http.accept_encoding_filter_enabled
-     proxy.config.http.cache.range.write
-     proxy.config.http.global_user_agent_header
--
-+    proxy.config.http.parent_proxy.per_parent_connect_attempts
-+    proxy.config.http.parent_proxy.total_connect_attempts
-+    proxy.config.http.parent_origin.simple_retry_enabled
-+    proxy.config.http.parent_origin.simple_retry_response_codes
-+    proxy.config.http.parent_origin.dead_server_retry_enabled
-+    proxy.config.http.parent_origin.dead_server_retry_response_codes
- 
- Examples
- ========
-diff --git a/iocore/cache/Cache.cc b/iocore/cache/Cache.cc
-index 2879e82..fae560d 100644
---- a/iocore/cache/Cache.cc
-+++ b/iocore/cache/Cache.cc
-@@ -38,6 +38,8 @@
- #include "P_CacheBC.h"
- #endif
- 
-+#include "hugepages.h"
-+
- // Compilation Options
- #define USELESS_REENABLES // allow them for now
- // #define VERIFY_JTEST_DATA
-@@ -1295,7 +1297,13 @@ Vol::init(char *s, off_t blocks, off_t dir_skip, bool clear)
- 
-   Debug("cache_init", "allocating %zu directory bytes for a %lld byte volume (%lf%%)", vol_dirlen(this), (long long)this->len,
-         (double)vol_dirlen(this) / (double)this->len * 100.0);
--  raw_dir = (char *)ats_memalign(ats_pagesize(), vol_dirlen(this));
-+
-+  raw_dir = NULL;
-+  if (ats_hugepage_enabled())
-+    raw_dir = (char *)ats_alloc_hugepage(vol_dirlen(this));
-+  if (raw_dir == NULL)
-+    raw_dir = (char *)ats_memalign(ats_pagesize(), vol_dirlen(this));
-+
-   dir = (Dir *)(raw_dir + vol_headerlen(this));
-   header = (VolHeaderFooter *)raw_dir;
-   footer = (VolHeaderFooter *)(raw_dir + vol_dirlen(this) - ROUND_TO_STORE_BLOCK(sizeof(VolHeaderFooter)));
-@@ -2179,7 +2187,7 @@ CacheProcessor::mark_storage_offline(CacheDisk *d ///< Target disk
-     Warning("All storage devices offline, cache disabled");
-     CacheProcessor::cache_ready = 0;
-   } else { // check cache types specifically
--    if (theCache && !theCache->hosttable->gen_host_rec.vol_hash_table) {
-+    if (theCache && !theCache->getHosttable(__func__)->gen_host_rec.vol_hash_table) {
-       unsigned int caches_ready = 0;
-       caches_ready = caches_ready | (1 << CACHE_FRAG_TYPE_HTTP);
-       caches_ready = caches_ready | (1 << CACHE_FRAG_TYPE_NONE);
-@@ -2187,7 +2195,7 @@ CacheProcessor::mark_storage_offline(CacheDisk *d ///< Target disk
-       CacheProcessor::cache_ready &= caches_ready;
-       Warning("all volumes for http cache are corrupt, http cache disabled");
-     }
--    if (theStreamCache && !theStreamCache->hosttable->gen_host_rec.vol_hash_table) {
-+    if (theStreamCache && !theStreamCache->getHosttable(__func__)->gen_host_rec.vol_hash_table) {
-       unsigned int caches_ready = 0;
-       caches_ready = caches_ready | (1 << CACHE_FRAG_TYPE_RTSP);
-       caches_ready = ~caches_ready;
-@@ -3366,9 +3374,10 @@ create_volume(int volume_number, off_t size_in_blocks, int scheme, CacheVol *cp)
- void
- rebuild_host_table(Cache *cache)
- {
--  build_vol_hash_table(&cache->hosttable->gen_host_rec);
--  if (cache->hosttable->m_numEntries != 0) {
--    CacheHostMatcher *hm = cache->hosttable->getHostMatcher();
-+  CacheHostTable *hosttable = cache->getHosttable(__func__);
-+  build_vol_hash_table(&hosttable->gen_host_rec);
-+  if (hosttable->m_numEntries != 0) {
-+    CacheHostMatcher *hm = hosttable->getHostMatcher();
-     CacheHostRecord *h_rec = hm->getDataArray();
-     int h_rec_len = hm->getNumElements();
-     int i;
-@@ -3383,8 +3392,9 @@ Vol *
- Cache::key_to_vol(CacheKey *key, char const *hostname, int host_len)
- {
-   uint32_t h = (key->slice32(2) >> DIR_TAG_WIDTH) % VOL_HASH_TABLE_SIZE;
-+  CacheHostTable *hosttable = getHosttable(__func__);
-   unsigned short *hash_table = hosttable->gen_host_rec.vol_hash_table;
--  CacheHostRecord *host_rec = &hosttable->gen_host_rec;
-+  CacheHostRecord *host_rec = &(hosttable->gen_host_rec);
- 
-   if (hosttable->m_numEntries > 0 && host_len) {
-     CacheHostResult res;
-@@ -3392,21 +3402,13 @@ Cache::key_to_vol(CacheKey *key, char const *hostname, int host_len)
-     if (res.record) {
-       unsigned short *host_hash_table = res.record->vol_hash_table;
-       if (host_hash_table) {
--        if (is_debug_tag_set("cache_hosting")) {
--          char format_str[50];
--          snprintf(format_str, sizeof(format_str), "Volume: %%xd for host: %%.%ds", host_len);
--          Debug("cache_hosting", format_str, res.record, hostname);
--        }
-+        Debug("cache_hosting", "Volume: %p for host: %.*s", res.record, host_len, hostname);
-         return res.record->vols[host_hash_table[h]];
-       }
-     }
-   }
-   if (hash_table) {
--    if (is_debug_tag_set("cache_hosting")) {
--      char format_str[50];
--      snprintf(format_str, sizeof(format_str), "Generic volume: %%xd for host: %%.%ds", host_len);
--      Debug("cache_hosting", format_str, host_rec, hostname);
--    }
-+    Debug("cache_hosting", "Generic volume: %p for host: %.*s", host_rec, host_len, hostname);
-     return host_rec->vols[hash_table[h]];
-   } else
-     return host_rec->vols[0];
-diff --git a/iocore/cache/CacheDir.cc b/iocore/cache/CacheDir.cc
-index 779c16b..e54fbfb 100644
---- a/iocore/cache/CacheDir.cc
-+++ b/iocore/cache/CacheDir.cc
-@@ -24,6 +24,8 @@
- 
- #include "P_Cache.h"
- 
-+#include "hugepages.h"
-+
- // #define LOOP_CHECK_MODE 1
- #ifdef LOOP_CHECK_MODE
- #define DIR_LOOP_THRESHOLD 1000
-@@ -1011,6 +1013,7 @@ sync_cache_dir_on_shutdown(void)
-   Debug("cache_dir_sync", "sync started");
-   char *buf = NULL;
-   size_t buflen = 0;
-+  bool buf_huge = false;
- 
-   EThread *t = (EThread *)0xdeadbeef;
-   for (int i = 0; i < gnvol; i++) {
-@@ -1077,10 +1080,22 @@ sync_cache_dir_on_shutdown(void)
- #endif
- 
-     if (buflen < dirlen) {
--      if (buf)
--        ats_memalign_free(buf);
--      buf = (char *)ats_memalign(ats_pagesize(), dirlen);
-+      if (buf) {
-+        if (buf_huge)
-+          ats_free_hugepage(buf, buflen);
-+        else
-+          ats_memalign_free(buf);
-+        buf = NULL;
-+      }
-       buflen = dirlen;
-+      if (ats_hugepage_enabled()) {
-+        buf = (char *)ats_alloc_hugepage(buflen);
-+        buf_huge = true;
-+      }
-+      if (buf == NULL) {
-+        buf = (char *)ats_memalign(ats_pagesize(), buflen);
-+        buf_huge = false;
-+      }
-     }
- 
-     if (!d->dir_sync_in_progress) {
-@@ -1104,8 +1119,13 @@ sync_cache_dir_on_shutdown(void)
-     Debug("cache_dir_sync", "done syncing dir for vol %s", d->hash_text.get());
-   }
-   Debug("cache_dir_sync", "sync done");
--  if (buf)
--    ats_memalign_free(buf);
-+  if (buf) {
-+    if (buf_huge)
-+      ats_free_hugepage(buf, buflen);
-+    else
-+      ats_memalign_free(buf);
-+    buf = NULL;
-+  }
- }
- 
- 
-@@ -1120,11 +1140,6 @@ CacheSync::mainEvent(int event, Event *e)
- Lrestart:
-   if (vol_idx >= gnvol) {
-     vol_idx = 0;
--    if (buf) {
--      ats_memalign_free(buf);
--      buf = 0;
--      buflen = 0;
--    }
-     Debug("cache_dir_sync", "sync done");
-     if (event == EVENT_INTERVAL)
-       trigger = e->ethread->schedule_in(this, HRTIME_SECONDS(cache_config_dir_sync_frequency));
-@@ -1196,10 +1211,22 @@ Lrestart:
-       Debug("cache_dir_sync", "pos: %" PRIu64 " Dir %s dirty...syncing to disk", vol->header->write_pos, vol->hash_text.get());
-       vol->header->dirty = 0;
-       if (buflen < dirlen) {
--        if (buf)
--          ats_memalign_free(buf);
--        buf = (char *)ats_memalign(ats_pagesize(), dirlen);
-+        if (buf) {
-+          if (buf_huge)
-+            ats_free_hugepage(buf, buflen);
-+          else
-+            ats_memalign_free(buf);
-+          buf = NULL;
-+        }
-         buflen = dirlen;
-+        if (ats_hugepage_enabled()) {
-+          buf = (char *)ats_alloc_hugepage(buflen);
-+          buf_huge = true;
-+        }
-+        if (buf == NULL) {
-+          buf = (char *)ats_memalign(ats_pagesize(), buflen);
-+          buf_huge = false;
-+        }
-       }
-       vol->header->sync_serial++;
-       vol->footer->sync_serial = vol->header->sync_serial;
-diff --git a/iocore/cache/CacheVol.cc b/iocore/cache/CacheVol.cc
-index 47f5775..fb82742 100644
---- a/iocore/cache/CacheVol.cc
-+++ b/iocore/cache/CacheVol.cc
-@@ -57,10 +57,11 @@ CacheVC::scanVol(int /* event ATS_UNUSED */, Event * /* e ATS_UNUSED */)
-   Debug("cache_scan_truss", "inside %p:scanVol", this);
-   if (_action.cancelled)
-     return free_CacheVC(this);
--  CacheHostRecord *rec = &theCache->hosttable->gen_host_rec;
-+  CacheHostTable *hosttable = theCache->getHosttable(__func__);
-+  CacheHostRecord *rec = &hosttable->gen_host_rec;
-   if (host_len) {
-     CacheHostResult res;
--    theCache->hosttable->Match(hostname, host_len, &res);
-+    hosttable->Match(hostname, host_len, &res);
-     if (res.record)
-       rec = res.record;
-   }
-diff --git a/iocore/cache/P_CacheDir.h b/iocore/cache/P_CacheDir.h
-index 0a31c32..f5c83d5 100644
---- a/iocore/cache/P_CacheDir.h
-+++ b/iocore/cache/P_CacheDir.h
-@@ -293,6 +293,7 @@ struct CacheSync : public Continuation {
-   int vol_idx;
-   char *buf;
-   size_t buflen;
-+  bool buf_huge;
-   off_t writepos;
-   AIOCallbackInternal io;
-   Event *trigger;
-@@ -300,7 +301,8 @@ struct CacheSync : public Continuation {
-   int mainEvent(int event, Event *e);
-   void aio_write(int fd, char *b, int n, off_t o);
- 
--  CacheSync() : Continuation(new_ProxyMutex()), vol_idx(0), buf(0), buflen(0), writepos(0), trigger(0), start_time(0)
-+  CacheSync()
-+    : Continuation(new_ProxyMutex()), vol_idx(0), buf(0), buflen(0), buf_huge(false), writepos(0), trigger(0), start_time(0)
-   {
-     SET_HANDLER(&CacheSync::mainEvent);
-   }
-diff --git a/iocore/cache/P_CacheHosting.h b/iocore/cache/P_CacheHosting.h
-index 21d2b1a..c874f64 100644
---- a/iocore/cache/P_CacheHosting.h
-+++ b/iocore/cache/P_CacheHosting.h
-@@ -163,7 +163,8 @@ struct CacheHostTableConfig : public Continuation {
-     (void)e;
-     (void)event;
-     CacheHostTable *t = new CacheHostTable((*ppt)->cache, (*ppt)->type);
--    CacheHostTable *old = (CacheHostTable *)ink_atomic_swap(&t, *ppt);
-+    CacheHostTable *old = (CacheHostTable *)ink_atomic_swap(ppt, t);
-+    Debug("cache_hosting", "swapped: old=%p, new=%p", old, t);
-     new_Deleter(old, CACHE_MEM_FREE_TIMEOUT);
-     return EVENT_DONE;
-   }
-diff --git a/iocore/cache/P_CacheInternal.h b/iocore/cache/P_CacheInternal.h
-index d06c8d3..d27a752 100644
---- a/iocore/cache/P_CacheInternal.h
-+++ b/iocore/cache/P_CacheInternal.h
-@@ -1058,6 +1058,12 @@ struct Cache {
-       hosttable(NULL), total_initialized_vol(0), scheme(CACHE_NONE_TYPE)
-   {
-   }
-+  CacheHostTable *
-+  getHosttable(const char *callfunc)
-+  {
-+    Debug("cache_hosting", "getHosttable() from: %s", callfunc);
-+    return hosttable;
-+  }
- };
- 
- extern Cache *theCache;
-diff --git a/lib/records/RecCore.cc b/lib/records/RecCore.cc
-index 5babfad..9c75006 100644
---- a/lib/records/RecCore.cc
-+++ b/lib/records/RecCore.cc
-@@ -789,7 +789,7 @@ RecRegisterStat(RecT rec_type, const char *name, RecDataT data_type, RecData dat
-     // new default value.
-     if ((r->stat_meta.persist_type == RECP_NULL || r->stat_meta.persist_type == RECP_PERSISTENT) &&
-         persist_type == RECP_NON_PERSISTENT) {
--      RecDebug(DL_Debug, "resetting default value for formerly persisted stat '%s'", r->name);
-+      RecDebug(DL_Debug, "resetting default value for formerly persisted stat id:%d '%s'", r->rsb_id, r->name);
-       RecDataSet(r->data_type, &(r->data), &(data_default));
-     }
- 
-@@ -955,6 +955,8 @@ RecDumpRecords(RecT rec_type, RecDumpEntryCb callback, void *edata)
- {
-   int i, num_records;
- 
-+  ink_rwlock_rdlock(&g_records_rwlock);
-+
-   num_records = g_num_records;
-   for (i = 0; i < num_records; i++) {
-     RecRecord *r = &(g_records[i]);
-@@ -964,6 +966,8 @@ RecDumpRecords(RecT rec_type, RecDumpEntryCb callback, void *edata)
-       rec_mutex_release(&(r->lock));
-     }
-   }
-+
-+  ink_rwlock_unlock(&g_records_rwlock);
- }
- 
- void
-diff --git a/lib/records/RecProcess.cc b/lib/records/RecProcess.cc
-index f0c59bb..9a44ee6 100644
---- a/lib/records/RecProcess.cc
-+++ b/lib/records/RecProcess.cc
-@@ -173,12 +173,18 @@ raw_stat_sync_to_global(RecRawStatBlock *rsb, int id)
-     tlp = ((RecRawStat *)((char *)(eventProcessor.all_ethreads[i]) + rsb->ethr_stat_offset)) + id;
-     total.sum += tlp->sum;
-     total.count += tlp->count;
-+    // Debug("stats","raw_stat_sync_to_global(): ethread: %d, id: %d, total.sum: %" PRId64 ", total.count: %" PRId64 ", tlp->sum: %"
-+    // PRId64 ", tlp->count: %" PRId64,
-+    // i, id, total.sum, total.count, tlp->sum, tlp->count);
-   }
- 
-   for (i = 0; i < eventProcessor.n_dthreads; i++) {
-     tlp = ((RecRawStat *)((char *)(eventProcessor.all_dthreads[i]) + rsb->ethr_stat_offset)) + id;
-     total.sum += tlp->sum;
-     total.count += tlp->count;
-+    // Debug("stats","raw_stat_sync_to_global(): dthread: %d, id: %d, total.sum: %" PRId64 ", total.count: %" PRId64 ", tlp->sum: %"
-+    // PRId64 ", tlp->count: %" PRId64,
-+    // i, id, total.sum, total.count, tlp->sum, tlp->count);
-   }
- 
-   if (total.sum < 0) { // Assure that we stay positive
-@@ -194,9 +200,9 @@ raw_stat_sync_to_global(RecRawStatBlock *rsb, int id)
-   delta.count = total.count - rsb->global[id]->last_count;
- 
-   // This is too verbose now, so leaving it out / leif
--  // Debug("stats", "raw_stat_sync_to_global(): rsb pointer:%p id:%d delta:%" PRId64 " total:%" PRId64 " last:%" PRId64 " global:%"
--  // PRId64 "\n",
--  // rsb, id, delta.sum, total.sum, rsb->global[id]->last_sum, rsb->global[id]->sum);
-+  Debug("stats.verbose", "raw_stat_sync_to_global(): rsb pointer:%p rsb data pointer:%p id:%d delta:%" PRId64 " total:%" PRId64
-+                         " last:%" PRId64 " global:%" PRId64 "\n",
-+        rsb, rsb->global[id], id, delta.sum, total.sum, rsb->global[id]->last_sum, rsb->global[id]->sum);
- 
-   // increment the global values by the delta
-   ink_atomic_increment(&(rsb->global[id]->sum), delta.sum);
-@@ -540,7 +546,7 @@ int
- _RecRegisterRawStat(RecRawStatBlock *rsb, RecT rec_type, const char *name, RecDataT data_type, RecPersistT persist_type, int id,
-                     RecRawStatSyncCb sync_cb)
- {
--  Debug("stats", "RecRawStatSyncCb(%s): rsb pointer:%p id:%d\n", name, rsb, id);
-+  Debug("stats", "_RecRegisterRawStat(%s): rsb pointer:%p id:%d\n", name, rsb, id);
- 
-   // check to see if we're good to proceed
-   ink_assert(id < rsb->max_stats);
-@@ -556,6 +562,11 @@ _RecRegisterRawStat(RecRawStatBlock *rsb, RecT rec_type, const char *name, RecDa
-     err = REC_ERR_FAIL;
-     goto Ldone;
-   }
-+  if (r->rsb_id > 0 && r->rsb_id != id) {
-+    Warning("_RecRegisterRawStat(): Created and reusing a stat with id = %d for new stat named %s", r->rsb_id, name);
-+  } else {
-+    Warning("_RecRegisterStat(): Stat created, name: %s, id: %d", name, id);
-+  }
-   r->rsb_id = id; // This is the index within the RSB raw block for this stat, used for lookups by name.
-   if (i_am_the_record_owner(r->rec_type)) {
-     r->sync_required = r->sync_required | REC_PEER_SYNC_REQUIRED;
-@@ -570,6 +581,7 @@ _RecRegisterRawStat(RecRawStatBlock *rsb, RecT rec_type, const char *name, RecDa
- 
-   // setup the periodic sync callback
-   RecRegisterRawStatSyncCb(name, sync_cb, rsb, id);
-+  Warning("_RecRegisterRawStat(): Stat created, id:%d name:%s, data address:%p", id, name, &r->stat_meta.data_raw);
- 
- Ldone:
-   return err;
-diff --git a/lib/ts/ConsistentHash.cc b/lib/ts/ConsistentHash.cc
-index c983ccb..912bc74 100644
---- a/lib/ts/ConsistentHash.cc
-+++ b/lib/ts/ConsistentHash.cc
-@@ -67,13 +67,19 @@ ATSConsistentHash::insert(ATSConsistentHashNode *node, float weight, ATSHash64 *
- }
- 
- ATSConsistentHashNode *
--ATSConsistentHash::lookup(const char *url, ATSConsistentHashIter *i, bool *w, ATSHash64 *h)
-+ATSConsistentHash::lookup(const char *url, size_t url_len, ATSConsistentHashIter *i, bool *w, ATSHash64 *h)
- {
-   uint64_t url_hash;
-   ATSConsistentHashIter NodeMapIterUp, *iter;
-   ATSHash64 *thash;
-   bool *wptr, wrapped = false;
- 
-+  if (url_len <= 0 && url) {
-+    url_len = strlen(url);
-+  } else {
-+    url_len = 0;
-+  }
-+
-   if (h) {
-     thash = h;
-   } else if (hash) {
-@@ -95,7 +101,7 @@ ATSConsistentHash::lookup(const char *url, ATSConsistentHashIter *i, bool *w, AT
-   }
- 
-   if (url) {
--    thash->update(url, strlen(url));
-+    thash->update(url, url_len);
-     thash->final();
-     url_hash = thash->get();
-     thash->clear();
-@@ -124,13 +130,19 @@ ATSConsistentHash::lookup(const char *url, ATSConsistentHashIter *i, bool *w, AT
- }
- 
- ATSConsistentHashNode *
--ATSConsistentHash::lookup_available(const char *url, ATSConsistentHashIter *i, bool *w, ATSHash64 *h)
-+ATSConsistentHash::lookup_available(const char *url, size_t url_len, ATSConsistentHashIter *i, bool *w, ATSHash64 *h)
- {
-   uint64_t url_hash;
-   ATSConsistentHashIter NodeMapIterUp, *iter;
-   ATSHash64 *thash;
-   bool *wptr, wrapped = false;
- 
-+  if (url_len <= 0 && url) {
-+    url_len = strlen(url);
-+  } else {
-+    url_len = 0;
-+  }
-+
-   if (h) {
-     thash = h;
-   } else if (hash) {
-@@ -152,7 +164,7 @@ ATSConsistentHash::lookup_available(const char *url, ATSConsistentHashIter *i, b
-   }
- 
-   if (url) {
--    thash->update(url, strlen(url));
-+    thash->update(url, url_len);
-     thash->final();
-     url_hash = thash->get();
-     thash->clear();
-@@ -179,6 +191,34 @@ ATSConsistentHash::lookup_available(const char *url, ATSConsistentHashIter *i, b
-   return (*iter)->second;
- }
- 
-+ATSConsistentHashNode *
-+ATSConsistentHash::lookup_by_hashval(uint64_t hashval, ATSConsistentHashIter *i, bool *w)
-+{
-+  ATSConsistentHashIter NodeMapIterUp, *iter;
-+  bool *wptr, wrapped = false;
-+
-+  if (w) {
-+    wptr = w;
-+  } else {
-+    wptr = &wrapped;
-+  }
-+
-+  if (i) {
-+    iter = i;
-+  } else {
-+    iter = &NodeMapIterUp;
-+  }
-+
-+  *iter = NodeMap.lower_bound(hashval);
-+
-+  if (*iter == NodeMap.end()) {
-+    *wptr = true;
-+    *iter = NodeMap.begin();
-+  }
-+
-+  return (*iter)->second;
-+}
-+
- ATSConsistentHash::~ATSConsistentHash()
- {
-   if (hash) {
-diff --git a/lib/ts/ConsistentHash.h b/lib/ts/ConsistentHash.h
-index 6406a6c6..49822ad 100644
---- a/lib/ts/ConsistentHash.h
-+++ b/lib/ts/ConsistentHash.h
-@@ -49,9 +49,11 @@ typedef std::map<uint64_t, ATSConsistentHashNode *>::iterator ATSConsistentHashI
- struct ATSConsistentHash {
-   ATSConsistentHash(int r = 1024, ATSHash64 *h = NULL);
-   void insert(ATSConsistentHashNode *node, float weight = 1.0, ATSHash64 *h = NULL);
--  ATSConsistentHashNode *lookup(const char *url = NULL, ATSConsistentHashIter *i = NULL, bool *w = NULL, ATSHash64 *h = NULL);
--  ATSConsistentHashNode *lookup_available(const char *url = NULL, ATSConsistentHashIter *i = NULL, bool *w = NULL,
--                                          ATSHash64 *h = NULL);
-+  ATSConsistentHashNode *lookup(const char *url = NULL, size_t url_len = 0, ATSConsistentHashIter *i = NULL, bool *w = NULL,
-+                                ATSHash64 *h = NULL);
-+  ATSConsistentHashNode *lookup_available(const char *url = NULL, size_t url_len = 0, ATSConsistentHashIter *i = NULL,
-+                                          bool *w = NULL, ATSHash64 *h = NULL);
-+  ATSConsistentHashNode *lookup_by_hashval(uint64_t hashval, ATSConsistentHashIter *i = NULL, bool *w = NULL);
-   ~ATSConsistentHash();
- 
- private:
-diff --git a/lib/ts/Makefile.am b/lib/ts/Makefile.am
-index d5ca4ac..3f5eee5 100644
---- a/lib/ts/Makefile.am
-+++ b/lib/ts/Makefile.am
-@@ -107,6 +107,8 @@ libtsutil_la_SOURCES = \
-   defalloc.h \
-   fastlz.c \
-   fastlz.h \
-+  hugepages.cc \
-+  hugepages.h \
-   ink_aiocb.h \
-   ink_align.h \
-   ink_apidefs.h \
-diff --git a/lib/ts/apidefs.h.in b/lib/ts/apidefs.h.in
-index 04f4dd9..31cb807 100644
---- a/lib/ts/apidefs.h.in
-+++ b/lib/ts/apidefs.h.in
-@@ -758,6 +758,14 @@ extern "C"
-     TS_CONFIG_HTTP_POST_CHECK_CONTENT_LENGTH_ENABLED,
-     TS_CONFIG_HTTP_GLOBAL_USER_AGENT_HEADER,
-     TS_CONFIG_HTTP_AUTH_SERVER_SESSION_PRIVATE,
-+    TS_CONFIG_HTTP_TRANSACTION_ACTIVE_TIMEOUT_IN,
-+    TS_CONFIG_HTTP_PER_PARENT_CONNECT_ATTEMPTS,
-+    TS_CONFIG_HTTP_PARENT_TOTAL_CONNECT_ATTEMPTS,
-+    TS_CONFIG_HTTP_SIMPLE_RETRY_ENABLED,
-+    TS_CONFIG_HTTP_SIMPLE_RETRY_RESPONSE_CODES,
-+    TS_CONFIG_HTTP_DEAD_SERVER_RETRY_ENABLED,
-+    TS_CONFIG_HTTP_DEAD_SERVER_RETRY_RESPONSE_CODES,
-+    TS_CONFIG_HTTP_URL_REMAP_REQUIRED,
-     TS_CONFIG_LAST_ENTRY
-   } TSOverridableConfigKey;
- 
-diff --git a/lib/ts/hugepages.cc b/lib/ts/hugepages.cc
-new file mode 100644
-index 0000000..d7d94a4
---- /dev/null
-+++ b/lib/ts/hugepages.cc
-@@ -0,0 +1,147 @@
-+/** @file
-+
-+  @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 <cstdio>
-+#include <sys/mman.h>
-+#include "Diags.h"
-+#include "ink_align.h"
-+
-+#define DEBUG_TAG "hugepages"
-+
-+#ifdef MAP_HUGETLB
-+#define MEMINFO_PATH "/proc/meminfo"
-+#define LINE_SIZE 256
-+#define TOKEN "Hugepagesize:"
-+#define TOKEN_SIZE (strlen(TOKEN))
-+
-+static int hugepage_size = -1;
-+static bool hugepage_enabled;
-+#endif
-+
-+size_t
-+ats_hugepage_size(void)
-+{
-+#ifdef MAP_HUGETLB
-+  return hugepage_size;
-+#else
-+  Debug(DEBUG_TAG, "MAP_HUGETLB not defined");
-+  return 0;
-+#endif
-+}
-+
-+bool
-+ats_hugepage_enabled(void)
-+{
-+#ifdef MAP_HUGETLB
-+  return hugepage_enabled;
-+#else
-+  return false;
-+#endif
-+}
-+
-+void
-+ats_hugepage_init(int enabled)
-+{
-+#ifdef MAP_HUGETLB
-+  FILE *fp;
-+  char line[LINE_SIZE];
-+  char *p, *ep;
-+
-+  hugepage_size = 0;
-+
-+  if (!enabled) {
-+    Debug(DEBUG_TAG, "hugepages not enabled");
-+    return;
-+  }
-+
-+  fp = fopen(MEMINFO_PATH, "r");
-+
-+  if (fp == NULL) {
-+    Debug(DEBUG_TAG, "Cannot open file %s", MEMINFO_PATH);
-+    return;
-+  }
-+
-+  while (fgets(line, sizeof(line), fp)) {
-+    if (strncmp(line, TOKEN, TOKEN_SIZE) == 0) {
-+      p = line + TOKEN_SIZE;
-+      while (*p == ' ') {
-+        p++;
-+      }
-+      hugepage_size = strtol(p, &ep, 10);
-+      // What other values can this be?
-+      if (strncmp(ep, " kB", 4)) {
-+        hugepage_size *= 1024;
-+      }
-+      break;
-+    }
-+  }
-+
-+  fclose(fp);
-+
-+  if (hugepage_size) {
-+    hugepage_enabled = true;
-+  }
-+
-+  Debug(DEBUG_TAG, "Hugepage size = %d", hugepage_size);
-+#else
-+  Debug(DEBUG_TAG, "MAP_HUGETLB not defined");
-+#endif
-+}
-+
-+void *
-+ats_alloc_hugepage(size_t s)
-+{
-+#ifdef MAP_HUGETLB
-+  size_t size;
-+  void *mem;
-+
-+  size = INK_ALIGN(s, ats_hugepage_size());
-+
-+  mem = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS | MAP_HUGETLB, -1, 0);
-+
-+  if (mem == MAP_FAILED) {
-+    Debug(DEBUG_TAG, "Could not allocate hugepages size = %zu", size);
-+    return NULL;
-+  }
-+
-+  return mem;
-+#else
-+  (void)s;
-+  Debug(DEBUG_TAG, "MAP_HUGETLB not defined");
-+  return NULL;
-+#endif
-+}
-+
-+bool
-+ats_free_hugepage(void *ptr, size_t s)
-+{
-+#ifdef MAP_HUGETLB
-+  size_t size;
-+
-+  size = INK_ALIGN(s, ats_hugepage_size());
-+  return (munmap(ptr, size) == 0);
-+#else
-+  (void)ptr;
-+  (void)s;
-+  Debug(DEBUG_TAG, "MAP_HUGETLB not defined");
-+  return false;
-+#endif
-+}
-diff --git a/lib/ts/hugepages.h b/lib/ts/hugepages.h
-new file mode 100644
-index 0000000..812542b
---- /dev/null
-+++ b/lib/ts/hugepages.h
-@@ -0,0 +1,32 @@
-+/** @file
-+
-+  @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.
-+ */
-+#ifndef _hugepages_h_
-+#define _hugepages_h_
-+
-+#include <cstring>
-+
-+size_t ats_hugepage_size(void);
-+bool ats_hugepage_enabled(void);
-+void ats_hugepage_init(int);
-+void *ats_alloc_hugepage(size_t);
-+bool ats_free_hugepage(void *, size_t);
-+
-+#endif
-diff --git a/lib/ts/ink_queue.cc b/lib/ts/ink_queue.cc
-index e718b3f..0f14b68 100644
---- a/lib/ts/ink_queue.cc
-+++ b/lib/ts/ink_queue.cc
-@@ -50,6 +50,7 @@
- #include "ink_assert.h"
- #include "ink_queue_ext.h"
- #include "ink_align.h"
-+#include "hugepages.h"
- 
- inkcoreapi volatile int64_t fastalloc_mem_in_use = 0;
- inkcoreapi volatile int64_t fastalloc_mem_total = 0;
-@@ -100,9 +101,13 @@ ink_freelist_init(InkFreeList **fl, const char *name, uint32_t type_size, uint32
-   /* quick test for power of 2 */
-   ink_assert(!(alignment & (alignment - 1)));
-   f->alignment = alignment;
--  f->chunk_size = chunk_size;
-   // Make sure we align *all* the objects in the allocation, not just the first one
-   f->type_size = INK_ALIGN(type_size, alignment);
-+  if (ats_hugepage_enabled()) {
-+    f->chunk_size = INK_ALIGN(chunk_size * f->type_size, ats_hugepage_size()) / f->type_size;
-+  } else {
-+    f->chunk_size = chunk_size;
-+  }
-   SET_FREELIST_POINTER_VERSION(f->head, FROM_PTR(0), 0);
- 
-   f->used = 0;
-@@ -171,12 +176,16 @@ ink_freelist_new(InkFreeList *f)
- #ifdef DEBUG
-       char *oldsbrk = (char *)sbrk(0), *newsbrk = NULL;
- #endif
--      if (f->alignment)
--        newp = ats_memalign(f->alignment, f->chunk_size * type_size);
--      else
--        newp = ats_malloc(f->chunk_size * type_size);
-+      if (ats_hugepage_enabled())
-+        newp = ats_alloc_hugepage(f->chunk_size * type_size);
-+
-+      if (newp == NULL) {
-+        if (f->alignment)
-+          newp = ats_memalign(f->alignment, f->chunk_size * type_size);
-+        else
-+          newp = ats_malloc(f->chunk_size * type_size);
-+      }
-       ats_madvise((caddr_t)newp, f->chunk_size * type_size, f->advice);
--
-       fl_memadd(f->chunk_size * type_size);
- #ifdef DEBUG
-       newsbrk = (char *)sbrk(0);
-diff --git a/lib/ts/libts.h b/lib/ts/libts.h
-index d244158..20f85b2 100644
---- a/lib/ts/libts.h
-+++ b/lib/ts/libts.h
-@@ -41,6 +41,7 @@
- #define std *** _FIXME_REMOVE_DEPENDENCY_ON_THE_STL_ ***
- */
- 
-+#include "hugepages.h"
- #include "ink_config.h"
- #include "ink_platform.h"
- #include "ink_align.h"
-diff --git a/mgmt/RecordsConfig.cc b/mgmt/RecordsConfig.cc
-index f520f4a..0e229c2 100644
---- a/mgmt/RecordsConfig.cc
-+++ b/mgmt/RecordsConfig.cc
-@@ -506,6 +506,17 @@ static const RecordElement RecordsConfig[] =
-   ,
- 
-   //        ###################################
-+  //        # parent origin configuration     #
-+  //        ###################################
-+  {RECT_CONFIG, "proxy.config.http.parent_origin.simple_retry_enabled", RECD_INT, "0", RECU_DYNAMIC, RR_NULL, RECC_INT, "[0-1]", RECA_NULL}
-+  ,
-+  {RECT_CONFIG, "proxy.config.http.parent_origin.simple_retry_response_codes", RECD_STRING, "404", RECU_DYNAMIC, RR_NULL, RECC_STR, "^([0-9]+,)$", RECA_NULL}
-+  ,
-+  {RECT_CONFIG, "proxy.config.http.parent_origin.dead_server_retry_enabled", RECD_INT, "0", RECU_DYNAMIC, RR_NULL, RECC_INT, "[0-1]", RECA_NULL}
-+  ,
-+  {RECT_CONFIG, "proxy.config.http.parent_origin.dead_server_retry_response_codes", RECD_STRING, "503", RECU_DYNAMIC, RR_NULL, RECC_STR, "^([0-9]+,)$", RECA_NULL}
-+  ,
-+  //        ###################################
-   //        # NO DNS DOC IN CACHE             #
-   //        ###################################
-   {RECT_CONFIG, "proxy.config.http.doc_in_cache_skip_dns", RECD_INT, "1", RECU_DYNAMIC, RR_NULL, RECC_INT, "[0-1]", RECA_NULL}
-@@ -647,6 +658,13 @@ static const RecordElement RecordsConfig[] =
-   ,
-   {RECT_CONFIG, "proxy.config.http.cache.max_open_write_retries", RECD_INT, "1", RECU_DYNAMIC, RR_NULL, RECC_NULL, NULL, RECA_NULL}
-   ,
-+  //       #  open_write_fail_action has 3 options:
-+  //       #
-+  //       #  0 - default. disable cache and goto origin
-+  //       #  1 - return error if cache miss
-+  //       #  2 - serve stale until proxy.config.http.cache.max_stale_age, then goto origin, if refresh_miss
-+  {RECT_CONFIG, "proxy.config.http.cache.open_write_fail_action", RECD_INT, "0", RECU_DYNAMIC, RR_NULL, RECC_NULL, NULL, RECA_NULL}
-+  ,
-   //       #  when_to_revalidate has 4 options:
-   //       #
-   //       #  0 - default. use use cache directives or heuristic
-@@ -2067,6 +2085,8 @@ static const RecordElement RecordsConfig[] =
-   ,
-   {RECT_CONFIG, "proxy.config.allocator.debug_filter", RECD_INT, "0", RECU_NULL, RR_NULL, RECC_NULL, "[0-3]", RECA_NULL}
-   ,
-+  {RECT_CONFIG, "proxy.config.allocator.hugepages", RECD_INT, "0", RECU_RESTART_TS, RR_NULL, RECC_NULL, "[0-1]", RECA_NULL}
-+  ,
- 
-   //############
-   //#
-diff --git a/plugins/cacheurl/cacheurl.cc b/plugins/cacheurl/cacheurl.cc
-index 5f03598..52565fc 100644
---- a/plugins/cacheurl/cacheurl.cc
-+++ b/plugins/cacheurl/cacheurl.cc
-@@ -42,6 +42,7 @@
- #define TOKENCOUNT 10
- #define OVECOUNT 30
- #define PLUGIN_NAME "cacheurl"
-+#define DEFAULT_CONFIG "cacheurl.config"
- 
- struct regex_info {
-   pcre *re;          /* Compiled regular expression */
-@@ -213,10 +214,10 @@ load_config_file(const char *config_file)
-   regex_info *info = 0;
- 
-   if (config_file == NULL) {
--    /* Default config file of plugins/cacheurl.config */
--    path = TSPluginDirGet();
--    path += "/cacheurl.config";
--  } else if (*config_file != '/') {
-+    config_file = DEFAULT_CONFIG;
-+  }
-+
-+  if (*config_file != '/') {
-     // Relative paths are relative to the config directory
-     path = TSConfigDirGet();
-     path += "/";
-diff --git a/plugins/experimental/Makefile.am b/plugins/experimental/Makefile.am
-index 2ef296c..52fef44 100644
---- a/plugins/experimental/Makefile.am
-+++ b/plugins/experimental/Makefile.am
-@@ -19,6 +19,7 @@ SUBDIRS = \
-  background_fetch \
-  balancer \
-  buffer_upload \
-+ cache_range_requests \
-  channel_stats \
-  collapsed_connection \
-  custom_redirect \
-diff --git a/plugins/experimental/background_fetch/background_fetch.cc b/plugins/experimental/background_fetch/background_fetch.cc
-index 878183e..fd0af7a 100644
---- a/plugins/experimental/background_fetch/background_fetch.cc
-+++ b/plugins/experimental/background_fetch/background_fetch.cc
-@@ -84,8 +84,13 @@ read_config(char *config_file, BgFetchRuleMap *ri)
-     snprintf(file_path, sizeof(file_path), "%s/%s", TSInstallDirGet(), config_file);
-     file = TSfopen(file_path, "r");
-     if (file == NULL) {
--      TSError("%s: invalid config file", PLUGIN_NAME);
--      return false;
-+      TSDebug(PLUGIN_NAME, "Failed to open config file %s, trying config path", config_file);
-+      snprintf(file_path, sizeof(file_path), "%s/%s", TSConfigDirGet(), config_file);
-+      file = TSfopen(file_path, "r");
-+      if (file == NULL) {
-+        TSError("%s: invalid config file", PLUGIN_NAME);
-+        return false;
-+      }
-     }
-   }
- 
-diff --git a/plugins/experimental/cache_range_requests/Makefile.am b/plugins/experimental/cache_range_requests/Makefile.am
-new file mode 100644
-index 0000000..5a27cac
---- /dev/null
-+++ b/plugins/experimental/cache_range_requests/Makefile.am
-@@ -0,0 +1,21 @@
-+#  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 $(top_srcdir)/build/plugins.mk
-+
-+pkglib_LTLIBRARIES = cache_range_requests.la
-+cache_range_requests_la_SOURCES = cache_range_requests.cc
-+cache_range_requests_la_LDFLAGS = $(TS_PLUGIN_LDFLAGS)
-diff --git a/plugins/experimental/cache_range_requests/README b/plugins/experimental/cache_range_requests/README
-new file mode 100644
-index 0000000..faddeb5
---- /dev/null
-+++ b/plugins/experimental/cache_range_requests/README
-@@ -0,0 +1,36 @@
-+
-+Thousands of range requests for a very large object in the traffic server cache
-+are likely to increase system load averages due to I/O wait as objects are stored
-+on a single stripe or disk drive.
-+
-+This plugin allows you to remap individual range requests so that they are stored
-+as individual objects in the ATS cache when subsequent range requests are likely
-+to use the same range.  This spreads range requests over multiple stripes thereby
-+reducing I/O wait and system load averages.
-+
-+This plugin reads the range request header byte range value and then creates a
-+new cache key url using the original request url with the range value appended
-+to it.  The range header is removed where appropriate from the requests and the
-+origin server response code is changed from a 206 to a 200 to insure that the
-+object is written to cache using the new cache key url.  The response code sent 
-+to the client will be changed back to a 206 and all requests to the origin server 
-+will contain the range header so that the correct response is received.
-+
-+Installation:
-+
-+    make
-+    sudo make install
-+
-+If you don't have the traffic server binaries in your path, then you will need
-+to specify the path to tsxs manually:
-+
-+    make TSXS=/opt/trafficserver/bin/tsxs
-+    sudo make TSXS=/opt/trafficserver/bin/tsxs install
-+
-+Configuration:
-+
-+    Add @plugin=cache_range_requests.so to your remap.config rules.
-+
-+    Or for a global plugin where all range requests are processed,
-+    Add cache_range_requests.so to the plugin.config
-+
-diff --git a/plugins/experimental/cache_range_requests/cache_range_requests.cc b/plugins/experimental/cache_range_requests/cache_range_requests.cc
-new file mode 100644
-index 0000000..8722279
---- /dev/null
-+++ b/plugins/experimental/cache_range_requests/cache_range_requests.cc
-@@ -0,0 +1,411 @@
-+/*
-+ * 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.
-+ */
-+
-+/*
-+ * This plugin looks for range requests and then creates a new
-+ * cache key url so that each individual range requests is written
-+ * to the cache as a individual object so that subsequent range
-+ * requests are read accross different disk drives reducing I/O
-+ * wait and load averages when there are large numbers of range
-+ * requests.
-+ */
-+
-+#include <stdio.h>
-+#include <string.h>
-+#include "ts/ts.h"
-+#include "ts/remap.h"
-+
-+#define PLUGIN_NAME "cache_range_requests"
-+#define DEBUG_LOG(fmt, ...) TSDebug(PLUGIN_NAME, "[%s:%d] %s(): " fmt, __FILE__, __LINE__, __func__, ##__VA_ARGS__)
-+#define ERROR_LOG(fmt, ...) TSError("[%s:%d] %s(): " fmt, __FILE__, __LINE__, __func__, ##__VA_ARGS__)
-+
-+struct txndata {
-+  char *range_value;
-+};
-+
-+static void handle_read_request_header(TSCont, TSEvent, void *);
-+static void range_header_check(TSHttpTxn txnp);
-+static void handle_send_origin_request(TSCont, TSHttpTxn, struct txndata *);
-+static void handle_client_send_response(TSHttpTxn, struct txndata *);
-+static void handle_server_read_response(TSHttpTxn, struct txndata *);
-+static int remove_header(TSMBuffer, TSMLoc, const char *, int);
-+static bool set_header(TSMBuffer, TSMLoc, const char *, int, const char *, int);
-+static void transaction_handler(TSCont, TSEvent, void *);
-+
-+/**
-+ * Entry point when used as a global plugin.
-+ *
-+ */
-+static void
-+handle_read_request_header(TSCont txn_contp, TSEvent event, void *edata)
-+{
-+  TSHttpTxn txnp = static_cast<TSHttpTxn>(edata);
-+
-+  range_header_check(txnp);
-+
-+  TSHttpTxnReenable(txnp, TS_EVENT_HTTP_CONTINUE);
-+}
-+
-+/**
-+ * Reads the client request header and if this is a range request:
-+ *
-+ * 1. creates a new cache key url using the range request information.
-+ * 2. Saves the range request information and then removes the range
-+ *    header so that the response retrieved from the origin will
-+ *    be written to cache.
-+ * 3. Schedules TS_HTTP_SEND_REQUEST_HDR_HOOK, TS_HTTP_SEND_RESPONSE_HDR_HOOK,
-+ *    and TS_HTTP_TXN_CLOSE_HOOK for further processing.
-+ */
-+static void
-+range_header_check(TSHttpTxn txnp)
-+{
-+  char cache_key_url[8192] = {0};
-+  char *req_url;
-+  int length, url_length;
-+  struct txndata *txn_state;
-+  TSMBuffer hdr_bufp;
-+  TSMLoc req_hdrs = NULL;
-+  TSMLoc loc = NULL;
-+  TSCont txn_contp;
-+
-+  if (TS_SUCCESS == TSHttpTxnClientReqGet(txnp, &hdr_bufp, &req_hdrs)) {
-+    loc = TSMimeHdrFieldFind(hdr_bufp, req_hdrs, TS_MIME_FIELD_RANGE, TS_MIME_LEN_RANGE);
-+    if (TS_NULL_MLOC != loc) {
-+      const char *hdr_value = TSMimeHdrFieldValueStringGet(hdr_bufp, req_hdrs, loc, 0, &length);
-+      if (!hdr_value || length <= 0) {
-+        DEBUG_LOG("Not a range request.");
-+      } else {
-+        if (NULL == (txn_contp = TSContCreate((TSEventFunc)transaction_handler, NULL))) {
-+          ERROR_LOG("failed to create the transaction handler continuation.");
-+        } else {
-+          txn_state = (struct txndata *)TSmalloc(sizeof(struct txndata));
-+          txn_state->range_value = TSstrndup(hdr_value, length);
-+          DEBUG_LOG("length: %d, txn_state->range_value: %s", length, txn_state->range_value);
-+          txn_state->range_value[length] = '\0'; // workaround for bug in core
-+
-+          req_url = TSHttpTxnEffectiveUrlStringGet(txnp, &url_length);
-+          snprintf(cache_key_url, 8192, "%s-%s", req_url, txn_state->range_value);
-+          DEBUG_LOG("Rewriting cache URL for %s to %s", req_url, cache_key_url);
-+          if (req_url != NULL)
-+            TSfree(req_url);
-+
-+          // set the cache key.
-+          if (TS_SUCCESS != TSCacheUrlSet(txnp, cache_key_url, strlen(cache_key_url))) {
-+            DEBUG_LOG("failed to change the cache url to %s.", cache_key_url);
-+          }
-+          // remove the range request header.
-+          if (remove_header(hdr_bufp, req_hdrs, TS_MIME_FIELD_RANGE, TS_MIME_LEN_RANGE) > 0) {
-+            DEBUG_LOG("Removed the Range: header from the request.");
-+          }
-+
-+          TSContDataSet(txn_contp, txn_state);
-+          TSHttpTxnHookAdd(txnp, TS_HTTP_SEND_REQUEST_HDR_HOOK, txn_contp);
-+          TSHttpTxnHookAdd(txnp, TS_HTTP_SEND_RESPONSE_HDR_HOOK, txn_contp);
-+          TSHttpTxnHookAdd(txnp, TS_HTTP_TXN_CLOSE_HOOK, txn_contp);
-+          DEBUG_LOG("Added TS_HTTP_SEND_REQUEST_HDR_HOOK, TS_HTTP_SEND_RESPONSE_HDR_HOOK, and TS_HTTP_TXN_CLOSE_HOOK");
-+        }
-+      }
-+      TSHandleMLocRelease(hdr_bufp, req_hdrs, loc);
-+    } else {
-+      DEBUG_LOG("no range request header.");
-+    }
-+    TSHandleMLocRelease(hdr_bufp, req_hdrs, NULL);
-+  } else {
-+    DEBUG_LOG("failed to retrieve the server request");
-+  }
-+}
-+
-+/**
-+ * Restores the range request header if the request must be
-+ * satisfied from the origin and schedules the TS_READ_RESPONSE_HDR_HOOK.
-+ */
-+static void
-+handle_send_origin_request(TSCont contp, TSHttpTxn txnp, struct txndata *txn_state)
-+{
-+  TSMBuffer hdr_bufp;
-+  TSMLoc req_hdrs = NULL;
-+
-+  if (TS_SUCCESS == TSHttpTxnServerReqGet(txnp, &hdr_bufp, &req_hdrs) && txn_state->range_value != NULL) {
-+    if (set_header(hdr_bufp, req_hdrs, TS_MIME_FIELD_RANGE, TS_MIME_LEN_RANGE, txn_state->range_value,
-+                   strlen(txn_state->range_value))) {
-+      DEBUG_LOG("Added range header: %s", txn_state->range_value);
-+      TSHttpTxnHookAdd(txnp, TS_HTTP_READ_RESPONSE_HDR_HOOK, contp);
-+    }
-+  }
-+  TSHandleMLocRelease(hdr_bufp, req_hdrs, NULL);
-+}
-+
-+/**
-+ * Changes the response code back to a 206 Partial content before
-+ * replying to the client that requested a range.
-+ */
-+static void
-+handle_client_send_response(TSHttpTxn txnp, struct txndata *txn_state)
-+{
-+  bool partial_content_reason = false;
-+  char *p;
-+  int length;
-+  TSMBuffer response, hdr_bufp;
-+  TSMLoc resp_hdr, req_hdrs = NULL;
-+
-+  TSReturnCode result = TSHttpTxnClientRespGet(txnp, &response, &resp_hdr);
-+  DEBUG_LOG("result: %d", result);
-+  if (TS_SUCCESS == result) {
-+    TSHttpStatus status = TSHttpHdrStatusGet(response, resp_hdr);
-+    // a cached result will have a TS_HTTP_OK with a 'Partial Content' reason
-+    if ((p = (char *)TSHttpHdrReasonGet(response, resp_hdr, &length)) != NULL) {
-+      if ((length == 15) && (0 == strncasecmp(p, "Partial Content", length))) {
-+        partial_content_reason = true;
-+      }
-+    }
-+    DEBUG_LOG("%d %.*s", status, length, p);
-+    if (TS_HTTP_STATUS_OK == status && partial_content_reason) {
-+      DEBUG_LOG("Got TS_HTTP_STATUS_OK.");
-+      TSHttpHdrStatusSet(response, resp_hdr, TS_HTTP_STATUS_PARTIAL_CONTENT);
-+      DEBUG_LOG("Set response header to TS_HTTP_STATUS_PARTIAL_CONTENT.");
-+    }
-+  }
-+  // add the range request header back in so that range requests may be logged.
-+  if (TS_SUCCESS == TSHttpTxnClientReqGet(txnp, &hdr_bufp, &req_hdrs) && txn_state->range_value != NULL) {
-+    if (set_header(hdr_bufp, req_hdrs, TS_MIME_FIELD_RANGE, TS_MIME_LEN_RANGE, txn_state->range_value,
-+                   strlen(txn_state->range_value))) {
-+      DEBUG_LOG("added range header: %s", txn_state->range_value);
-+    } else {
-+      DEBUG_LOG("set_header() failed.");
-+    }
-+  } else {
-+    DEBUG_LOG("failed to get Request Headers");
-+  }
-+  TSHandleMLocRelease(response, resp_hdr, NULL);
-+  TSHandleMLocRelease(hdr_bufp, req_hdrs, NULL);
-+}
-+
-+/**
-+ * After receiving a range request response from the origin, change
-+ * the response code from a 206 Partial content to a 200 OK so that
-+ * the response will be written to cache.
-+ */
-+static void
-+handle_server_read_response(TSHttpTxn txnp, struct txndata *txn_state)
-+{
-+  TSMBuffer response;
-+  TSMLoc resp_hdr;
-+  TSHttpStatus status;
-+
-+  if (TS_SUCCESS == TSHttpTxnServerRespGet(txnp, &response, &resp_hdr)) {
-+    status = TSHttpHdrStatusGet(response, resp_hdr);
-+    if (TS_HTTP_STATUS_PARTIAL_CONTENT == status) {
-+      DEBUG_LOG("Got TS_HTTP_STATUS_PARTIAL_CONTENT.");
-+      TSHttpHdrStatusSet(response, resp_hdr, TS_HTTP_STATUS_OK);
-+      DEBUG_LOG("Set response header to TS_HTTP_STATUS_OK.");
-+      bool cacheable = TSHttpTxnIsCacheable(txnp, NULL, response);
-+      DEBUG_LOG("range is cacheable: %d", cacheable);
-+    } else if (TS_HTTP_STATUS_OK == status) {
-+      DEBUG_LOG("The origin does not support range requests, attempting to disable cache write.");
-+      if (TS_SUCCESS == TSHttpTxnServerRespNoStoreSet(txnp, 1)) {
-+        DEBUG_LOG("Cache write has been disabled for this transaction.");
-+      } else {
-+        DEBUG_LOG("Unable to disable cache write for this transaction.");
-+      }
-+    }
-+  }
-+  TSHandleMLocRelease(response, resp_hdr, NULL);
-+}
-+
-+/**
-+ * Remove a header (fully) from an TSMLoc / TSMBuffer. Return the number
-+ * of fields (header values) we removed.
-+ *
-+ * From background_fetch.cc
-+ */
-+static int
-+remove_header(TSMBuffer bufp, TSMLoc hdr_loc, const char *header, int len)
-+{
-+  TSMLoc field = TSMimeHdrFieldFind(bufp, hdr_loc, header, len);
-+  int cnt = 0;
-+
-+  while (field) {
-+    TSMLoc tmp = TSMimeHdrFieldNextDup(bufp, hdr_loc, field);
-+
-+    ++cnt;
-+    TSMimeHdrFieldDestroy(bufp, hdr_loc, field);
-+    TSHandleMLocRelease(bufp, hdr_loc, field);
-+    field = tmp;
-+  }
-+
-+  return cnt;
-+}
-+
-+/**
-+ * Set a header to a specific value. This will avoid going to through a
-+ * remove / add sequence in case of an existing header.
-+ * but clean.
-+ *
-+ * From background_fetch.cc
-+ */
-+static bool
-+set_header(TSMBuffer bufp, TSMLoc hdr_loc, const char *header, int len, const char *val, int val_len)
-+{
-+  if (!bufp || !hdr_loc || !header || len <= 0 || !val || val_len <= 0) {
-+    return false;
-+  }
-+
-+  DEBUG_LOG("header: %s, len: %d, val: %s, val_len: %d", header, len, val, val_len);
-+  bool ret = false;
-+  TSMLoc field_loc = TSMimeHdrFieldFind(bufp, hdr_loc, header, len);
-+
-+  if (!field_loc) {
-+    // No existing header, so create one
-+    if (TS_SUCCESS == TSMimeHdrFieldCreateNamed(bufp, hdr_loc, header, len, &field_loc)) {
-+      if (TS_SUCCESS == TSMimeHdrFieldValueStringSet(bufp, hdr_loc, field_loc, -1, val, val_len)) {
-+        TSMimeHdrFieldAppend(bufp, hdr_loc, field_loc);
-+        ret = true;
-+      }
-+      TSHandleMLocRelease(bufp, hdr_loc, field_loc);
-+    }
-+  } else {
-+    TSMLoc tmp = NULL;
-+    bool first = true;
-+
-+    while (field_loc) {
-+      if (first) {
-+        first = false;
-+        if (TS_SUCCESS == TSMimeHdrFieldValueStringSet(bufp, hdr_loc, field_loc, -1, val, val_len)) {
-+          ret = true;
-+        }
-+      } else {
-+        TSMimeHdrFieldDestroy(bufp, hdr_loc, field_loc);
-+      }
-+      tmp = TSMimeHdrFieldNextDup(bufp, hdr_loc, field_loc);
-+      TSHandleMLocRelease(bufp, hdr_loc, field_loc);
-+      field_loc = tmp;
-+    }
-+  }
-+
-+  return ret;
-+}
-+
-+/**
-+ * Remap initialization.
-+ */
-+TSReturnCode
-+TSRemapInit(TSRemapInterface *api_info, char *errbuf, int errbuf_size)
-+{
-+  if (!api_info) {
-+    strncpy(errbuf, "[tsremap_init] - Invalid TSRemapInterface argument", errbuf_size - 1);
-+    return TS_ERROR;
-+  }
-+
-+  if (api_info->tsremap_version < TSREMAP_VERSION) {
-+    snprintf(errbuf, errbuf_size - 1, "[TSRemapInit] - Incorrect API version %ld.%ld", api_info->tsremap_version >> 16,
-+             (api_info->tsremap_version & 0xffff));
-+    return TS_ERROR;
-+  }
-+
-+  DEBUG_LOG("cache_range_requests remap is successfully initialized.");
-+  return TS_SUCCESS;
-+}
-+
-+/**
-+ * not used.
-+ */
-+TSReturnCode
-+TSRemapNewInstance(int argc, char *argv[], void **ih, char * /*errbuf */, int /* errbuf_size */)
-+{
-+  return TS_SUCCESS;
-+}
-+
-+/**
-+ * not used.
-+ */
-+void
-+TSRemapDeleteInstance(void *ih)
-+{
-+  DEBUG_LOG("no op");
-+}
-+
-+/**
-+ * Remap entry point.
-+ */
-+TSRemapStatus
-+TSRemapDoRemap(void *ih, TSHttpTxn txnp, TSRemapRequestInfo * /* rri */)
-+{
-+  range_header_check(txnp);
-+  return TSREMAP_NO_REMAP;
-+}
-+
-+/**
-+ * Global plugin initialization.
-+ */
-+void
-+TSPluginInit(int argc, const char *argv[])
-+{
-+  TSPluginRegistrationInfo info;
-+  TSCont txnp_cont;
-+
-+  info.plugin_name = (char *)PLUGIN_NAME;
-+  info.vendor_name = (char *)"Comcast";
-+  info.support_email = (char *)"John_Rushford@cable.comcast.com";
-+
-+  if (TSPluginRegister(TS_SDK_VERSION_3_0, &info) != TS_SUCCESS) {
-+    ERROR_LOG("Plugin registration failed.\n");
-+    ERROR_LOG("Unable to initialize plugin (disabled).");
-+    return;
-+  }
-+
-+  if (NULL == (txnp_cont = TSContCreate((TSEventFunc)handle_read_request_header, NULL))) {
-+    ERROR_LOG("failed to create the transaction continuation handler.");
-+    return;
-+  } else {
-+    TSHttpHookAdd(TS_HTTP_READ_REQUEST_HDR_HOOK, txnp_cont);
-+  }
-+}
-+
-+/**
-+ * Transaction event handler.
-+ */
-+static void
-+transaction_handler(TSCont contp, TSEvent event, void *edata)
-+{
-+  TSHttpTxn txnp = static_cast<TSHttpTxn>(edata);
-+  struct txndata *txn_state = (struct txndata *)TSContDataGet(contp);
-+
-+  switch (event) {
-+  case TS_EVENT_HTTP_READ_RESPONSE_HDR:
-+    handle_server_read_response(txnp, txn_state);
-+    break;
-+  case TS_EVENT_HTTP_SEND_REQUEST_HDR:
-+    handle_send_origin_request(contp, txnp, txn_state);
-+    break;
-+  case TS_EVENT_HTTP_SEND_RESPONSE_HDR:
-+    handle_client_send_response(txnp, txn_state);
-+    break;
-+  case TS_EVENT_HTTP_TXN_CLOSE:
-+    if (txn_state != NULL && txn_state->range_value != NULL)
-+      TSfree(txn_state->range_value);
-+    if (txn_state != NULL)
-+      TSfree(txn_state);
-+    TSContDestroy(contp);
-+    break;
-+  default:
-+    TSAssert(!"Unexpected event");
-+    break;
-+  }
-+  TSHttpTxnReenable(txnp, TS_EVENT_HTTP_CONTINUE);
-+}
-diff --git a/plugins/experimental/regex_revalidate/regex_revalidate.c b/plugins/experimental/regex_revalidate/regex_revalidate.c
-index f25c36f..d261308 100644
---- a/plugins/experimental/regex_revalidate/regex_revalidate.c
-+++ b/plugins/experimental/regex_revalidate/regex_revalidate.c
-@@ -40,8 +40,35 @@
- #include <pcre.h>
- #endif
- 
--#define LOG_PREFIX "regex_revalidate"
--#define CONFIG_TMOUT 60000
-+typedef struct invalidate_t {
-+  const char *regex_text;
-+  pcre *regex;
-+  pcre_extra *regex_extra;
-+  time_t epoch;
-+  time_t expiry;
-+  struct invalidate_t *volatile next;
-+} invalidate_t;
-+
-+typedef invalidate_t config_t;
-+
-+typedef struct {
-+  char *config_path;
-+  volatile time_t last_load;
-+  config_t *config;
-+  TSTextLogObject log;
-+} config_holder_t;
-+
-+static int free_handler(TSCont cont, TSEvent event, void *edata);
-+static int config_handler(TSCont cont, TSEvent event, void *edata);
-+static config_t *get_config(TSCont cont);
-+static config_holder_t *new_config_holder();
-+static config_holder_t *init_config_holder(config_holder_t *config_holder, const char *path);
-+static void free_config_holder_t(config_holder_t *config_holder);
-+static void schedule_free_invalidate_t(invalidate_t *iptr);
-+
-+#define PLUGIN_TAG "regex_revalidate"
-+#define DEFAULT_CONFIG_NAME "regex_revalidate.config"
-+#define PRUNE_TMOUT 60000
- #define FREE_TMOUT 300000
- #define OVECTOR_SIZE 30
- #define LOG_ROLL_INTERVAL 86400
-@@ -59,22 +86,6 @@ ts_free(void *s)
-   return TSfree(s);
- }
- 
--typedef struct invalidate_t {
--  const char *regex_text;
--  pcre *regex;
--  pcre_extra *regex_extra;
--  time_t epoch;
--  time_t expiry;
--  struct invalidate_t *next;
--} invalidate_t;
--
--typedef struct {
--  invalidate_t *volatile invalidate_list;
--  char *config_file;
--  volatile time_t last_load;
--  TSTextLogObject log;
--} plugin_state_t;
--
- static invalidate_t *
- init_invalidate_t(invalidate_t *i)
- {
-@@ -111,65 +122,6 @@ free_invalidate_t_list(invalidate_t *i)
-   free_invalidate_t(i);
- }
- 
--static plugin_state_t *
--init_plugin_state_t(plugin_state_t *pstate)
--{
--  pstate->invalidate_list = NULL;
--  pstate->config_file = NULL;
--  pstate->last_load = 0;
--  pstate->log = NULL;
--  return pstate;
--}
--
--static void
--free_plugin_state_t(plugin_state_t *pstate)
--{
--  if (pstate->invalidate_list)
--    free_invalidate_t_list(pstate->invalidate_list);
--  if (pstate->config_file)
--    TSfree(pstate->config_file);
--  if (pstate->log)
--    TSTextLogObjectDestroy(pstate->log);
--  TSfree(pstate);
--}
--
--static invalidate_t *
--copy_invalidate_t(invalidate_t *i)
--{
--  invalidate_t *iptr;
--  const char *errptr;
--  int erroffset;
--
--  iptr = (invalidate_t *)TSmalloc(sizeof(invalidate_t));
--  iptr->regex_text = TSstrdup(i->regex_text);
--  iptr->regex = pcre_compile(iptr->regex_text, 0, &errptr, &erroffset, NULL); // There is no pcre_copy :-(
--  iptr->regex_extra = pcre_study(iptr->regex, 0, &errptr);                    // Assuming no errors since this worked before :-/
--  iptr->epoch = i->epoch;
--  iptr->expiry = i->expiry;
--  iptr->next = NULL;
--  return iptr;
--}
--
--static invalidate_t *
--copy_config(invalidate_t *old_list)
--{
--  invalidate_t *new_list = NULL;
--  invalidate_t *iptr_old, *iptr_new;
--
--  if (old_list) {
--    new_list = copy_invalidate_t(old_list);
--    iptr_old = old_list->next;
--    iptr_new = new_list;
--    while (iptr_old) {
--      iptr_new->next = copy_invalidate_t(iptr_old);
--      iptr_new = iptr_new->next;
--      iptr_old = iptr_old->next;
--    }
--  }
--
--  return new_list;
--}
--
- static bool
- prune_config(invalidate_t **i)
- {
-@@ -184,14 +136,20 @@ prune_config(invalidate_t **i)
-     ilast = NULL;
-     while (iptr) {
-       if (difftime(iptr->expiry, now) < 0) {
--        TSDebug(LOG_PREFIX, "Removing %s expiry: %d now: %d", iptr->regex_text, (int)iptr->expiry, (int)now);
-+        TSDebug(PLUGIN_TAG, "Removing %s expiry: %d now: %d", iptr->regex_text, (int)iptr->expiry, (int)now);
-+        TSError(PLUGIN_TAG " - Removing %s expiry: %d now: %d", iptr->regex_text, (int)iptr->expiry, (int)now);
-         if (ilast) {
-+          // jlaue: TODO is this right?
-+          //                    iptr = __sync_val_compare_and_swap(&(ilast->next), ilast->next, iptr->next);
-           ilast->next = iptr->next;
--          free_invalidate_t(iptr);
-+          //                    free_invalidate_t(iptr);
-+          schedule_free_invalidate_t(iptr);
-           iptr = ilast->next;
-+
-         } else {
-           *i = iptr->next;
--          free_invalidate_t(iptr);
-+          //                    free_invalidate_t(iptr);
-+          schedule_free_invalidate_t(iptr);
-           iptr = *i;
-         }
-         pruned = true;
-@@ -204,161 +162,44 @@ prune_config(invalidate_t **i)
-   return pruned;
- }
- 
--static bool
--load_config(plugin_state_t *pstate, invalidate_t **ilist)
--{
--  FILE *fs;
--  struct stat s;
--  size_t path_len;
--  char *path;
--  char line[LINE_MAX];
--  time_t now;
--  pcre *config_re;
--  const char *errptr;
--  int erroffset, ovector[OVECTOR_SIZE], rc;
--  int ln = 0;
--  invalidate_t *iptr, *i;
--
--  if (pstate->config_file[0] != '/') {
--    path_len = strlen(TSConfigDirGet()) + strlen(pstate->config_file) + 2;
--    path = alloca(path_len);
--    snprintf(path, path_len, "%s/%s", TSConfigDirGet(), pstate->config_file);
--  } else
--    path = pstate->config_file;
--  if (stat(path, &s) < 0) {
--    TSDebug(LOG_PREFIX, "Could not stat %s", path);
--    return false;
--  }
--  if (s.st_mtime > pstate->last_load) {
--    now = time(NULL);
--    if (!(fs = fopen(path, "r"))) {
--      TSDebug(LOG_PREFIX, "Could not open %s for reading", path);
--      return false;
--    }
--    config_re = pcre_compile("^([^#].+?)\\s+(\\d+)\\s*$", 0, &errptr, &erroffset, NULL);
--    while (fgets(line, LINE_MAX, fs) != NULL) {
--      ln++;
--      TSDebug(LOG_PREFIX, "Processing: %d %s", ln, line);
--      rc = pcre_exec(config_re, NULL, line, strlen(line), 0, 0, ovector, OVECTOR_SIZE);
--      if (rc == 3) {
--        i = (invalidate_t *)TSmalloc(sizeof(invalidate_t));
--        init_invalidate_t(i);
--        pcre_get_substring(line, ovector, rc, 1, &i->regex_text);
--        i->epoch = now;
--        i->expiry = atoi(line + ovector[4]);
--        i->regex = pcre_compile(i->regex_text, 0, &errptr, &erroffset, NULL);
--        if (i->expiry <= i->epoch) {
--          TSDebug(LOG_PREFIX, "Rule is already expired!");
--          free_invalidate_t(i);
--        } else if (i->regex == NULL) {
--          TSDebug(LOG_PREFIX, "%s did not compile", i->regex_text);
--          free_invalidate_t(i);
--        } else {
--          i->regex_extra = pcre_study(i->regex, 0, &errptr);
--          if (!*ilist) {
--            *ilist = i;
--            TSDebug(LOG_PREFIX, "Created new list and Loaded %s %d %d", i->regex_text, (int)i->epoch, (int)i->expiry);
--          } else {
--            iptr = *ilist;
--            while (1) {
--              if (strcmp(i->regex_text, iptr->regex_text) == 0) {
--                if (iptr->expiry != i->expiry) {
--                  TSDebug(LOG_PREFIX, "Updating duplicate %s", i->regex_text);
--                  iptr->epoch = i->epoch;
--                  iptr->expiry = i->expiry;
--                }
--                free_invalidate_t(i);
--                i = NULL;
--                break;
--              } else if (!iptr->next)
--                break;
--              else
--                iptr = iptr->next;
--            }
--            if (i) {
--              iptr->next = i;
--              TSDebug(LOG_PREFIX, "Loaded %s %d %d", i->regex_text, (int)i->epoch, (int)i->expiry);
--            }
--          }
--        }
--      } else
--        TSDebug(LOG_PREFIX, "Skipping line %d", ln);
--    }
--    pcre_free(config_re);
--    fclose(fs);
--    pstate->last_load = s.st_mtime;
--    return true;
--  } else
--    TSDebug(LOG_PREFIX, "File mod time is not newer: %d >= %d", (int)pstate->last_load, (int)s.st_mtime);
--  return false;
--}
- 
- static void
--list_config(plugin_state_t *pstate, invalidate_t *i)
-+list_config(config_holder_t *config_holder, invalidate_t *i)
- {
-   invalidate_t *iptr;
- 
--  TSDebug(LOG_PREFIX, "Current config:");
--  if (pstate->log)
--    TSTextLogObjectWrite(pstate->log, "Current config:");
-+  TSDebug(PLUGIN_TAG, "Current config:");
-+  if (config_holder->log)
-+    TSTextLogObjectWrite(config_holder->log, "Current config:");
-   if (i) {
-     iptr = i;
-     while (iptr) {
--      TSDebug(LOG_PREFIX, "%s epoch: %d expiry: %d", iptr->regex_text, (int)iptr->epoch, (int)iptr->expiry);
--      if (pstate->log)
--        TSTextLogObjectWrite(pstate->log, "%s epoch: %d expiry: %d", iptr->regex_text, (int)iptr->epoch, (int)iptr->expiry);
-+      TSDebug(PLUGIN_TAG, "%s epoch: %d expiry: %d", iptr->regex_text, (int)iptr->epoch, (int)iptr->expiry);
-+      if (config_holder->log)
-+        TSTextLogObjectWrite(config_holder->log, "%s epoch: %d expiry: %d", iptr->regex_text, (int)iptr->epoch, (int)iptr->expiry);
-       iptr = iptr->next;
-     }
-   } else {
--    TSDebug(LOG_PREFIX, "EMPTY");
--    if (pstate->log)
--      TSTextLogObjectWrite(pstate->log, "EMPTY");
-+    TSDebug(PLUGIN_TAG, "EMPTY");
-+    if (config_holder->log)
-+      TSTextLogObjectWrite(config_holder->log, "EMPTY");
-   }
- }
- 
- static int
--free_handler(TSCont cont, TSEvent event ATS_UNUSED, void *edata ATS_UNUSED)
-+config_pruner(TSCont cont, TSEvent event ATS_UNUSED, void *edata ATS_UNUSED)
- {
--  invalidate_t *iptr;
-+  invalidate_t *i;
- 
--  TSDebug(LOG_PREFIX, "Freeing old config");
--  iptr = (invalidate_t *)TSContDataGet(cont);
--  free_invalidate_t_list(iptr);
--  TSContDestroy(cont);
--  return 0;
--}
-+  TSDebug(PLUGIN_TAG, "config_pruner");
-+  config_holder_t *configh = (config_holder_t *)TSContDataGet(cont);
-+  i = configh->config;
- 
--static int
--config_handler(TSCont cont, TSEvent event ATS_UNUSED, void *edata ATS_UNUSED)
--{
--  plugin_state_t *pstate;
--  invalidate_t *i, *iptr;
--  TSCont free_cont;
--  bool updated;
-+  prune_config(&i);
- 
--  TSDebug(LOG_PREFIX, "In config Handler");
--  pstate = (plugin_state_t *)TSContDataGet(cont);
--  i = copy_config(pstate->invalidate_list);
-+  configh->config = i;
- 
--  updated = prune_config(&i);
--  updated = load_config(pstate, &i) || updated;
--
--  if (updated) {
--    list_config(pstate, i);
--    iptr = __sync_val_compare_and_swap(&(pstate->invalidate_list), pstate->invalidate_list, i);
--
--    if (iptr) {
--      free_cont = TSContCreate(free_handler, NULL);
--      TSContDataSet(free_cont, (void *)iptr);
--      TSContSchedule(free_cont, FREE_TMOUT, TS_THREAD_POOL_TASK);
--    }
--  } else {
--    TSDebug(LOG_PREFIX, "No Changes");
--    if (i)
--      free_invalidate_t_list(i);
--  }
--
--  TSContSchedule(cont, CONFIG_TMOUT, TS_THREAD_POOL_TASK);
-+  TSContSchedule(cont, PRUNE_TMOUT, TS_THREAD_POOL_TASK);
-   return 0;
- }
- 
-@@ -387,7 +228,6 @@ main_handler(TSCont cont, TSEvent event, void *edata)
-   TSHttpTxn txn = (TSHttpTxn)edata;
-   int status;
-   invalidate_t *iptr;
--  plugin_state_t *pstate;
- 
-   time_t date = 0, now = 0;
-   char *url = NULL;
-@@ -397,8 +237,7 @@ main_handler(TSCont cont, TSEvent event, void *edata)
-   case TS_EVENT_HTTP_CACHE_LOOKUP_COMPLETE:
-     if (TSHttpTxnCacheLookupStatusGet(txn, &status) == TS_SUCCESS) {
-       if (status == TS_CACHE_LOOKUP_HIT_FRESH) {
--        pstate = (plugin_state_t *)TSContDataGet(cont);
--        iptr = pstate->invalidate_list;
-+        iptr = get_config(cont);
-         while (iptr) {
-           if (!date) {
-             date = get_date_from_cached_hdr(txn);
-@@ -410,7 +249,7 @@ main_handler(TSCont cont, TSEvent event, void *edata)
-             if (pcre_exec(iptr->regex, iptr->regex_extra, url, url_len, 0, 0, NULL, 0) >= 0) {
-               TSHttpTxnCacheLookupStatusSet(txn, TS_CACHE_LOOKUP_HIT_STALE);
-               iptr = NULL;
--              TSDebug(LOG_PREFIX, "Forced revalidate - %.*s", url_len, url);
-+              TSDebug(PLUGIN_TAG, "Forced revalidate - %.*s", url_len, url);
-             }
-           }
-           if (iptr)
-@@ -457,13 +296,12 @@ TSPluginInit(int argc, const char *argv[])
- {
-   TSPluginRegistrationInfo info;
-   TSCont main_cont, config_cont;
--  plugin_state_t *pstate;
--  invalidate_t *iptr = NULL;
-+  config_holder_t *config_holder;
-+  char *path = NULL;
- 
--  TSDebug(LOG_PREFIX, "Starting plugin init.");
-+  TSDebug(PLUGIN_TAG, "Starting plugin init.");
- 
--  pstate = (plugin_state_t *)TSmalloc(sizeof(plugin_state_t));
--  init_plugin_state_t(pstate);
-+  config_holder = new_config_holder();
- 
-   int c;
-   optind = 1;
-@@ -473,46 +311,48 @@ TSPluginInit(int argc, const char *argv[])
-   while ((c = getopt_long(argc, (char *const *)argv, "c:l:", longopts, NULL)) != -1) {
-     switch (c) {
-     case 'c':
--      pstate->config_file = TSstrdup(optarg);
-+      path = TSstrdup(optarg);
-       break;
-     case 'l':
--      TSTextLogObjectCreate(optarg, TS_LOG_MODE_ADD_TIMESTAMP, &pstate->log);
--      TSTextLogObjectRollingEnabledSet(pstate->log, 1);
--      TSTextLogObjectRollingIntervalSecSet(pstate->log, LOG_ROLL_INTERVAL);
--      TSTextLogObjectRollingOffsetHrSet(pstate->log, LOG_ROLL_OFFSET);
-+      TSTextLogObjectCreate(optarg, TS_LOG_MODE_ADD_TIMESTAMP, &config_holder->log);
-+      TSTextLogObjectRollingEnabledSet(config_holder->log, 1);
-+      TSTextLogObjectRollingIntervalSecSet(config_holder->log, LOG_ROLL_INTERVAL);
-+      TSTextLogObjectRollingOffsetHrSet(config_holder->log, LOG_ROLL_OFFSET);
-       break;
-     default:
-       break;
-     }
-   }
-+  config_holder = init_config_holder(config_holder, path);
- 
--  if (!pstate->config_file) {
-+  if (!config_holder->config_path) {
-     TSError("Plugin requires a --config option along with a config file name.");
--    free_plugin_state_t(pstate);
-+    free_config_holder_t(config_holder);
-     return;
-   }
- 
--  if (!load_config(pstate, &iptr))
--    TSDebug(LOG_PREFIX, "Problem loading config from file %s", pstate->config_file);
-+  //    if (!load_config(free_config_holder_t, &iptr))
-+  if (config_holder->config)
-+    TSDebug(PLUGIN_TAG, "Problem loading config from file %s", config_holder->config_path);
-   else {
--    pstate->invalidate_list = iptr;
--    list_config(pstate, iptr);
-+    //        config_holder->config = iptr;
-+    list_config(config_holder, config_holder->config);
-   }
- 
--  info.plugin_name = LOG_PREFIX;
-+  info.plugin_name = PLUGIN_TAG;
-   info.vendor_name = "Apache Software Foundation";
-   info.support_email = "dev@trafficserver.apache.org";
- 
-   if (TSPluginRegister(TS_SDK_VERSION_3_0, &info) != TS_SUCCESS) {
-     TSError("Plugin registration failed.");
--    free_plugin_state_t(pstate);
-+    free_config_holder_t(config_holder);
-     return;
-   } else
--    TSDebug(LOG_PREFIX, "Plugin registration succeeded.");
-+    TSDebug(PLUGIN_TAG, "Plugin registration succeeded.");
- 
-   if (!check_ts_version()) {
-     TSError("Plugin requires Traffic Server %d.%d.%d", TS_VERSION_MAJOR, TS_VERSION_MINOR, TS_VERSION_MICRO);
--    free_plugin_state_t(pstate);
-+    free_config_holder_t(config_holder);
-     return;
-   }
- 
-@@ -520,12 +360,235 @@ TSPluginInit(int argc, const char *argv[])
-   pcre_free = &ts_free;
- 
-   main_cont = TSContCreate(main_handler, NULL);
--  TSContDataSet(main_cont, (void *)pstate);
-+  TSContDataSet(main_cont, (void *)config_holder);
-   TSHttpHookAdd(TS_HTTP_CACHE_LOOKUP_COMPLETE_HOOK, main_cont);
- 
-+  config_cont = TSContCreate(config_pruner, TSMutexCreate());
-+  TSContDataSet(config_cont, (void *)config_holder);
-+  TSContSchedule(config_cont, PRUNE_TMOUT, TS_THREAD_POOL_TASK);
-+
-   config_cont = TSContCreate(config_handler, TSMutexCreate());
--  TSContDataSet(config_cont, (void *)pstate);
--  TSContSchedule(config_cont, CONFIG_TMOUT, TS_THREAD_POOL_TASK);
-+  TSContDataSet(config_cont, (void *)config_holder);
-+  TSMgmtUpdateRegister(config_cont, PLUGIN_TAG);
-+
-+  TSDebug(PLUGIN_TAG, "Plugin Init Complete.");
-+}
-+
-+static config_t *
-+new_config(TSFile fs)
-+{
-+  char line[LINE_MAX];
-+  time_t now;
-+  pcre *config_re;
-+  const char *errptr;
-+  int erroffset, ovector[OVECTOR_SIZE], rc;
-+  int ln = 0;
-+  invalidate_t *iptr, *i, *config = 0;
-+
-+  now = time(NULL);
-+
-+  config_re = pcre_compile("^([^#].+?)\\s+(\\d+)\\s*$", 0, &errptr, &erroffset, NULL);
-+  while (TSfgets(fs, line, LINE_MAX - 1) != NULL) {
-+    ln++;
-+    TSDebug(PLUGIN_TAG, "Processing: %d %s", ln, line);
-+    rc = pcre_exec(config_re, NULL, line, strlen(line), 0, 0, ovector, OVECTOR_SIZE);
-+    if (rc == 3) {
-+      i = (invalidate_t *)TSmalloc(sizeof(invalidate_t));
-+      init_invalidate_t(i);
-+      pcre_get_substring(line, ovector, rc, 1, &i->regex_text);
-+      i->epoch = now;
-+      i->expiry = atoi(line + ovector[4]);
-+      i->regex = pcre_compile(i->regex_text, 0, &errptr, &erroffset, NULL);
-+      if (i->expiry <= i->epoch) {
-+        TSDebug(PLUGIN_TAG, "NOT Loaded, already expired! %s %d %d", i->regex_text, (int)i->epoch, (int)i->expiry);
-+        TSError(PLUGIN_TAG " - NOT Loaded, already expired: %s %d %d", i->regex_text, (int)i->epoch, (int)i->expiry);
-+        free_invalidate_t(i);
-+      } else if (i->regex == NULL) {
-+        TSDebug(PLUGIN_TAG, "%s did not compile", i->regex_text);
-+        free_invalidate_t(i);
-+      } else {
-+        i->regex_extra = pcre_study(i->regex, 0, &errptr);
-+        if (!config) {
-+          config = i;
-+          TSDebug(PLUGIN_TAG, "Created new list and Loaded %s %d %d", i->regex_text, (int)i->epoch, (int)i->expiry);
-+          TSError(PLUGIN_TAG " - New Revalidate: %s %d %d", i->regex_text, (int)i->epoch, (int)i->expiry);
-+        } else {
-+          iptr = config;
-+          while (1) {
-+            if (strcmp(i->regex_text, iptr->regex_text) == 0) {
-+              if (iptr->expiry != i->expiry) {
-+                TSDebug(PLUGIN_TAG, "Updating duplicate %s", i->regex_text);
-+                iptr->epoch = i->epoch;
-+                iptr->expiry = i->expiry;
-+              }
-+              free_invalidate_t(i);
-+              i = NULL;
-+              break;
-+            } else if (!iptr->next)
-+              break;
-+            else
-+              iptr = iptr->next;
-+          }
-+          if (i) {
-+            iptr->next = i;
-+            TSDebug(PLUGIN_TAG, "Loaded %s %d %d", i->regex_text, (int)i->epoch, (int)i->expiry);
-+          }
-+        }
-+      }
-+    } else
-+      TSDebug(PLUGIN_TAG, "Skipping line %d", ln);
-+  }
-+  pcre_free(config_re);
-+
-+  return config;
-+}
-+
-+static void
-+delete_config(config_t *config)
-+{
-+  TSDebug(PLUGIN_TAG, "Freeing config");
-+  free_invalidate_t_list(config);
-+}
-+
-+static int
-+free_invalidate_handler(TSCont cont, TSEvent event ATS_UNUSED, void *edata ATS_UNUSED)
-+{
-+  invalidate_t *i = (invalidate_t *)TSContDataGet(cont);
-+  free_invalidate_t(i);
-+  TSContDestroy(cont);
-+  return 0;
-+}
-+
-+static void
-+schedule_free_invalidate_t(invalidate_t *iptr)
-+{
-+  TSCont free_cont;
-+  free_cont = TSContCreate(free_invalidate_handler, NULL);
-+  TSContDataSet(free_cont, (void *)iptr);
-+  TSContSchedule(free_cont, FREE_TMOUT, TS_THREAD_POOL_TASK);
-+  return;
-+}
- 
--  TSDebug(LOG_PREFIX, "Plugin Init Complete.");
-+static config_t *
-+get_config(TSCont cont)
-+{
-+  config_holder_t *configh = (config_holder_t *)TSContDataGet(cont);
-+  if (!configh) {
-+    return 0;
-+  }
-+  return configh->config;
-+}
-+
-+static void
-+load_config_file(config_holder_t *config_holder)
-+{
-+  TSFile fh;
-+  struct stat s;
-+
-+  config_t *newconfig, *oldconfig;
-+  TSCont free_cont;
-+
-+  // check date
-+  if (stat(config_holder->config_path, &s) < 0) {
-+    TSDebug(PLUGIN_TAG, "Could not stat %s", config_holder->config_path);
-+    if (config_holder->config) {
-+      return;
-+    }
-+  } else {
-+    TSDebug(PLUGIN_TAG, "s.st_mtime=%lu, last_load=%lu", s.st_mtime, config_holder->last_load);
-+    if (s.st_mtime < config_holder->last_load) {
-+      return;
-+    }
-+  }
-+
-+  TSDebug(PLUGIN_TAG, "Opening config file: %s", config_holder->config_path);
-+  fh = TSfopen(config_holder->config_path, "r");
-+  TSError(PLUGIN_TAG " - Reading config: %s", config_holder->config_path);
-+
-+  if (!fh) {
-+    TSError("[%s] Unable to open config: %s.\n", PLUGIN_TAG, config_holder->config_path);
-+    return;
-+  }
-+
-+  newconfig = 0;
-+  newconfig = new_config(fh);
-+  if (newconfig) {
-+    config_holder->last_load = time(NULL);
-+    config_t **confp = &(config_holder->config);
-+    oldconfig = __sync_lock_test_and_set(confp, newconfig);
-+    if (oldconfig) {
-+      TSDebug(PLUGIN_TAG, "scheduling free: %p (%p)", oldconfig, newconfig);
-+      free_cont = TSContCreate(free_handler, NULL);
-+      TSContDataSet(free_cont, (void *)oldconfig);
-+      TSContSchedule(free_cont, FREE_TMOUT, TS_THREAD_POOL_TASK);
-+    }
-+  }
-+  if (fh)
-+    TSfclose(fh);
-+  return;
-+}
-+
-+static config_holder_t *
-+new_config_holder(void)
-+{
-+  config_holder_t *config_holder = TSmalloc(sizeof(config_holder_t));
-+  return config_holder;
-+}
-+
-+static config_holder_t *
-+init_config_holder(config_holder_t *config_holder, const char *path)
-+{
-+  int path_len = 0;
-+  config_holder->config_path = 0;
-+  config_holder->config = 0;
-+  config_holder->last_load = 0;
-+  config_holder->log = 0;
-+
-+  if (!path)
-+    path = DEFAULT_CONFIG_NAME;
-+  if (path[0] != '/') {
-+    path_len = strlen(TSConfigDirGet()) + strlen(path) + 2;
-+    config_holder->config_path = ts_malloc(path_len);
-+    snprintf(config_holder->config_path, path_len, "%s/%s", TSConfigDirGet(), path);
-+    TSDebug(PLUGIN_TAG, "path: '%s' len=%d", config_holder->config_path, path_len);
-+  } else
-+    config_holder->config_path = TSstrdup(path);
-+
-+  load_config_file(config_holder);
-+  return config_holder;
-+}
-+
-+static void
-+free_config_holder_t(config_holder_t *config_holder)
-+{
-+  if (config_holder->config)
-+    free_invalidate_t_list(config_holder->config);
-+  if (config_holder->config_path)
-+    TSfree(config_holder->config_path);
-+  if (config_holder->log)
-+    TSTextLogObjectDestroy(config_holder->log);
-+  TSfree(config_holder);
-+}
-+
-+static int
-+free_handler(TSCont cont, TSEvent event ATS_UNUSED, void *edata ATS_UNUSED)
-+{
-+  config_t *config;
-+
-+  TSDebug(PLUGIN_TAG, "Freeing old config");
-+  config = (config_t *)TSContDataGet(cont);
-+  delete_config(config);
-+  TSContDestroy(cont);
-+  return 0;
-+}
-+
-+static int
-+config_handler(TSCont cont, TSEvent event ATS_UNUSED, void *edata ATS_UNUSED)
-+{
-+  config_holder_t *config_holder;
-+
-+  TSDebug(PLUGIN_TAG, "In config Handler");
-+  config_holder = (config_holder_t *)TSContDataGet(cont);
-+  load_config_file(config_holder);
-+  return 0;
- }
-diff --git a/plugins/experimental/remap_stats/remap_stats.c b/plugins/experimental/remap_stats/remap_stats.c
-index e231ec2..8d3f987 100644
---- a/plugins/experimental/remap_stats/remap_stats.c
-+++ b/plugins/experimental/remap_stats/remap_stats.c
-@@ -23,12 +23,14 @@
- #include "ink_defs.h"
- 
- #include "ts/ts.h"
-+
- #include <stdint.h>
- #include <stdbool.h>
- #include <string.h>
- #include <stdio.h>
- #include <getopt.h>
- #include <search.h>
-+#include <time.h>
- 
- #define PLUGIN_NAME "remap_stats"
- #define DEBUG_TAG PLUGIN_NAME
-@@ -36,18 +38,52 @@
- #define MAX_STAT_LENGTH (1 << 8)
- 
- typedef struct {
-+  time_t last_update;
-   bool post_remap_host;
--  int txn_slot;
-+  int txn_slot, schedule_delay;
-   TSStatPersistence persist_type;
-   TSMutex stat_creation_mutex;
- } config_t;
- 
-+typedef struct {
-+  int stat_id;
-+  time_t last_update;
-+} value_t;
-+
-+static int
-+lookup_stat(char *name, TSStatPersistence persist_type, TSMutex create_mutex)
-+{
-+  int stat_id = -1;
-+
-+  TSMutexLock(create_mutex);
-+  if (TS_ERROR == TSStatFindName((const char *)name, &stat_id)) {
-+    stat_id = TSStatCreate((const char *)name, TS_RECORDDATATYPE_INT, persist_type, TS_STAT_SYNC_SUM);
-+    if (stat_id == TS_ERROR)
-+      TSDebug(DEBUG_TAG, "Error creating stat_name: %s", name);
-+    else
-+      TSError("[%s:%d] Created stat_name: %s stat_id: %d", __FILE__, __LINE__, name, stat_id);
-+  }
-+  TSMutexUnlock(create_mutex);
-+
-+  return stat_id;
-+}
-+
-+static inline time_t
-+now()
-+{
-+  struct timespec ts;
-+
-+  clock_gettime(CLOCK_MONOTONIC_COARSE, &ts);
-+
-+  return ts.tv_sec;
-+}
- 
- static void
--stat_add(char *name, TSMgmtInt amount, TSStatPersistence persist_type, TSMutex create_mutex)
-+stat_add(char *name, TSMgmtInt amount, TSStatPersistence persist_type, TSMutex create_mutex, time_t config_last_update)
- {
-   int stat_id = -1;
-   ENTRY search, *result = NULL;
-+  value_t *val;
-   static __thread struct hsearch_data stat_cache;
-   static __thread bool hash_init = false;
- 
-@@ -65,32 +101,43 @@ stat_add(char *name, TSMgmtInt amount, TSStatPersistence persist_type, TSMutex c
-     // This is an unlikely path because we most likely have the stat cached
-     // so this mutex won't be much overhead and it fixes a race condition
-     // in the RecCore. Hopefully this can be removed in the future.
--    TSMutexLock(create_mutex);
--    if (TS_ERROR == TSStatFindName((const char *)name, &stat_id)) {
--      stat_id = TSStatCreate((const char *)name, TS_RECORDDATATYPE_INT, persist_type, TS_STAT_SYNC_SUM);
--      if (stat_id == TS_ERROR)
--        TSDebug(DEBUG_TAG, "Error creating stat_name: %s", name);
--      else
--        TSDebug(DEBUG_TAG, "Created stat_name: %s stat_id: %d", name, stat_id);
--    }
--    TSMutexUnlock(create_mutex);
-+    stat_id = lookup_stat(name, persist_type, create_mutex);
- 
-     if (stat_id >= 0) {
-       search.key = TSstrdup(name);
--      search.data = (void *)((intptr_t)stat_id);
-+      val = (value_t *)TSmalloc(sizeof(value_t));
-+      val->stat_id = stat_id;
-+      val->last_update = now();
-+      search.data = (void *)val;
-       hsearch_r(search, ENTER, &result, &stat_cache);
-       TSDebug(DEBUG_TAG, "Cached stat_name: %s stat_id: %d", name, stat_id);
-     }
--  } else
--    stat_id = (int)((intptr_t)result->data);
-+  } else {
-+    val = (value_t *)result->data;
-+
-+    // Stat expiry should be rare, so lets assume this is unlikely
-+    if (unlikely(val->last_update < config_last_update)) {
-+      stat_id = lookup_stat(name, persist_type, create_mutex);
-+      TSDebug(DEBUG_TAG, "stat_add(): running stat expiry check for stat_id:%d named: %s", stat_id, name);
-+      // Stat changes should not happen so lets assume this is unlikely
-+      if (unlikely(val->stat_id != stat_id)) {
-+        TSError("[%s:%d] Found difference stat_name: %s old stat_id: %d new stat_id: %d", __FILE__, __LINE__, name, val->stat_id,
-+                stat_id);
-+        val->stat_id = stat_id;
-+        val->last_update = now();
-+      }
-+    } else {
-+      stat_id = val->stat_id;
-+    }
-+  }
- 
--  if (likely(stat_id >= 0))
-+  if (likely(stat_id >= 0)) {
-+    TSDebug(DEBUG_TAG, "stat_add(): preparing to increment, name=%s, stat_id=%d, amount=%" PRId64, name, stat_id, amount);
-     TSStatIntIncrement(stat_id, amount);
--  else
-+  } else
-     TSDebug(DEBUG_TAG, "stat error! stat_name: %s stat_id: %d", name, stat_id);
- }
- 
--
- static char *
- get_effective_host(TSHttpTxn txn)
- {
-@@ -113,7 +160,6 @@ get_effective_host(TSHttpTxn txn)
-   return tmp;
- }
- 
--
- static int
- handle_read_req_hdr(TSCont cont, TSEvent event ATS_UNUSED, void *edata)
- {
-@@ -130,7 +176,6 @@ handle_read_req_hdr(TSCont cont, TSEvent event ATS_UNUSED, void *edata)
-   return 0;
- }
- 
--
- static int
- handle_post_remap(TSCont cont, TSEvent event ATS_UNUSED, void *edata)
- {
-@@ -148,14 +193,12 @@ handle_post_remap(TSCont cont, TSEvent event ATS_UNUSED, void *edata)
-   }
- 
-   TSHttpTxnReenable(txn, TS_EVENT_HTTP_CONTINUE);
--  TSDebug(DEBUG_TAG, "Post Remap Handler Finished");
-+  TSDebug(DEBUG_TAG, "Post Remap Handler Finished.");
-   return 0;
- }
- 
--
- #define CREATE_STAT_NAME(s, h, b) snprintf(s, MAX_STAT_LENGTH, "plugin.%s.%s.%s", PLUGIN_NAME, h, b)
- 
--
- static int
- handle_txn_close(TSCont cont, TSEvent event ATS_UNUSED, void *edata)
- {
-@@ -175,6 +218,8 @@ handle_txn_close(TSCont cont, TSEvent event ATS_UNUSED, void *edata)
- 
-   hostname = (char *)((uintptr_t)txnd & (~((uintptr_t)0x01))); // Get hostname
- 
-+  TSDebug(DEBUG_TAG, "handle_txn_close(): hostname: %s", hostname);
-+
-   if (txnd) {
-     if ((uintptr_t)txnd & 0x01) // remap succeeded?
-     {
-@@ -190,13 +235,13 @@ handle_txn_close(TSCont cont, TSEvent event ATS_UNUSED, void *edata)
-       in_bytes += TSHttpTxnClientReqBodyBytesGet(txn);
- 
-       CREATE_STAT_NAME(stat_name, remap, "in_bytes");
--      stat_add(stat_name, (TSMgmtInt)in_bytes, config->persist_type, config->stat_creation_mutex);
-+      stat_add(stat_name, (TSMgmtInt)in_bytes, config->persist_type, config->stat_creation_mutex, config->last_update);
- 
-       out_bytes = TSHttpTxnClientRespHdrBytesGet(txn);
-       out_bytes += TSHttpTxnClientRespBodyBytesGet(txn);
- 
-       CREATE_STAT_NAME(stat_name, remap, "out_bytes");
--      stat_add(stat_name, (TSMgmtInt)out_bytes, config->persist_type, config->stat_creation_mutex);
-+      stat_add(stat_name, (TSMgmtInt)out_bytes, config->persist_type, config->stat_creation_mutex, config->last_update);
- 
-       if (TSHttpTxnClientRespGet(txn, &buf, &hdr_loc) == TS_SUCCESS) {
-         status_code = (int)TSHttpHdrStatusGet(buf, hdr_loc);
-@@ -215,10 +260,10 @@ handle_txn_close(TSCont cont, TSEvent event ATS_UNUSED, void *edata)
-         else
-           CREATE_STAT_NAME(stat_name, remap, "status_other");
- 
--        stat_add(stat_name, 1, config->persist_type, config->stat_creation_mutex);
-+        stat_add(stat_name, 1, config->persist_type, config->stat_creation_mutex, config->last_update);
-       } else {
-         CREATE_STAT_NAME(stat_name, remap, "status_unknown");
--        stat_add(stat_name, 1, config->persist_type, config->stat_creation_mutex);
-+        stat_add(stat_name, 1, config->persist_type, config->stat_creation_mutex, config->last_update);
-       }
- 
-       if (remap != unknown)
-@@ -232,11 +277,43 @@ handle_txn_close(TSCont cont, TSEvent event ATS_UNUSED, void *edata)
-   return 0;
- }
- 
-+static int
-+do_time_update(TSCont cont, TSEvent event ATS_UNUSED, void *edata ATS_UNUSED)
-+{
-+  config_t *config = (config_t *)TSContDataGet(cont);
-+  TSDebug(DEBUG_TAG, "do_time_update() called, updating config->last_update.");
-+
-+
-+  while (!__sync_bool_compare_and_swap(&(config->last_update), config->last_update, now()))
-+    ;
-+
-+  TSContDestroy(cont);
-+  return 0;
-+}
-+
-+static int
-+handle_config_update(TSCont cont, TSEvent event ATS_UNUSED, void *edata ATS_UNUSED)
-+{
-+  config_t *config = (config_t *)TSContDataGet(cont);
-+
-+  TSDebug(DEBUG_TAG, "handle_config_update() called due to management update.");
-+
-+  if (config->schedule_delay > 0) {
-+    TSCont do_update_cont = TSContCreate(do_time_update, NULL);
-+    TSContDataSet(do_update_cont, (void *)config);
-+    TSContSchedule(do_update_cont, config->schedule_delay * 1000, TS_THREAD_POOL_TASK);
-+  } else {
-+    while (!__sync_bool_compare_and_swap(&(config->last_update), config->last_update, now()))
-+      ;
-+  }
-+  return 0;
-+}
-+
- void
- TSPluginInit(int argc, const char *argv[])
- {
-   TSPluginRegistrationInfo info;
--  TSCont pre_remap_cont, post_remap_cont, global_cont;
-+  TSCont pre_remap_cont, post_remap_cont, global_cont, update_cont;
-   config_t *config;
- 
-   info.plugin_name = PLUGIN_NAME;
-@@ -253,14 +330,18 @@ TSPluginInit(int argc, const char *argv[])
-   config->post_remap_host = false;
-   config->persist_type = TS_STAT_NON_PERSISTENT;
-   config->stat_creation_mutex = TSMutexCreate();
-+  config->schedule_delay = 0;
-+  config->last_update = 0;
- 
-   if (argc > 1) {
-     int c;
-     optind = 1;
--    static const struct option longopts[] = {
--      {"post-remap-host", no_argument, NULL, 'P'}, {"persistent", no_argument, NULL, 'p'}, {NULL, 0, NULL, 0}};
-+    static const struct option longopts[] = {{"post-remap-host", no_argument, NULL, 'P'},
-+                                             {"persistent", no_argument, NULL, 'p'},
-+                                             {"delay", required_argument, NULL, 'd'},
-+                                             {NULL, 0, NULL, 0}};
- 
--    while ((c = getopt_long(argc, (char *const *)argv, "Pp", longopts, NULL)) != -1) {
-+    while ((c = getopt_long(argc, (char *const *)argv, "Ppd:", longopts, NULL)) != -1) {
-       switch (c) {
-       case 'P':
-         config->post_remap_host = true;
-@@ -270,6 +351,10 @@ TSPluginInit(int argc, const char *argv[])
-         config->persist_type = TS_STAT_PERSISTENT;
-         TSDebug(DEBUG_TAG, "Using persistent stats");
-         break;
-+      case 'd':
-+        config->schedule_delay = atoi(optarg);
-+        TSDebug(DEBUG_TAG, "Setting scheduling delay to %d", config->schedule_delay);
-+        break;
-       default:
-         break;
-       }
-@@ -292,5 +377,9 @@ TSPluginInit(int argc, const char *argv[])
-   TSContDataSet(global_cont, (void *)config);
-   TSHttpHookAdd(TS_HTTP_TXN_CLOSE_HOOK, global_cont);
- 
-+  update_cont = TSContCreate(handle_config_update, NULL);
-+  TSContDataSet(update_cont, (void *)config);
-+  TSMgmtUpdateRegister(update_cont, PLUGIN_NAME);
-+
-   TSDebug(DEBUG_TAG, "Init complete");
- }
-diff --git a/plugins/experimental/stale_while_revalidate/stale_while_revalidate.c b/plugins/experimental/stale_while_revalidate/stale_while_revalidate.c
-index c3cd9bc..dd45572 100644
---- a/plugins/experimental/stale_while_revalidate/stale_while_revalidate.c
-+++ b/plugins/experimental/stale_while_revalidate/stale_while_revalidate.c
-@@ -268,6 +268,7 @@ consume_resource(TSCont cont, TSEvent event ATS_UNUSED, void *edata ATS_UNUSED)
-   case TS_EVENT_VCONN_WRITE_READY:
-     // We shouldn't get here because we specify the exact size of the buffer.
-     TSDebug(PLUGIN_NAME, "Write Ready");
-+    break;
-   case TS_EVENT_VCONN_WRITE_COMPLETE:
-     TSDebug(PLUGIN_NAME, "Write Complete");
-     // TSDebug(PLUGIN_NAME, "TSVConnShutdown()");
-diff --git a/plugins/experimental/ts_lua/ts_lua_http_config.c b/plugins/experimental/ts_lua/ts_lua_http_config.c
-index f840625..be81bd6 100644
---- a/plugins/experimental/ts_lua/ts_lua_http_config.c
-+++ b/plugins/experimental/ts_lua/ts_lua_http_config.c
-@@ -81,6 +81,13 @@ typedef enum {
-   TS_LUA_CONFIG_HTTP_CACHE_FUZZ_PROBABILITY = TS_CONFIG_HTTP_CACHE_FUZZ_PROBABILITY,
-   TS_LUA_CONFIG_NET_SOCK_PACKET_MARK_OUT = TS_CONFIG_NET_SOCK_PACKET_MARK_OUT,
-   TS_LUA_CONFIG_NET_SOCK_PACKET_TOS_OUT = TS_CONFIG_NET_SOCK_PACKET_TOS_OUT,
-+  TS_LUA_CONFIG_HTTP_PER_PARENT_CONNECT_ATTEMPTS = TS_CONFIG_HTTP_PER_PARENT_CONNECT_ATTEMPTS,
-+  TS_LUA_CONFIG_HTTP_PARENT_TOTAL_CONNECT_ATTEMPTS = TS_CONFIG_HTTP_PARENT_TOTAL_CONNECT_ATTEMPTS,
-+  TS_LUA_CONFIG_HTTP_SIMPLE_RETRY_ENABLED = TS_CONFIG_HTTP_SIMPLE_RETRY_ENABLED,
-+  TS_LUA_CONFIG_HTTP_SIMPLE_RETRY_RESPONSE_CODES = TS_CONFIG_HTTP_SIMPLE_RETRY_RESPONSE_CODES,
-+  TS_LUA_CONFIG_HTTP_DEAD_SERVER_RETRY_ENABLED = TS_CONFIG_HTTP_DEAD_SERVER_RETRY_ENABLED,
-+  TS_LUA_CONFIG_HTTP_DEAD_SERVER_RETRY_RESPONSE_CODES = TS_CONFIG_HTTP_SIMPLE_RETRY_RESPONSE_CODES,
-+  TS_LUA_CONFIG_HTTP_URL_REMAP_REQUIRED = TS_CONFIG_HTTP_URL_REMAP_REQUIRED,
-   TS_LUA_CONFIG_LAST_ENTRY = TS_CONFIG_LAST_ENTRY
- } TSLuaOverridableConfigKey;
- 
-diff --git a/plugins/experimental/url_sig/url_sig.c b/plugins/experimental/url_sig/url_sig.c
-index 672f2c5..2418f21 100644
---- a/plugins/experimental/url_sig/url_sig.c
-+++ b/plugins/experimental/url_sig/url_sig.c
-@@ -32,6 +32,12 @@
- #include <limits.h>
- #include <ctype.h>
- 
-+#ifdef HAVE_PCRE_PCRE_H
-+#include <pcre/pcre.h>
-+#else
-+#include <pcre.h>
-+#endif
-+
- #include <ts/ts.h>
- #include <ts/remap.h>
- 
-@@ -41,13 +47,26 @@ struct config {
-   TSHttpStatus err_status;
-   char *err_url;
-   char keys[MAX_KEY_NUM][MAX_KEY_LEN];
-+  pcre *regex;
-+  pcre_extra *regex_extra;
- };
- 
--void
-+static void
- free_cfg(struct config *cfg)
- {
-   TSError("Cleaning up...");
-   TSfree(cfg->err_url);
-+
-+  if (cfg->regex_extra)
-+#ifndef PCRE_STUDY_JIT_COMPILE
-+    pcre_free(cfg->regex_extra);
-+#else
-+    pcre_free_study(cfg->regex_extra);
-+#endif
-+
-+  if (cfg->regex)
-+    pcre_free(cfg->regex);
-+
-   TSfree(cfg);
- }
- 
-@@ -150,16 +169,30 @@ TSRemapNewInstance(int argc, char *argv[], void **ih, char *errbuf, int errbuf_s
-       value += 3;
-    

<TRUNCATED>