Repository: trafficserver
Updated Branches:
  refs/heads/master 8456a6ea2 -> 0d8bfb404


TS-1893 Add configuration options for server session matching.


Project: http://git-wip-us.apache.org/repos/asf/trafficserver/repo
Commit: http://git-wip-us.apache.org/repos/asf/trafficserver/commit/0d8bfb40
Tree: http://git-wip-us.apache.org/repos/asf/trafficserver/tree/0d8bfb40
Diff: http://git-wip-us.apache.org/repos/asf/trafficserver/diff/0d8bfb40

Branch: refs/heads/master
Commit: 0d8bfb404df781637da317af68487d8b10671152
Parents: 8456a6e
Author: Alan M. Carroll <[email protected]>
Authored: Fri Feb 14 16:50:45 2014 -0600
Committer: Alan M. Carroll <[email protected]>
Committed: Fri Feb 14 16:50:45 2014 -0600

----------------------------------------------------------------------
 CHANGES                                         |   2 +
 doc/arch/hacking/index.en.rst                   |   4 +
 .../configuration/records.config.en.rst         |  44 +++++-
 mgmt/RecordsConfig.cc                           |   4 +
 proxy/InkAPI.cc                                 |  73 ++++++++--
 proxy/InkAPITest.cc                             |  18 ++-
 proxy/api/ts/ts.h.in                            |  25 +++-
 proxy/http/HttpConfig.cc                        | 145 ++++++++++++++++++-
 proxy/http/HttpConfig.h                         |   9 +-
 proxy/http/HttpSM.cc                            |  15 +-
 proxy/http/HttpServerSession.cc                 |   4 +-
 proxy/http/HttpServerSession.h                  |  11 +-
 proxy/http/HttpSessionManager.cc                |  56 ++++---
 proxy/http/HttpSessionManager.h                 |  17 +++
 14 files changed, 365 insertions(+), 62 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/trafficserver/blob/0d8bfb40/CHANGES
----------------------------------------------------------------------
diff --git a/CHANGES b/CHANGES
index a39bc32..90db4ec 100644
--- a/CHANGES
+++ b/CHANGES
@@ -1,6 +1,8 @@
                                                          -*- coding: utf-8 -*-
 Changes with Apache Traffic Server 5.0.0
 
+  *) [TS-1893] Add more options to server session control.
+
   *) [TS-2239] Initial ALPN TLS extension support.
 
   *) [TS-2568] Better template messages.

http://git-wip-us.apache.org/repos/asf/trafficserver/blob/0d8bfb40/doc/arch/hacking/index.en.rst
----------------------------------------------------------------------
diff --git a/doc/arch/hacking/index.en.rst b/doc/arch/hacking/index.en.rst
index b7edc7d..84e997a 100644
--- a/doc/arch/hacking/index.en.rst
+++ b/doc/arch/hacking/index.en.rst
@@ -24,3 +24,7 @@ Introduction
 This is a documentation stub on how to hack Apache Traffic Server. Here we try 
to document things such as how to write
 and run unit or regression tests or how to inspect the state of the core with 
a debugger.
 
+.. toctree::
+   :maxdepth: 1
+
+   config-var-impl.en

http://git-wip-us.apache.org/repos/asf/trafficserver/blob/0d8bfb40/doc/reference/configuration/records.config.en.rst
----------------------------------------------------------------------
diff --git a/doc/reference/configuration/records.config.en.rst 
b/doc/reference/configuration/records.config.en.rst
index be67e33..e23192b 100644
--- a/doc/reference/configuration/records.config.en.rst
+++ b/doc/reference/configuration/records.config.en.rst
@@ -598,9 +598,41 @@ Value Effect
        origin servers.
 
 .. ts:cv:: CONFIG proxy.config.http.share_server_sessions INT 1
+   :deprecated:
 
    Enables (``1``) or disables (``0``) the reuse of server sessions.
 
+.. ts:cv:: CONFIG proxy.config.http.server_session_sharing.match STRING both
+
+   Enable and set the ability to re-use server connections across client 
connections. The valid values are
+
+   none
+      Do not match, do not re-use server sessions.
+
+   ip
+      Re-use server sessions, check only that the IP address and port of the 
origin server matches.
+
+   host
+      Re-use server sessions, check only that the fully qualified domain name 
matches.
+
+   both
+      Re-use server sessions, but only if the IP address and fully qualified 
domain name match.
+
+   It is strongly recommended to use either *none* or *both* for this value 
unless you have a specific need to use *ip*
+   or *host*. The most common reason is virtual hosts that share an IP address 
in which case performance can be enhanced
+   if those sessions can be re-used. However, not all web servers support 
requests for different virtual hosts on the
+   same connection so use with caution.
+
+.. ts:cv:: CONFIG proxy.config.http.server_session_sharing.pool STRING thread
+
+   Control the scope of server session re-use if it is enabled by 
:ts:cv:`proxy.config.server_session_sharing.match`. The valid values are
+
+   global
+      Re-use sessions from a global pool of all server sessions.
+
+   thread
+      Re-use sessions from a per-thread pool.
+
 .. ts:cv:: CONFIG proxy.config.http.record_heartbeat INT 0
    :reloadable:
 
@@ -1196,15 +1228,15 @@ Cache Control
 
 .. ts:cv:: CONFIG proxy.config.cache.limits.http.max_alts INT 5
 
-   The maximum number of alternates that are allowed for any given URL. 
+   The maximum number of alternates that are allowed for any given URL.
    Disable by setting to 0. Note that this setting will not strictly enforce
-   this if the variable ``proxy.config.cache.vary_on_user_agent`` is set 
+   this if the variable ``proxy.config.cache.vary_on_user_agent`` is set
    to 1 (by default it is 0).
 
 .. ts:cv:: CONFIG proxy.config.cache.target_fragment_size INT 1048576
 
-   Sets the target size of a contiguous fragment of a file in the disk cache. 
Accepts values that are powers of 2, e.g. 65536, 131072, 
-   262144, 524288, 1048576, 2097152, etc. When setting this, consider that 
larger numbers could waste memory on slow connections, 
+   Sets the target size of a contiguous fragment of a file in the disk cache. 
Accepts values that are powers of 2, e.g. 65536, 131072,
+   262144, 524288, 1048576, 2097152, etc. When setting this, consider that 
larger numbers could waste memory on slow connections,
    but smaller numbers could increase (waste) seeks.
 
 RAM Cache
@@ -1406,8 +1438,8 @@ hostname to ``host_x.y.com``.
 
 .. ts:cv:: CONFIG proxy.config.dns.validate_query_name INT 0
 
-   When enabled (1) provides additional resilience against DNS forgery (for 
instance 
-   in DNS Injection attacks), particularly in forward or transparent proxies, 
but 
+   When enabled (1) provides additional resilience against DNS forgery (for 
instance
+   in DNS Injection attacks), particularly in forward or transparent proxies, 
but
    requires that the resolver populates the queries section of the response 
properly.
 
 HostDB

http://git-wip-us.apache.org/repos/asf/trafficserver/blob/0d8bfb40/mgmt/RecordsConfig.cc
----------------------------------------------------------------------
diff --git a/mgmt/RecordsConfig.cc b/mgmt/RecordsConfig.cc
index 41b876c..1b04a1f 100644
--- a/mgmt/RecordsConfig.cc
+++ b/mgmt/RecordsConfig.cc
@@ -428,6 +428,10 @@ RecordElement RecordsConfig[] = {
   ,
   {RECT_CONFIG, "proxy.config.http.share_server_sessions", RECD_INT, "2", 
RECU_RESTART_TS, RR_NULL, RECC_NULL, NULL, RECA_NULL}
   ,
+  {RECT_CONFIG, "proxy.config.http.server_session_sharing.match", RECD_STRING, 
"both", RECU_RESTART_TS, RR_NULL, RECC_NULL, NULL, RECA_NULL}
+  ,
+  {RECT_CONFIG, "proxy.config.http.server_session_sharing.pool", RECD_STRING, 
"thread", RECU_RESTART_TS, RR_NULL, RECC_NULL, NULL, RECA_NULL}
+  ,
   {RECT_CONFIG, "proxy.config.http.record_heartbeat", RECD_INT, "0", 
RECU_DYNAMIC, RR_NULL, RECC_NULL, NULL, RECA_NULL}
   ,
   {RECT_CONFIG, "proxy.config.http.record_tcp_mem_hit", RECD_INT, "0", 
RECU_DYNAMIC, RR_NULL, RECC_NULL, NULL, RECA_NULL}

http://git-wip-us.apache.org/repos/asf/trafficserver/blob/0d8bfb40/proxy/InkAPI.cc
----------------------------------------------------------------------
diff --git a/proxy/InkAPI.cc b/proxy/InkAPI.cc
index 7067819..bc0a9ec 100644
--- a/proxy/InkAPI.cc
+++ b/proxy/InkAPI.cc
@@ -2976,7 +2976,7 @@ TSMimeHdrFieldNext(TSMBuffer bufp, TSMLoc hdr, TSMLoc 
field)
       return TS_NULL_MLOC;
     if (f->is_live()) {
       MIMEFieldSDKHandle *h = sdk_alloc_field_handle(bufp, handle->mh);
-      
+
       h->field_ptr = f;
       return reinterpret_cast<TSMLoc>(h);
     }
@@ -3913,7 +3913,7 @@ TSCacheKeyDigestSet(TSCacheKey key, const char *input, 
int length)
   sdk_assert(sdk_sanity_check_cachekey(key) == TS_SUCCESS);
   sdk_assert(sdk_sanity_check_iocore_structure((void*) input) == TS_SUCCESS);
   sdk_assert(length > 0);
-  
+
   if (((CacheInfo *) key)->magic != CACHE_INFO_MAGIC_ALIVE)
     return TS_ERROR;
 
@@ -4617,7 +4617,7 @@ TSHttpTxnServerReqGet(TSHttpTxn txnp, TSMBuffer *bufp, 
TSMLoc *obj)
     *obj = reinterpret_cast<TSMLoc>(hptr->m_http);
     sdk_sanity_check_mbuffer(*bufp);
     return TS_SUCCESS;
-  } 
+  }
 
   return TS_ERROR;
 }
@@ -5179,7 +5179,7 @@ TSHttpTxnTransformRespGet(TSHttpTxn txnp, TSMBuffer 
*bufp, TSMLoc *obj)
     *(reinterpret_cast<HTTPHdr**>(bufp)) = hptr;
     *obj = reinterpret_cast<TSMLoc>(hptr->m_http);
     return sdk_sanity_check_mbuffer(*bufp);
-  } 
+  }
 
   return TS_ERROR;
 }
@@ -5200,7 +5200,7 @@ sockaddr const*
 TSHttpTxnClientAddrGet(TSHttpTxn txnp)
 {
   sdk_assert(sdk_sanity_check_txn(txnp) == TS_SUCCESS);
- 
+
   TSHttpSsn ssnp = TSHttpTxnSsnGet(txnp);
   return TSHttpSsnClientAddrGet(ssnp);
 }
@@ -5221,7 +5221,7 @@ sockaddr const*
 TSHttpTxnIncomingAddrGet(TSHttpTxn txnp)
 {
   sdk_assert(sdk_sanity_check_txn(txnp) == TS_SUCCESS);
- 
+
   TSHttpSsn ssnp = TSHttpTxnSsnGet(txnp);
   return TSHttpSsnIncomingAddrGet(ssnp);
 }
@@ -7265,7 +7265,7 @@ TSReturnCode
 TSAIOWrite(int fd, off_t offset, char* buf, const size_t bufSize, TSCont contp)
 {
   sdk_assert(sdk_sanity_check_iocore_structure (contp) == TS_SUCCESS);
-  
+
   Continuation* pCont = (Continuation*) contp;
   AIOCallback* pAIO = new_AIOCallback();
 
@@ -7305,7 +7305,7 @@ TSRecordDump(TSRecordType rec_type, TSRecordDumpCb 
callback, void *edata)
   RecDumpRecords((RecT)rec_type, (RecDumpEntryCb)callback, edata);
 }
 
-/* ability to skip the remap phase of the State Machine 
+/* ability to skip the remap phase of the State Machine
    this only really makes sense in TS_HTTP_READ_REQUEST_HDR_HOOK
 */
 void
@@ -7352,7 +7352,14 @@ _conf_to_memberp(TSOverridableConfigKey conf, HttpSM* 
sm, OverridableDataType *t
     ret = &sm->t_state.txn_conf->keep_alive_post_out;
     break;
   case TS_CONFIG_HTTP_SHARE_SERVER_SESSIONS:
-    ret = &sm->t_state.txn_conf->share_server_sessions;
+    ink_assert("Deprecated config key value - 
TS_CONFIG_HTTP_SHARE_SERVER_SESSIONS");
+//    ret = &sm->t_state.txn_conf->share_server_sessions;
+    break;
+  case TS_CONFIG_HTTP_SERVER_SESSION_SHARING_POOL:
+    ret = &sm->t_state.txn_conf->server_session_sharing_pool;
+    break;
+  case TS_CONFIG_HTTP_SERVER_SESSION_SHARING_MATCH:
+    ret = &sm->t_state.txn_conf->server_session_sharing_match;
     break;
   case TS_CONFIG_NET_SOCK_RECV_BUFFER_SIZE_OUT:
     typ = OVERRIDABLE_TYPE_INT;
@@ -7639,6 +7646,26 @@ TSHttpTxnConfigIntSet(TSHttpTxn txnp, 
TSOverridableConfigKey conf, TSMgmtInt val
 
   s->t_state.setup_per_txn_configs();
 
+  // 4.1.X backwards compatibility - remove for 5.0
+  if (TS_CONFIG_HTTP_SHARE_SERVER_SESSIONS == conf) {
+    switch (value) {
+    case 0: s->t_state.txn_conf->server_session_sharing_match = 
TS_SERVER_SESSION_SHARING_MATCH_NONE; break;
+    case 1:
+      s->t_state.txn_conf->server_session_sharing_match = 
TS_SERVER_SESSION_SHARING_MATCH_BOTH;
+      s->t_state.txn_conf->server_session_sharing_pool = 
TS_SERVER_SESSION_SHARING_POOL_GLOBAL;
+      break;
+    case 2:
+      s->t_state.txn_conf->server_session_sharing_match = 
TS_SERVER_SESSION_SHARING_MATCH_BOTH;
+      s->t_state.txn_conf->server_session_sharing_pool = 
TS_SERVER_SESSION_SHARING_POOL_THREAD;
+      break;
+    default:
+      return TS_ERROR;
+      break; // make the compiler happy
+    }
+    return TS_SUCCESS;
+  }
+  // end 4.1.X BC
+
   void *dest = _conf_to_memberp(conf, s, &type);
 
   if (!dest)
@@ -7664,8 +7691,26 @@ TSHttpTxnConfigIntGet(TSHttpTxn txnp, 
TSOverridableConfigKey conf, TSMgmtInt *va
   sdk_assert(sdk_sanity_check_txn(txnp) == TS_SUCCESS);
   sdk_assert(sdk_sanity_check_null_ptr((void*)value) == TS_SUCCESS);
 
+  HttpSM *s = reinterpret_cast<HttpSM*>(txnp);
   OverridableDataType type;
-  void* src = _conf_to_memberp(conf, (HttpSM*)txnp, &type);
+
+  // 4.1.X backwards compatibility - remove for 5.0
+  if (TS_CONFIG_HTTP_SHARE_SERVER_SESSIONS == conf) {
+    if (s->t_state.txn_conf->server_session_sharing_match == 
TS_SERVER_SESSION_SHARING_MATCH_NONE)
+      *value = 0;
+    else if (s->t_state.txn_conf->server_session_sharing_match == 
TS_SERVER_SESSION_SHARING_MATCH_BOTH &&
+             s->t_state.txn_conf->server_session_sharing_pool == 
TS_SERVER_SESSION_SHARING_POOL_GLOBAL)
+      *value = 1;
+    else if (s->t_state.txn_conf->server_session_sharing_match == 
TS_SERVER_SESSION_SHARING_MATCH_BOTH &&
+             s->t_state.txn_conf->server_session_sharing_pool == 
TS_SERVER_SESSION_SHARING_POOL_THREAD)
+      *value = 2;
+    else
+      return TS_ERROR;
+    return TS_SUCCESS;
+  }
+  // end 4.1.X BC
+
+  void* src = _conf_to_memberp(conf, s, &type);
 
   if (!src)
     return TS_ERROR;
@@ -8040,6 +8085,10 @@ TSHttpTxnConfigFind(const char* name, int length, 
TSOverridableConfigKey *conf,
       else if (!strncmp(name, "proxy.config.http.cache.max_open_read_retries", 
length))
         cnf = TS_CONFIG_HTTP_CACHE_MAX_OPEN_READ_RETRIES;
       break;
+    case 'l':
+      if (0 == strncmp(name, "proxy.config.http.server_session_sharing.pool", 
length))
+        cnf = TS_CONFIG_HTTP_SERVER_SESSION_SHARING_POOL;
+      break;
     }
     break;
 
@@ -8069,6 +8118,10 @@ TSHttpTxnConfigFind(const char* name, int length, 
TSOverridableConfigKey *conf,
       if (!strncmp(name, "proxy.config.http.forward.proxy_auth_to_parent", 
length))
         cnf = TS_CONFIG_HTTP_FORWARD_PROXY_AUTH_TO_PARENT;
       break;
+    case 'h':
+      if (0 == strncmp(name, "proxy.config.http.server_session_sharing.match", 
length))
+        cnf = TS_CONFIG_HTTP_SERVER_SESSION_SHARING_MATCH;
+      break;
     }
     break;
 

http://git-wip-us.apache.org/repos/asf/trafficserver/blob/0d8bfb40/proxy/InkAPITest.cc
----------------------------------------------------------------------
diff --git a/proxy/InkAPITest.cc b/proxy/InkAPITest.cc
index 727cc26..f558eb0 100644
--- a/proxy/InkAPITest.cc
+++ b/proxy/InkAPITest.cc
@@ -6096,8 +6096,7 @@ cache_hook_handler(TSCont contp, TSEvent event, void 
*edata)
     TSSkipRemappingSet(txnp,1);
     TSHttpTxnReenable(txnp, TS_EVENT_HTTP_CONTINUE);
     break;
-  
-  
+
   case TS_EVENT_HTTP_CACHE_LOOKUP_COMPLETE:
     {
       int lookup_status;
@@ -6259,7 +6258,7 @@ EXCLUSIVE_REGRESSION_TEST(SDK_API_HttpTxnCache) 
(RegressionTest * test, int /* a
   socktest->first_time = true;
   socktest->magic = MAGIC_ALIVE;
   TSContDataSet(cont, socktest);
-  
+
   TSHttpHookAdd(TS_HTTP_READ_REQUEST_HDR_HOOK, cont);
   /* Register to HTTP hooks that are called in case of a cache MISS */
   TSHttpHookAdd(TS_HTTP_READ_CACHE_HDR_HOOK, cont);
@@ -6752,7 +6751,7 @@ transform_hook_handler(TSCont contp, TSEvent event, void 
*edata)
       } else {
         SDK_RPRINT(data->test, "TSHttpTxnTransformedResponseCache", 
"TestCase1", TC_FAIL, "Value's Mismatch");
       }
-      
+
       /* Note: response is available using test->browser->response pointer */
       *(data->pstatus) = REGRESSION_TEST_PASSED;
       if (data->browser1->status != REQUEST_SUCCESS) {
@@ -6835,9 +6834,9 @@ EXCLUSIVE_REGRESSION_TEST(SDK_API_HttpTxnTransform) 
(RegressionTest * test, int
 
   /* Prepare the buffer to be appended to responses */
   load(TRANSFORM_APPEND_STRING);
-  
+
   TSHttpHookAdd(TS_HTTP_READ_REQUEST_HDR_HOOK, cont); //so we can skip 
remapping
-  
+
   /* Register to HTTP hooks that are called in case of a cache MISS */
   TSHttpHookAdd(TS_HTTP_READ_RESPONSE_HDR_HOOK, cont);
 
@@ -7345,6 +7344,8 @@ const char *SDK_Overridable_Configs[TS_CONFIG_LAST_ENTRY] 
= {
   "proxy.config.http.keep_alive_enabled_out",
   "proxy.config.http.keep_alive_post_out",
   "proxy.config.http.share_server_sessions",
+  "proxy.config.http.server_session_sharing.pool",
+  "proxy.config.http.server_session_sharing.match",
   "proxy.config.net.sock_recv_buffer_size_out",
   "proxy.config.net.sock_send_buffer_size_out",
   "proxy.config.net.sock_option_flag_out",
@@ -7433,7 +7434,7 @@ REGRESSION_TEST(SDK_API_OVERRIDABLE_CONFIGS) 
(RegressionTest * test, int /* atyp
   const char *sval_read;
   const char *test_string = "The Apache Traffic Server";
   int len;
-  
+
 
   s->init();
 
@@ -7457,6 +7458,9 @@ REGRESSION_TEST(SDK_API_OVERRIDABLE_CONFIGS) 
(RegressionTest * test, int /* atyp
     switch (type) {
     case TS_RECORDDATATYPE_INT:
       ival_rand = generator.random() % 126; // to fit in a signed byte
+      // 4.1 backwards compatibility - remove for 5.0
+      if (TS_CONFIG_HTTP_SHARE_SERVER_SESSIONS == key) ival_rand %= 2;
+      // end BC
       TSHttpTxnConfigIntSet(txnp, key, ival_rand);
       TSHttpTxnConfigIntGet(txnp, key, &ival_read);
       if (ival_rand != ival_read) {

http://git-wip-us.apache.org/repos/asf/trafficserver/blob/0d8bfb40/proxy/api/ts/ts.h.in
----------------------------------------------------------------------
diff --git a/proxy/api/ts/ts.h.in b/proxy/api/ts/ts.h.in
index b37a504..3d0c987 100644
--- a/proxy/api/ts/ts.h.in
+++ b/proxy/api/ts/ts.h.in
@@ -520,6 +520,27 @@ extern "C"
     AFTER_BODY
   } TSFetchWakeUpOptions;
 
+#ifndef _HTTP_PROXY_API_ENUMS_H_
+#define _HTTP_PROXY_API_ENUMS_H_
+  /// Server session sharing values - match
+  /// Must be identical to definition in HttpProxyAPIEnums.h
+  typedef enum
+  {
+    TS_SERVER_SESSION_SHARING_MATCH_NONE,
+    TS_SERVER_SESSION_SHARING_MATCH_BOTH,
+    TS_SERVER_SESSION_SHARING_MATCH_IP,
+    TS_SERVER_SESSION_SHARING_MATCH_HOST
+  } TSServerSessionSharingMatchType;
+
+  /// Server session sharing values - pool
+  /// Must be identical to definition in HttpProxyAPIEnums.h
+  typedef enum
+  {
+    TS_SERVER_SESSION_SHARING_POOL_GLOBAL,
+    TS_SERVER_SESSION_SHARING_POOL_THREAD
+  } TSServerSessionSharingPoolType;
+#endif
+
   /* librecords types */
 
   /* The values of this enum must match enum RecT in I_RecDefs.h */
@@ -612,7 +633,9 @@ extern "C"
     TS_CONFIG_HTTP_KEEP_ALIVE_ENABLED_IN,
     TS_CONFIG_HTTP_KEEP_ALIVE_ENABLED_OUT,
     TS_CONFIG_HTTP_KEEP_ALIVE_POST_OUT,
-    TS_CONFIG_HTTP_SHARE_SERVER_SESSIONS,
+    TS_CONFIG_HTTP_SHARE_SERVER_SESSIONS, // DEPRECATED
+    TS_CONFIG_HTTP_SERVER_SESSION_SHARING_POOL,
+    TS_CONFIG_HTTP_SERVER_SESSION_SHARING_MATCH,
     TS_CONFIG_NET_SOCK_RECV_BUFFER_SIZE_OUT,
     TS_CONFIG_NET_SOCK_SEND_BUFFER_SIZE_OUT,
     TS_CONFIG_NET_SOCK_OPTION_FLAG_OUT,

http://git-wip-us.apache.org/repos/asf/trafficserver/blob/0d8bfb40/proxy/http/HttpConfig.cc
----------------------------------------------------------------------
diff --git a/proxy/http/HttpConfig.cc b/proxy/http/HttpConfig.cc
index 419de41..5ecbfca 100644
--- a/proxy/http/HttpConfig.cc
+++ b/proxy/http/HttpConfig.cc
@@ -65,7 +65,6 @@ do { \
 } while (0);
 
 
-
 class HttpConfigCont:public Continuation
 {
 public:
@@ -73,6 +72,62 @@ public:
   int handle_event(int event, void *edata);
 };
 
+/// Data item for enumerated type config value.
+template <typename T> struct ConfigEnumPair
+{
+  T _value;
+  char const* _key;
+};
+
+/// Convert a string to an enumeration value.
+/// @a n is the number of entries in the list.
+/// @return @c true if the string is found, @c false if not found.
+/// If found @a value is set to the corresponding value in @a list.
+template <typename T> static bool
+http_config_enum_search(char const* key, ConfigEnumPair<T>* list, size_t n, 
MgmtByte value)
+{
+  // We don't expect any of these lists to be more than 10 long, so a linear 
search is the best choice.
+  for ( size_t i = 0 ; i < n ; ++i ) {
+    if (0 == strcasecmp(list[i]._key, key)) {
+      value = list[i]._value;
+      return true;
+    }
+  }
+  return false;
+}
+
+/// Read a string from the configuration and convert it to an enumeration 
value.
+/// @a n is the number of entries in the list.
+/// @return @c true if the string is found, @c false if not found.
+/// If found @a value is set to the corresponding value in @a list.
+template <typename T> static bool
+http_config_enum_read(char const* name, ConfigEnumPair<T>* list, size_t n, 
MgmtByte value)
+{
+  char key[512]; // it's just one key - painful UI if keys are longer than this
+  if (REC_ERR_OKAY == RecGetRecordString(name, key, sizeof(key))) {
+    return http_config_enum_search(key, list, n, value);
+  }
+  return false;
+}
+
+/// Session sharing match types.
+static
+ConfigEnumPair<TSServerSessionSharingMatchType> SessionSharingMatchStrings[] =
+{
+  { TS_SERVER_SESSION_SHARING_MATCH_NONE, "none" },
+  { TS_SERVER_SESSION_SHARING_MATCH_IP, "ip" },
+  { TS_SERVER_SESSION_SHARING_MATCH_HOST, "host" },
+  { TS_SERVER_SESSION_SHARING_MATCH_BOTH, "both" }
+};
+  
+static
+ConfigEnumPair<TSServerSessionSharingPoolType> SessionSharingPoolStrings[] =
+{
+  { TS_SERVER_SESSION_SHARING_POOL_GLOBAL, "global" },
+  { TS_SERVER_SESSION_SHARING_POOL_THREAD, "thread" }
+};
+
+# define ARRAY_SIZE(x) (sizeof(x)/(sizeof((x)[0])))
 
 ////////////////////////////////////////////////////////////////
 //
@@ -115,6 +170,73 @@ http_config_cb(const char * /* name ATS_UNUSED */, 
RecDataT /* data_type ATS_UNU
   return 0;
 }
 
+// Convert from the old share_server_session value to the new config vars.
+static void
+http_config_share_server_sessions_bc(HttpConfigParams* c, MgmtByte v)
+{
+  switch (v) {
+  case 0:
+    c->oride.server_session_sharing_match = 
TS_SERVER_SESSION_SHARING_MATCH_NONE;
+    c->oride.server_session_sharing_pool = 
TS_SERVER_SESSION_SHARING_POOL_GLOBAL;
+    break;
+  case 1:
+    c->oride.server_session_sharing_match = 
TS_SERVER_SESSION_SHARING_MATCH_BOTH;
+    c->oride.server_session_sharing_pool = 
TS_SERVER_SESSION_SHARING_POOL_GLOBAL;
+    break;
+  case 2:
+    c->oride.server_session_sharing_match = 
TS_SERVER_SESSION_SHARING_MATCH_BOTH;
+    c->oride.server_session_sharing_pool = 
TS_SERVER_SESSION_SHARING_POOL_THREAD;
+    break;
+  }
+}
+
+static void
+http_config_share_server_sessions_read_bc(HttpConfigParams* c)
+{
+  MgmtByte v;
+  if (REC_ERR_OKAY == 
RecGetRecordByte("proxy.config.http.share_server_sessions", &v)) 
+    http_config_share_server_sessions_bc(c, v);
+}
+
+// [amc] Not sure which is uglier, this switch or having a micro-function for 
each var.
+// Oh, how I long for when we can use C++eleventy lambdas without compiler 
problems!
+// I think for 5.0 when the BC stuff is yanked, we should probably revert this 
to independent callbacks.
+static int
+http_server_session_sharing_cb(char const* name, RecDataT dtype, RecData data, 
void* cookie)
+{
+  bool valid_p = true;
+  HttpConfigParams* c = static_cast<HttpConfigParams*>(cookie);
+
+  if (0 == strcasecmp("proxy.config.http.server_session_sharing.pool", name)) {
+    MgmtByte& match = c->oride.server_session_sharing_match;
+    if (RECD_INT == dtype) {
+      match = static_cast<TSServerSessionSharingMatchType>(data.rec_int);
+    } else if (RECD_STRING == dtype && 
http_config_enum_search(data.rec_string, SessionSharingMatchStrings, 
ARRAY_SIZE(SessionSharingMatchStrings), match)) {
+      // empty
+    } else {
+      valid_p = false;
+    }
+  } else if (0 == strcasecmp("proxy.config.http.server_session_sharing.match", 
name)) {
+    MgmtByte& match = c->oride.server_session_sharing_pool;
+    if (RECD_INT == dtype) {
+      match = static_cast<TSServerSessionSharingPoolType>(data.rec_int);
+    } else if (RECD_STRING == dtype && 
http_config_enum_search(data.rec_string, SessionSharingPoolStrings, 
ARRAY_SIZE(SessionSharingPoolStrings), match)) {
+      // empty
+    } else {
+      valid_p = false;
+    }
+  } else if (0 == strcasecmp("proxy.config.http.share_server_sessions", name) 
&& RECD_INT == dtype) {
+    http_config_share_server_sessions_bc(c, data.rec_int);
+  } else {
+    valid_p = false;
+  }
+
+  // Signal an update if valid value arrived.
+  if (valid_p) 
+    http_config_cb(name, dtype, data, cookie);
+
+ return REC_ERR_OKAY;
+}
 
 void
 register_configs()
@@ -1185,7 +1307,19 @@ HttpConfig::startup()
   HttpEstablishStaticConfigByte(c.oride.flow_control_enabled, 
"proxy.config.http.flow_control.enabled");
   HttpEstablishStaticConfigLongLong(c.oride.flow_high_water_mark, 
"proxy.config.http.flow_control.high_water");
   HttpEstablishStaticConfigLongLong(c.oride.flow_low_water_mark, 
"proxy.config.http.flow_control.low_water");
-  HttpEstablishStaticConfigByte(c.oride.share_server_sessions, 
"proxy.config.http.share_server_sessions");
+//HttpEstablishStaticConfigByte(c.oride.share_server_sessions, 
"proxy.config.http.share_server_sessions");
+
+  // 4.2 Backwards compatibility
+  RecRegisterConfigUpdateCb("proxy.config.http.share_server_sessions", 
&http_server_session_sharing_cb, &c);
+  http_config_share_server_sessions_read_bc(&c);
+  // end 4.2 BC
+
+  // [amc] This is a bit of a mess, need to figure out to make this cleaner.
+  RecRegisterConfigUpdateCb("proxy.config.http.server_session_sharing.pool", 
&http_server_session_sharing_cb, &c);
+  http_config_enum_read("proxy.config.http.server_session_sharing.pool", 
SessionSharingPoolStrings, ARRAY_SIZE(SessionSharingPoolStrings), 
c.oride.server_session_sharing_pool);
+  RecRegisterConfigUpdateCb("proxy.config.http.server_session_sharing.match", 
&http_server_session_sharing_cb, &c);
+  http_config_enum_read("proxy.config.http.server_session_sharing.match", 
SessionSharingMatchStrings, ARRAY_SIZE(SessionSharingMatchStrings), 
c.oride.server_session_sharing_match);
+
   HttpEstablishStaticConfigByte(c.oride.keep_alive_post_out, 
"proxy.config.http.keep_alive_post_out");
 
   HttpEstablishStaticConfigLongLong(c.oride.keep_alive_no_activity_timeout_in,
@@ -1439,8 +1573,9 @@ HttpConfig::reconfigure()
     params->oride.flow_high_water_mark = params->oride.flow_low_water_mark = 0;
   }
 
-  params->oride.share_server_sessions = m_master.oride.share_server_sessions;
-  params->oride.keep_alive_post_out = 
INT_TO_BOOL(m_master.oride.keep_alive_post_out);
+//  params->oride.share_server_sessions = m_master.oride.share_server_sessions;
+  params->oride.server_session_sharing_pool = 
m_master.oride.server_session_sharing_pool;
+  params->oride.server_session_sharing_match = 
m_master.oride.server_session_sharing_match;
 
   params->oride.keep_alive_no_activity_timeout_in = 
m_master.oride.keep_alive_no_activity_timeout_in;
   params->oride.keep_alive_no_activity_timeout_out = 
m_master.oride.keep_alive_no_activity_timeout_out;
@@ -1545,7 +1680,7 @@ HttpConfig::reconfigure()
 
   params->oride.request_hdr_max_size = m_master.oride.request_hdr_max_size;
   params->oride.response_hdr_max_size = m_master.oride.response_hdr_max_size;
-  
+
 params->push_method_enabled = INT_TO_BOOL(m_master.push_method_enabled);
 
   params->reverse_proxy_enabled = INT_TO_BOOL(m_master.reverse_proxy_enabled);

http://git-wip-us.apache.org/repos/asf/trafficserver/blob/0d8bfb40/proxy/http/HttpConfig.h
----------------------------------------------------------------------
diff --git a/proxy/http/HttpConfig.h b/proxy/http/HttpConfig.h
index 54cf273..064f4c6 100644
--- a/proxy/http/HttpConfig.h
+++ b/proxy/http/HttpConfig.h
@@ -48,6 +48,7 @@
 #endif
 
 #include "libts.h"
+#include "HttpProxyAPIEnums.h"
 #include "ProxyConfig.h"
 
 #include "P_RecProcess.h"
@@ -404,7 +405,9 @@ struct OverridableHttpConfigParams {
     : maintain_pristine_host_hdr(1), chunking_enabled(1),
       negative_caching_enabled(0), negative_revalidating_enabled(0), 
cache_when_to_revalidate(0),
       keep_alive_enabled_in(1), keep_alive_enabled_out(1), 
keep_alive_post_out(0),
-      share_server_sessions(2), fwd_proxy_auth_to_parent(0), 
insert_age_in_response(1),
+      server_session_sharing_match(TS_SERVER_SESSION_SHARING_MATCH_BOTH),
+      server_session_sharing_pool(TS_SERVER_SESSION_SHARING_POOL_THREAD),
+      fwd_proxy_auth_to_parent(0), insert_age_in_response(1),
       anonymize_remove_from(0), anonymize_remove_referer(0), 
anonymize_remove_user_agent(0),
       anonymize_remove_cookie(0), anonymize_remove_client_ip(0), 
anonymize_insert_client_ip(1),
       proxy_response_server_enabled(1), proxy_response_hsts_max_age(-1), 
proxy_response_hsts_include_subdomains(0),
@@ -457,7 +460,9 @@ struct OverridableHttpConfigParams {
   MgmtByte keep_alive_enabled_out;
   MgmtByte keep_alive_post_out;  // share server sessions for post
 
-  MgmtByte share_server_sessions;
+  MgmtByte server_session_sharing_match;
+  MgmtByte server_session_sharing_pool;
+  //  MgmtByte share_server_sessions;
   MgmtByte fwd_proxy_auth_to_parent;
 
   MgmtByte insert_age_in_response;

http://git-wip-us.apache.org/repos/asf/trafficserver/blob/0d8bfb40/proxy/http/HttpSM.cc
----------------------------------------------------------------------
diff --git a/proxy/http/HttpSM.cc b/proxy/http/HttpSM.cc
index d888bf6..04ad91b 100644
--- a/proxy/http/HttpSM.cc
+++ b/proxy/http/HttpSM.cc
@@ -1655,10 +1655,12 @@ HttpSM::state_http_server_open(int event, void *data)
 
   switch (event) {
   case NET_EVENT_OPEN:
-    session = (2 == t_state.txn_conf->share_server_sessions) ? 
+    session = (TS_SERVER_SESSION_SHARING_POOL_THREAD == 
t_state.txn_conf->server_session_sharing_pool) ? 
       THREAD_ALLOC_INIT(httpServerSessionAllocator, mutex->thread_holding) :
       httpServerSessionAllocator.alloc();
-    session->share_session = t_state.txn_conf->share_server_sessions;
+    session->sharing_pool = 
static_cast<TSServerSessionSharingPoolType>(t_state.txn_conf->server_session_sharing_pool);
+    session->sharing_match = 
static_cast<TSServerSessionSharingMatchType>(t_state.txn_conf->server_session_sharing_match);
+//    session->share_session = t_state.txn_conf->share_server_sessions;
 
     // If origin_max_connections or origin_min_keep_alive_connections is
     // set then we are metering the max and or min number
@@ -4517,7 +4519,7 @@ HttpSM::do_http_server_open(bool raw)
   // to do this but as far I can tell the code that prevented keep-alive if
   // there is a request body has been removed.
 
-  if (raw == false && t_state.txn_conf->share_server_sessions &&
+  if (raw == false && TS_SERVER_SESSION_SHARING_MATCH_NONE != 
t_state.txn_conf->server_session_sharing_match &&
       (t_state.txn_conf->keep_alive_post_out == 1 || 
t_state.hdr_info.request_content_length == 0) &&
        !is_private() && ua_session != NULL) {
     HSMresult_t shared_result;
@@ -4547,10 +4549,15 @@ HttpSM::do_http_server_open(bool raw)
   // This bug was due to when share_server_sessions is set to 0
   // and we have keep-alive, we are trying to open a new server session
   // when we already have an attached server session.
-  else if ((!t_state.txn_conf->share_server_sessions || is_private()) && 
(ua_session != NULL)) {
+  else if ((TS_SERVER_SESSION_SHARING_MATCH_NONE == 
t_state.txn_conf->server_session_sharing_match || is_private()) &&
+           (ua_session != NULL)) {
     HttpServerSession *existing_ss = ua_session->get_server_session();
 
     if (existing_ss) {
+      // [amc] Not sure if this is the best option, but we don't get here 
unless session sharing is disabled
+      // so there's point in further checking on the match or pool values. But 
why check anything? The
+      // client has already exchanged a request with this specific origin 
server and has sent another one
+      // shouldn't we just automatically keep the association?
       if (ats_ip_addr_eq(&existing_ss->server_ip.sa, 
&t_state.current.server->addr.sa) &&
           ats_ip_port_cast(&existing_ss->server_ip) == 
ats_ip_port_cast(&t_state.current.server->addr)) {
         ua_session->attach_server_session(NULL);

http://git-wip-us.apache.org/repos/asf/trafficserver/blob/0d8bfb40/proxy/http/HttpServerSession.cc
----------------------------------------------------------------------
diff --git a/proxy/http/HttpServerSession.cc b/proxy/http/HttpServerSession.cc
index dd3de61..0609854 100644
--- a/proxy/http/HttpServerSession.cc
+++ b/proxy/http/HttpServerSession.cc
@@ -51,7 +51,7 @@ HttpServerSession::destroy()
   }
 
   mutex.clear();
-  if (2 == share_session)
+  if (TS_SERVER_SESSION_SHARING_POOL_THREAD == sharing_pool)
     THREAD_FREE(this, httpServerSessionAllocator, this_thread());
   else
     httpServerSessionAllocator.free(this);
@@ -165,7 +165,7 @@ HttpServerSession::release()
   state = HSS_KA_SHARED;
 
   // Private sessions are never released back to the shared pool
-  if (private_session || share_session == 0) {
+  if (private_session || TS_SERVER_SESSION_SHARING_MATCH_NONE == 
sharing_match) {
     this->do_io_close();
     return;
   }

http://git-wip-us.apache.org/repos/asf/trafficserver/blob/0d8bfb40/proxy/http/HttpServerSession.h
----------------------------------------------------------------------
diff --git a/proxy/http/HttpServerSession.h b/proxy/http/HttpServerSession.h
index e5e3059..e349841 100644
--- a/proxy/http/HttpServerSession.h
+++ b/proxy/http/HttpServerSession.h
@@ -47,6 +47,7 @@
 #include "P_Net.h"
 
 #include "HttpConnectionCount.h"
+#include "HttpProxyAPIEnums.h"
 
 class HttpSM;
 class MIOBuffer;
@@ -72,7 +73,9 @@ public:
       hostname_hash(),
       host_hash_computed(false), con_id(0), transact_count(0),
       state(HSS_INIT), to_parent_proxy(false), server_trans_stat(0),
-      private_session(false), share_session(0),
+      private_session(false),
+      sharing_match(TS_SERVER_SESSION_SHARING_MATCH_BOTH),
+      sharing_pool(TS_SERVER_SESSION_SHARING_POOL_GLOBAL),
       enable_origin_connection_limiting(false),
       connection_count(NULL), read_buffer(NULL),
       server_vc(NULL), magic(HTTP_SS_MAGIC_DEAD), buf_reader(NULL)
@@ -137,8 +140,10 @@ public:
   //  are sent over them
   bool private_session;
 
-  // Copy of the owning SM's share_server_session setting
-  int share_session;
+  // Copy of the owning SM's server session sharing settings
+  TSServerSessionSharingMatchType sharing_match;
+  TSServerSessionSharingPoolType sharing_pool;
+  //  int share_session;
 
   LINK(HttpServerSession, lru_link);
   LINK(HttpServerSession, hash_link);

http://git-wip-us.apache.org/repos/asf/trafficserver/blob/0d8bfb40/proxy/http/HttpSessionManager.cc
----------------------------------------------------------------------
diff --git a/proxy/http/HttpSessionManager.cc b/proxy/http/HttpSessionManager.cc
index 8c8c81f..e533137 100644
--- a/proxy/http/HttpSessionManager.cc
+++ b/proxy/http/HttpSessionManager.cc
@@ -175,6 +175,25 @@ HttpSessionManager::purge_keepalives()
   }
 }
 
+bool
+HttpSessionManager::match(HttpServerSession* s, sockaddr const* addr, INK_MD5 
const& hostname_hash, HttpSM* sm)
+{
+  return
+    (TS_SERVER_SESSION_SHARING_MATCH_HOST == 
sm->t_state.txn_conf->server_session_sharing_match || 
+          (ats_ip_addr_eq(&s->server_ip.sa, addr) && ats_ip_port_cast(addr) == 
ats_ip_port_cast(addr)))
+    && (TS_SERVER_SESSION_SHARING_MATCH_IP == 
sm->t_state.txn_conf->server_session_sharing_match ||
+        s->hostname_hash == hostname_hash)
+    ;
+}
+
+bool
+HttpSessionManager::match(HttpServerSession* s, sockaddr const* addr, char 
const* hostname, HttpSM* sm)
+{
+  INK_MD5 hostname_hash;
+  ink_code_md5((unsigned char *) hostname, strlen(hostname), 
reinterpret_cast<unsigned char *>(&hostname_hash));
+  return match(s, addr, hostname_hash, sm);
+}
+
 HSMresult_t
 _acquire_session(SessionBucket *bucket, sockaddr const* ip, INK_MD5 
&hostname_hash, HttpSM *sm)
 {
@@ -188,18 +207,14 @@ _acquire_session(SessionBucket *bucket, sockaddr const* 
ip, INK_MD5 &hostname_ha
   //  the 2nd level bucket
   b = bucket->l2_hash[l2_index].head;
   while (b != NULL) {
-    if (ats_ip_addr_eq(&b->server_ip.sa, ip) &&
-      ats_ip_port_cast(ip) == ats_ip_port_cast(&b->server_ip)
-    ) {
-      if (hostname_hash == b->hostname_hash) {
-        bucket->lru_list.remove(b);
-        bucket->l2_hash[l2_index].remove(b);
-        b->state = HSS_ACTIVE;
-        to_return = b;
-        Debug("http_ss", "[%" PRId64 "] [acquire session] " "return session 
from shared pool", to_return->con_id);
-        sm->attach_server_session(to_return);
-        return HSM_DONE;
-      }
+    if (HttpSessionManager::match(b, ip, hostname_hash, sm)) {
+      bucket->lru_list.remove(b);
+      bucket->l2_hash[l2_index].remove(b);
+      b->state = HSS_ACTIVE;
+      to_return = b;
+      Debug("http_ss", "[%" PRId64 "] [acquire session] " "return session from 
shared pool", to_return->con_id);
+      sm->attach_server_session(to_return);
+      return HSM_DONE;
     }
 
     b = b->hash_link.next;
@@ -234,14 +249,11 @@ HttpSessionManager::acquire_session(Continuation * /* 
cont ATS_UNUSED */, sockad
   if (to_return != NULL) {
     ua_session->attach_server_session(NULL);
 
-    if (ats_ip_addr_eq(&to_return->server_ip.sa, ip) &&
-       ats_ip_port_cast(&to_return->server_ip) == ats_ip_port_cast(ip)) {
-      if (hostname_hash == to_return->hostname_hash) {
-        Debug("http_ss", "[%" PRId64 "] [acquire session] returning attached 
session ", to_return->con_id);
-        to_return->state = HSS_ACTIVE;
-        sm->attach_server_session(to_return);
-        return HSM_DONE;
-      }
+    if (match(to_return, ip, hostname_hash, sm)) {
+      Debug("http_ss", "[%" PRId64 "] [acquire session] returning attached 
session ", to_return->con_id);
+      to_return->state = HSS_ACTIVE;
+      sm->attach_server_session(to_return);
+      return HSM_DONE;
     }
     // Release this session back to the main session pool and
     //   then continue looking for one from the shared pool
@@ -257,7 +269,7 @@ HttpSessionManager::acquire_session(Continuation * /* cont 
ATS_UNUSED */, sockad
 
   ink_assert(l1_index < HSM_LEVEL1_BUCKETS);
 
-  if (2 == sm->t_state.txn_conf->share_server_sessions) {
+  if (TS_SERVER_SESSION_SHARING_POOL_THREAD == 
sm->t_state.txn_conf->server_session_sharing_pool) {
     ink_assert(ethread->l1_hash);
     return _acquire_session(ethread->l1_hash + l1_index, ip, hostname_hash, 
sm);
   } else {
@@ -283,7 +295,7 @@ HttpSessionManager::release_session(HttpServerSession 
*to_release)
 
   ink_assert(l1_index < HSM_LEVEL1_BUCKETS);
 
-  if (2 == to_release->share_session) {
+  if (TS_SERVER_SESSION_SHARING_POOL_THREAD == to_release->sharing_pool) {
     bucket = ethread->l1_hash + l1_index;
   } else {
     bucket = g_l1_hash + l1_index;

http://git-wip-us.apache.org/repos/asf/trafficserver/blob/0d8bfb40/proxy/http/HttpSessionManager.h
----------------------------------------------------------------------
diff --git a/proxy/http/HttpSessionManager.h b/proxy/http/HttpSessionManager.h
index de59bac..f6086eb 100644
--- a/proxy/http/HttpSessionManager.h
+++ b/proxy/http/HttpSessionManager.h
@@ -78,6 +78,23 @@ public:
   void init();
   int main_handler(int event, void *data);
 
+  /// Check if a session is a valid match.
+  static bool match(
+                   HttpServerSession* s, ///< Session to check for match.
+                   sockaddr const* addr, ///< IP address.
+                   INK_MD5 const& hostname_hash, ///< Hash of hostname of 
origin server.
+                   HttpSM* sm ///< State machine (for configuration data).
+                   );
+
+  /// Check if a session is a valid match.
+  static bool match(
+                   HttpServerSession* s, ///< Session to check for match.
+                   sockaddr const* addr, ///< IP address.
+                   char const* hostname, ///< Hostname of origin server.
+                   HttpSM* sm ///< State machine (for configuration data).
+                   );
+
+
 private:
   //    Global l1 hash, used when there is no per-thread buckets
   SessionBucket g_l1_hash[HSM_LEVEL1_BUCKETS];

Reply via email to