You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@trafficserver.apache.org by zw...@apache.org on 2013/10/06 17:06:38 UTC

git commit: TS-2212 Implement tag for HTTP

Updated Branches:
  refs/heads/master 196cd66f1 -> 8d17457f1


TS-2212 Implement <fsiz> tag for HTTP

The current docs explains it as

``fsiz``
    The size of the file (*n* bytes) as seen by the origin server.

However, there's nothing that implements this. This code will
try its best to find a body size, based on origin response
headers such as Content-Range and bytes read.

It's somewhat unfortunate that at the time of logging, the CacheVC
is no longer evailable, and all headers are already modified such
that they reflect client's e.g. Range: bytes=  header.

This patch implements the logic around using the Range-response
headers when available, and the internal (full) byte counters
when not.

Finally, this also generalizes the "atoi" functionality in lib/ts
(ParseRules) such that the prototypes with and without a string
length are available for all int types. This was needed in order
to do an efficient and safe atoi on the not-null terminated string
to a 64-bit int.


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

Branch: refs/heads/master
Commit: 8d17457f1fe5f91a10bb790d89019f88145b6479
Parents: 196cd66
Author: Leif Hedstrom <zw...@apache.org>
Authored: Thu Sep 12 13:58:27 2013 -0600
Committer: Leif Hedstrom <zw...@apache.org>
Committed: Sun Oct 6 09:03:40 2013 -0600

----------------------------------------------------------------------
 CHANGES                        |   5 +
 lib/ts/ParseRules.cc           | 131 +++++++++++++++++++++++
 lib/ts/ParseRules.h            | 206 +++++-------------------------------
 proxy/http/HttpSM.cc           |   1 +
 proxy/logging/LogAccessHttp.cc |  33 ++++++
 proxy/logging/LogAccessHttp.h  |   1 +
 6 files changed, 197 insertions(+), 180 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/trafficserver/blob/8d17457f/CHANGES
----------------------------------------------------------------------
diff --git a/CHANGES b/CHANGES
index cf1bff2..4b0344f 100644
--- a/CHANGES
+++ b/CHANGES
@@ -1,6 +1,11 @@
                                                          -*- coding: utf-8 -*-
 Changes with Apache Traffic Server 4.1.0
 
+  *) [TS-2212] Implement the <fsiz> log tag for HTTP requests. This also does
+   a small refactoring of the "atoi" functions in lib/ts, such that we now
+   consistently have both prototypes for all types (with and without a
+   string length parameter).
+
   *) [TS-2261] Add config option to restore/elevate access to reading files by
    root when loading plugins
 

http://git-wip-us.apache.org/repos/asf/trafficserver/blob/8d17457f/lib/ts/ParseRules.cc
----------------------------------------------------------------------
diff --git a/lib/ts/ParseRules.cc b/lib/ts/ParseRules.cc
index ba6ab7b..1834bbd 100644
--- a/lib/ts/ParseRules.cc
+++ b/lib/ts/ParseRules.cc
@@ -176,3 +176,134 @@ ParseRules::ink_tolower_buffer(char *ptr, unsigned int n)
     }
   }
 }
+
+// Implement our atol() / strtol() utility functions. Note that these will
+// deal with two cases atol does not:
+//
+//   1. They will handle both base 10 and base 16, always. 0x indicates hex.
+//   2. They all honor the SI multipliers (i.e. K, M, G and T.
+//
+int64_t
+ink_atoi64(const char *str)
+{
+  int64_t num = 0;
+  int negative = 0;
+
+  while (*str && ParseRules::is_wslfcr(*str))
+    str += 1;
+
+  if (unlikely(str[0] == '0' && str[1] == 'x')) {
+    str += 2;
+    while (*str && ParseRules::is_hex(*str))
+      num = (num << 4) + ink_get_hex(*str++);
+  } else {
+    if (unlikely(*str == '-')) {
+      negative = 1;
+      str += 1;
+    }
+
+    /*
+      NOTE: we first compute the value as negative then correct the
+      sign back to positive. This enables us to correctly parse MININT.
+    */
+    while (*str && ParseRules::is_digit(*str))
+      num = (num * 10) - (*str++ - '0');
+#if USE_SI_MULTILIERS
+    if (*str) {
+      if (*str == 'K')
+        num = num * (1LL << 10);
+      else if (*str == 'M')
+        num = num * (1LL << 20);
+      else if (*str == 'G')
+        num = num * (1LL << 30);
+      else if (*str == 'T')
+        num = num * (1LL << 40);
+    }
+#endif
+    if (!negative)
+      num = -num;
+  }
+  return num;
+}
+
+uint64_t
+ink_atoui64(const char *str)
+{
+  uint64_t num = 0;
+
+  while (*str && ParseRules::is_wslfcr(*str))
+    str += 1;
+
+  if (unlikely(str[0] == '0' && str[1] == 'x')) {
+    str += 2;
+    while (*str && ParseRules::is_hex(*str))
+      num = (num << 4) + ink_get_hex(*str++);
+  } else {
+    while (*str && ParseRules::is_digit(*str))
+      num = (num * 10) + (*str++ - '0');
+#if USE_SI_MULTILIERS
+    if (*str) {
+      if (*str == 'K')
+        num = num * (1LL << 10);
+      else if (*str == 'M')
+        num = num * (1LL << 20);
+      else if (*str == 'G')
+        num = num * (1LL << 30);
+      else if (*str == 'T')
+        num = num * (1LL << 40);
+    }
+#endif
+  }
+  return num;
+}
+
+int64_t
+ink_atoi64(const char *str, int len)
+{
+  int64_t num = 0;
+  int negative = 0;
+
+  while (len > 0 && *str && ParseRules::is_wslfcr(*str)) {
+    str += 1;
+    len--;
+  }
+
+  if (len <= 1)
+    return 0;
+
+  if (unlikely(str[0] == '0' && len > 1 && str[1] == 'x')) {
+    str += 2;
+    while (len > 0 && *str && ParseRules::is_hex(*str)) {
+      num = (num << 4) + ink_get_hex(*str++);
+      len--;
+    }
+  } else {
+    if (unlikely(*str == '-')) {
+      negative = 1;
+      str += 1;
+    }
+
+    /*
+      NOTE: we first compute the value as negative then correct the
+      sign back to positive. This enables us to correctly parse MININT.
+    */
+    while (len > 0 && *str && ParseRules::is_digit(*str)) {
+      num = (num * 10) - (*str++ - '0');
+      len--;
+    }
+#if USE_SI_MULTILIERS
+    if (len > 0 && *str) {
+      if (*str == 'K')
+        num = num * (1 << 10);
+      else if (*str == 'M')
+        num = num * (1 << 20);
+      else if (*str == 'G')
+        num = num * (1 << 30);
+    }
+#endif
+
+    if (!negative)
+      num = -num;
+  }
+  return num;
+}

http://git-wip-us.apache.org/repos/asf/trafficserver/blob/8d17457f/lib/ts/ParseRules.h
----------------------------------------------------------------------
diff --git a/lib/ts/ParseRules.h b/lib/ts/ParseRules.h
index 04600dd..dca6236 100644
--- a/lib/ts/ParseRules.h
+++ b/lib/ts/ParseRules.h
@@ -29,6 +29,7 @@
 
 #include "ink_defs.h"
 #include "ink_apidefs.h"
+#include "ink_platform.h"
 
 typedef unsigned int CTypeResult;
 
@@ -818,201 +819,46 @@ ink_get_hex(char c)
   return (int) ((c - 'a') + 10);
 }
 
+int64_t ink_atoi64(const char *);
+uint64_t ink_atoui64(const char *);
+int64_t ink_atoi64(const char *, int);
+
+
 static inline int
 ink_atoi(const char *str)
 {
-  int num = 0;
-  int negative = 0;
-
-  while (*str && ParseRules::is_wslfcr(*str))
-    str += 1;
-
-  if (unlikely(str[0] == '0' && str[1] == 'x')) {
-    str += 2;
-    while (*str && ParseRules::is_hex(*str))
-      num = (num << 4) + ink_get_hex(*str++);
-  } else {
-    if (unlikely(*str == '-')) {
-      negative = 1;
-      str += 1;
-    }
-
-    /*
-       NOTE: we first compute the value as negative then correct the
-       sign back to positive. This enables us to correctly parse MININT.
-     */
-    while (*str && ParseRules::is_digit(*str))
-      num = (num * 10) - (*str++ - '0');
-#if USE_SI_MULTILIERS
-    if (*str) {
-      if (*str == 'K')
-        num = num * (1 << 10);
-      else if (*str == 'M')
-        num = num * (1 << 20);
-      else if (*str == 'G')
-        num = num * (1 << 30);
-    }
-#endif
-
-    if (!negative)
-      num = -num;
-  }
+  int64_t val = ink_atoi64(str);
 
-  return num;
+  if (val > INT_MAX)
+    return INT_MAX;
+  else if (val < INT_MIN)
+    return INT_MIN;
+  else
+    return static_cast<int>(val);
 }
 
 static inline int
 ink_atoi(const char *str, int len)
 {
-  int num = 0;
-  int negative = 0;
+  int64_t val = ink_atoi64(str, len);
 
-  while (len > 0 && *str && ParseRules::is_wslfcr(*str)) {
-    str += 1;
-    len--;
-  }
-
-  if (len <= 1)
-    return 0;
-
-  if (unlikely(str[0] == '0' && len > 1 && str[1] == 'x')) {
-    str += 2;
-    while (len > 0 && *str && ParseRules::is_hex(*str)) {
-      num = (num << 4) + ink_get_hex(*str++);
-      len--;
-    }
-  } else {
-    if (unlikely(*str == '-')) {
-      negative = 1;
-      str += 1;
-    }
-
-    /*
-       NOTE: we first compute the value as negative then correct the
-       sign back to positive. This enables us to correctly parse MININT.
-     */
-    while (len > 0 && *str && ParseRules::is_digit(*str)) {
-      num = (num * 10) - (*str++ - '0');
-      len--;
-    }
-#if USE_SI_MULTILIERS
-    if (len > 0 && *str) {
-      if (*str == 'K')
-        num = num * (1 << 10);
-      else if (*str == 'M')
-        num = num * (1 << 20);
-      else if (*str == 'G')
-        num = num * (1 << 30);
-    }
-#endif
-
-    if (!negative)
-      num = -num;
-  }
-  return num;
+  if (val > INT_MAX)
+    return INT_MAX;
+  else if (val < INT_MIN)
+    return INT_MIN;
+  else
+    return static_cast<int>(val);
 }
 
 static inline unsigned int
 ink_atoui(const char *str)
 {
-  unsigned int num = 0;
-
-  while (*str && ParseRules::is_wslfcr(*str))
-    str += 1;
-
-  if (unlikely(str[0] == '0' && str[1] == 'x')) {
-    str += 2;
-    while (*str && ParseRules::is_hex(*str))
-      num = (num << 4) + ink_get_hex(*str++);
-  } else {
-    while (*str && ParseRules::is_digit(*str))
-      num = (num * 10) + (*str++ - '0');
-#if USE_SI_MULTILIERS
-    if (*str) {
-      if (*str == 'K')
-        num = num * (1 << 10);
-      else if (*str == 'M')
-        num = num * (1 << 20);
-      else if (*str == 'G')
-        num = num * (1 << 30);
-    }
-#endif
-  }
-  return num;
-}
-
-static inline int64_t
-ink_atoi64(const char *str)
-{
-  int64_t num = 0;
-  int negative = 0;
-
-  while (*str && ParseRules::is_wslfcr(*str))
-    str += 1;
-
-  if (unlikely(str[0] == '0' && str[1] == 'x')) {
-    str += 2;
-    while (*str && ParseRules::is_hex(*str))
-      num = (num << 4) + ink_get_hex(*str++);
-  } else {
-    if (unlikely(*str == '-')) {
-      negative = 1;
-      str += 1;
-    }
-
-    /*
-    NOTE: we first compute the value as negative then correct the
-    sign back to positive. This enables us to correctly parse MININT.
-    */
-    while (*str && ParseRules::is_digit(*str))
-      num = (num * 10) - (*str++ - '0');
-#if USE_SI_MULTILIERS
-    if (*str) {
-      if (*str == 'K')
-        num = num * (1LL << 10);
-      else if (*str == 'M')
-        num = num * (1LL << 20);
-      else if (*str == 'G')
-        num = num * (1LL << 30);
-      else if (*str == 'T')
-        num = num * (1LL << 40);
-    }
-#endif
-    if (!negative)
-      num = -num;
-  }
-  return num;
-}
-
-static inline uint64_t
-ink_atoui64(const char *str)
-{
-  uint64_t num = 0;
-
-  while (*str && ParseRules::is_wslfcr(*str))
-    str += 1;
-
-  if (unlikely(str[0] == '0' && str[1] == 'x')) {
-    str += 2;
-    while (*str && ParseRules::is_hex(*str))
-      num = (num << 4) + ink_get_hex(*str++);
-  } else {
-    while (*str && ParseRules::is_digit(*str))
-      num = (num * 10) + (*str++ - '0');
-#if USE_SI_MULTILIERS
-    if (*str) {
-      if (*str == 'K')
-        num = num * (1LL << 10);
-      else if (*str == 'M')
-        num = num * (1LL << 20);
-      else if (*str == 'G')
-        num = num * (1LL << 30);
-      else if (*str == 'T')
-        num = num * (1LL << 40);
-    }
-#endif
-  }
-  return num;
+  uint64_t val = ink_atoui64(str);
+
+  if (val > INT_MAX)
+    return INT_MAX;
+  else
+    return static_cast<int>(val);
 }
 
 #endif /* #if !defined (_ParseRules_h_) */

http://git-wip-us.apache.org/repos/asf/trafficserver/blob/8d17457f/proxy/http/HttpSM.cc
----------------------------------------------------------------------
diff --git a/proxy/http/HttpSM.cc b/proxy/http/HttpSM.cc
index 113a89b..beddcca 100644
--- a/proxy/http/HttpSM.cc
+++ b/proxy/http/HttpSM.cc
@@ -323,6 +323,7 @@ HttpSM::HttpSM()
     second_cache_sm(NULL),
     default_handler(NULL), pending_action(NULL), historical_action(NULL),
     last_action(HttpTransact::STATE_MACHINE_ACTION_UNDEFINED),
+    // TODO:  Now that bodies can be empty, should the body counters be set to -1 ? TS-2213
     client_request_hdr_bytes(0), client_request_body_bytes(0),
     server_request_hdr_bytes(0), server_request_body_bytes(0),
     server_response_hdr_bytes(0), server_response_body_bytes(0),

http://git-wip-us.apache.org/repos/asf/trafficserver/blob/8d17457f/proxy/logging/LogAccessHttp.cc
----------------------------------------------------------------------
diff --git a/proxy/logging/LogAccessHttp.cc b/proxy/logging/LogAccessHttp.cc
index a32de11..7e72399 100644
--- a/proxy/logging/LogAccessHttp.cc
+++ b/proxy/logging/LogAccessHttp.cc
@@ -976,6 +976,39 @@ LogAccessHttp::marshal_transfer_time_s(char *buf)
 }
 
 /*-------------------------------------------------------------------------
+  Figure out the size of the object *on origin*. This is somewhat tricky
+  since there are many variations on how this can be calculated.
+  -------------------------------------------------------------------------*/
+int
+LogAccessHttp::marshal_file_size(char *buf)
+{
+  if (buf) {
+    MIMEField *fld;
+    HTTPHdr *hdr = m_server_response ? m_server_response : m_cache_response;
+
+    if (hdr && (fld = hdr->field_find(MIME_FIELD_CONTENT_RANGE, MIME_LEN_CONTENT_RANGE))) {
+      int len;
+      char *str = (char*)fld->value_get(&len);
+      char *pos = (char*)memchr(str, '/', len); // Find the /
+
+      // If the size is not /* (which means unknown) use it as the file_size.
+      if (pos && !memchr(pos+1, '*', len - (pos + 1 - str))) {
+        marshal_int(buf, ink_atoi64(pos+1, len - (pos + 1 - str)));
+      }
+    } else {
+      // This is semi-broken when we serveq zero length objects. See TS-2213
+      if (m_http_sm->server_response_body_bytes > 0)
+        marshal_int(buf, m_http_sm->server_response_body_bytes);
+      else if (m_http_sm->cache_response_body_bytes > 0)
+        marshal_int(buf, m_http_sm->cache_response_body_bytes);
+    }
+  }
+  // Else, we don't set the value at all (so, -)
+
+  return INK_MIN_ALIGN;
+}
+
+/*-------------------------------------------------------------------------
   -------------------------------------------------------------------------*/
 
 int

http://git-wip-us.apache.org/repos/asf/trafficserver/blob/8d17457f/proxy/logging/LogAccessHttp.h
----------------------------------------------------------------------
diff --git a/proxy/logging/LogAccessHttp.h b/proxy/logging/LogAccessHttp.h
index 0568e4e..88192d0 100644
--- a/proxy/logging/LogAccessHttp.h
+++ b/proxy/logging/LogAccessHttp.h
@@ -126,6 +126,7 @@ public:
   //
   virtual int marshal_transfer_time_ms(char *); // INT
   virtual int marshal_transfer_time_s(char *);  // INT
+  virtual int marshal_file_size(char *); // INT
 
   //
   // named fields from within a http header