You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@trafficserver.apache.org by am...@apache.org on 2014/08/21 16:55:39 UTC

[1/6] ats_pagespeed: rename ats_speed -> ats_pagespeed

Repository: trafficserver
Updated Branches:
  refs/heads/5.1.x afa93fa92 -> e8b899b0f


http://git-wip-us.apache.org/repos/asf/trafficserver/blob/e8b899b0/plugins/experimental/ats_speed/gzip/gzip.cc
----------------------------------------------------------------------
diff --git a/plugins/experimental/ats_speed/gzip/gzip.cc b/plugins/experimental/ats_speed/gzip/gzip.cc
deleted file mode 100644
index 1397762..0000000
--- a/plugins/experimental/ats_speed/gzip/gzip.cc
+++ /dev/null
@@ -1,826 +0,0 @@
-/** @file
-
-  Transforms content using gzip or deflate
-
-  @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.
- */
-#define __STDC_LIMIT_MACROS
-#define __STDC_CONSTANT_MACROS
-#include <stdint.h>
-
-#include <string>
-#include <string.h>
-#include <zlib.h>
-#include <ts/ts.h>
-#include "debug_macros.h"
-#include "misc.h"
-#include "configuration.h"
-//#include "ink_defs.h"
-
-using namespace std;
-using namespace Gzip;
-
-//FIXME: custom dictionaries would be nice. configurable/content-type?
-//FIXME: look into autoscaling the compression level based on connection speed
-// a gprs device might benefit from a higher compression ratio, whereas a desktop w. high bandwith
-// might be served better with little or no compression at all
-//FIXME: look into compressing from the task thread pool
-//FIXME: make normalizing accept encoding configurable
-
-// from mod_deflate:
-// ZLIB's compression algorithm uses a
-// 0-9 based scale that GZIP does where '1' is 'Best speed' 
-// and '9' is 'Best compression'. Testing has proved level '6' 
-// to be about the best level to use in an HTTP Server. 
-
-const int ZLIB_COMPRESSION_LEVEL = 6;
-
-int arg_idx_hooked;
-int arg_idx_host_configuration;
-int arg_idx_url_disallowed;
-
-
-const char * global_hidden_header_name;
-Configuration* config = NULL;
-const char *dictionary = NULL;
-
-static GzipData *
-gzip_data_alloc(int compression_type)
-{
-  GzipData *data;
-  int err;
-
-  data = (GzipData *) TSmalloc(sizeof(GzipData));
-  data->downstream_vio = NULL;
-  data->downstream_buffer = NULL;
-  data->downstream_reader = NULL;
-  data->downstream_length = 0;
-  data->state = transform_state_initialized;
-  data->compression_type = compression_type;
-  data->zstrm.next_in = Z_NULL;
-  data->zstrm.avail_in = 0;
-  data->zstrm.total_in = 0;
-  data->zstrm.next_out = Z_NULL;
-  data->zstrm.avail_out = 0;
-  data->zstrm.total_out = 0;
-  data->zstrm.zalloc = gzip_alloc;
-  data->zstrm.zfree = gzip_free;
-  data->zstrm.opaque = (voidpf) 0;
-  data->zstrm.data_type = Z_ASCII;
-
-  int window_bits = (compression_type == COMPRESSION_TYPE_GZIP) ? WINDOW_BITS_GZIP : WINDOW_BITS_DEFLATE;
-
-  err = deflateInit2(&data->zstrm, ZLIB_COMPRESSION_LEVEL, Z_DEFLATED, window_bits, ZLIB_MEMLEVEL, Z_DEFAULT_STRATEGY);
-
-  if (err != Z_OK) {
-    fatal("gzip-transform: ERROR: deflateInit (%d)!", err);
-  }
-
-  if (dictionary) {
-    err = deflateSetDictionary(&data->zstrm, (const Bytef *) dictionary, strlen(dictionary));
-    if (err != Z_OK) {
-      fatal("gzip-transform: ERROR: deflateSetDictionary (%d)!", err);
-    }
-  }
-
-  return data;
-}
-
-
-static void
-gzip_data_destroy(GzipData * data)
-{
-  TSReleaseAssert(data);
-
-  //deflateEnd returnvalue ignore is intentional
-  //it would spew log on every client abort
-  deflateEnd(&data->zstrm);
-
-  if (data->downstream_buffer) {
-    TSIOBufferDestroy(data->downstream_buffer);
-  }
-
-  TSfree(data);
-}
-
-static TSReturnCode
-gzip_content_encoding_header(TSMBuffer bufp, TSMLoc hdr_loc, const int compression_type)
-{
-  TSReturnCode ret;
-  TSMLoc ce_loc;
-
-  // Delete Content-Encoding if present???
-
-  if ((ret = TSMimeHdrFieldCreateNamed(bufp, hdr_loc, "Content-Encoding", sizeof("Content-Encoding") - 1, &ce_loc)) == TS_SUCCESS) {
-    if (compression_type == COMPRESSION_TYPE_DEFLATE) {
-      ret = TSMimeHdrFieldValueStringInsert(bufp, hdr_loc, ce_loc, -1, "deflate", sizeof("deflate") - 1);
-    } else if (compression_type == COMPRESSION_TYPE_GZIP) {
-      ret = TSMimeHdrFieldValueStringInsert(bufp, hdr_loc, ce_loc, -1, "gzip", sizeof("gzip") - 1);
-    }
-    if (ret == TS_SUCCESS) {
-      ret = TSMimeHdrFieldAppend(bufp, hdr_loc, ce_loc);
-    }
-    TSHandleMLocRelease(bufp, hdr_loc, ce_loc);
-  }
-
-  if (ret != TS_SUCCESS) {
-    error("cannot add the Content-Encoding header");
-  }
-
-  return ret;
-}
-
-static TSReturnCode
-gzip_vary_header(TSMBuffer bufp, TSMLoc hdr_loc)
-{
-  TSReturnCode ret;
-  TSMLoc ce_loc;
-
-  ce_loc = TSMimeHdrFieldFind(bufp, hdr_loc, "Vary", sizeof("Vary") - 1);
-  if (ce_loc) {
-    int idx, count, len; 
-    const char *value;
-
-    count = TSMimeHdrFieldValuesCount(bufp, hdr_loc, ce_loc);
-    for(idx=0; idx<count; idx++) {
-      value = TSMimeHdrFieldValueStringGet(bufp, hdr_loc, ce_loc, idx, &len);
-      if (len &&
-          strncasecmp("Accept-Encoding", value, len) == 0) {
-        // Bail, Vary: Accept-Encoding already sent from origin
-        TSHandleMLocRelease(bufp, hdr_loc, ce_loc);
-        return TS_SUCCESS;
-      }
-    }
-
-    ret = TSMimeHdrFieldValueStringInsert(bufp, hdr_loc, ce_loc, -1, "Accept-Encoding", sizeof("Accept-Encoding") - 1);
-    TSHandleMLocRelease(bufp, hdr_loc, ce_loc);
-  } else {
-    if ((ret = TSMimeHdrFieldCreateNamed(bufp, hdr_loc, "Vary", sizeof("Vary") - 1, &ce_loc)) == TS_SUCCESS) {
-      if ((ret = TSMimeHdrFieldValueStringInsert(bufp, hdr_loc, ce_loc, -1, "Accept-Encoding", sizeof("Accept-Encoding") - 1)) == TS_SUCCESS) {
-        ret = TSMimeHdrFieldAppend(bufp, hdr_loc, ce_loc);
-      }
-
-      TSHandleMLocRelease(bufp, hdr_loc, ce_loc);
-    }
-  }
-
-  if (ret != TS_SUCCESS) {
-    error("cannot add/update the Vary header");
-  }
-
-  return ret;
-}
-
-//FIXME: the etag alteration isn't proper. it should modify the value inside quotes
-//       specify a very header..
-static TSReturnCode
-gzip_etag_header(TSMBuffer bufp, TSMLoc hdr_loc)
-{
-  TSReturnCode ret = TS_SUCCESS;
-  TSMLoc ce_loc;
-
-  ce_loc = TSMimeHdrFieldFind(bufp, hdr_loc, TS_MIME_FIELD_ETAG, TS_MIME_LEN_ETAG);
-
-  if (ce_loc) {
-    int changetag = 1;
-    int strl;
-    const char *strv = TSMimeHdrFieldValueStringGet(bufp, hdr_loc, ce_loc, -1, &strl);
-    //do not alter weak etags.
-    //FIXME: consider just making the etag weak for compressed content
-    if (strl >= 2) {
-      if ((strv[0] == 'w' || strv[0] == 'W') && strv[1] == '/') {
-        changetag = 0;
-      }
-      if (changetag) {
-        ret = TSMimeHdrFieldValueAppend(bufp, hdr_loc, ce_loc, 0, "-df", 3);
-      }
-    }
-    TSHandleMLocRelease(bufp, hdr_loc, ce_loc);
-  }
-
-  if (ret != TS_SUCCESS) {
-    error("cannot handle the %s header", TS_MIME_FIELD_ETAG);
-  }
-
-  return ret;
-}
-
-//FIXME: some things are potentially compressible. those responses
-static void
-gzip_transform_init(TSCont contp, GzipData * data)
-{
-  //update the vary, content-encoding, and etag response headers
-  //prepare the downstream for transforming
-
-  TSVConn downstream_conn;
-  TSMBuffer bufp;
-  TSMLoc hdr_loc;
-
-  data->state = transform_state_output;
-
-  if (TSHttpTxnTransformRespGet(data->txn, &bufp, &hdr_loc) != TS_SUCCESS) {
-    error("Error TSHttpTxnTransformRespGet");
-    return;
-  }
-
-  if (gzip_content_encoding_header(bufp, hdr_loc, data->compression_type) == TS_SUCCESS &&
-      gzip_vary_header(bufp, hdr_loc) == TS_SUCCESS &&
-      gzip_etag_header(bufp, hdr_loc) == TS_SUCCESS) {
-    downstream_conn = TSTransformOutputVConnGet(contp);
-    data->downstream_buffer = TSIOBufferCreate();
-    data->downstream_reader = TSIOBufferReaderAlloc(data->downstream_buffer);
-    data->downstream_vio = TSVConnWrite(downstream_conn, contp, data->downstream_reader, INT64_MAX);
-  }
-
-  TSHandleMLocRelease(bufp, TS_NULL_MLOC, hdr_loc);
-}
-
-
-
-static void
-gzip_transform_one(GzipData * data, TSIOBufferReader upstream_reader, int amount)
-{
-  TSIOBufferBlock downstream_blkp;
-  const char *upstream_buffer;
-  char *downstream_buffer;
-  int64_t upstream_length, downstream_length;
-  int err;
-
-  while (amount > 0) {
-    downstream_blkp = TSIOBufferReaderStart(upstream_reader);
-    if (!downstream_blkp) {
-      error("couldn't get from IOBufferBlock");
-      return;
-    }
-
-    upstream_buffer = TSIOBufferBlockReadStart(downstream_blkp, upstream_reader, &upstream_length);
-    if (!upstream_buffer) {
-      error("couldn't get from TSIOBufferBlockReadStart");
-      return;
-    }
-
-    if (upstream_length > amount) {
-      upstream_length = amount;
-    }
-
-    data->zstrm.next_in = (unsigned char *) upstream_buffer;
-    data->zstrm.avail_in = upstream_length;
-
-    while (data->zstrm.avail_in > 0) {
-      downstream_blkp = TSIOBufferStart(data->downstream_buffer);
-      downstream_buffer = TSIOBufferBlockWriteStart(downstream_blkp, &downstream_length);
-
-      data->zstrm.next_out = (unsigned char *) downstream_buffer;
-      data->zstrm.avail_out = downstream_length;
-
-      err = deflate(&data->zstrm, Z_NO_FLUSH);
-
-      if (err != Z_OK)
-        warning("deflate() call failed: %d", err);
-
-      if (downstream_length > data->zstrm.avail_out) {
-        TSIOBufferProduce(data->downstream_buffer, downstream_length - data->zstrm.avail_out);
-        data->downstream_length += (downstream_length - data->zstrm.avail_out);
-      }
-
-      if (data->zstrm.avail_out > 0) {
-        if (data->zstrm.avail_in != 0) {
-          error("gzip-transform: ERROR: avail_in is (%d): should be 0", data->zstrm.avail_in);
-        }
-      }
-    }
-
-    TSIOBufferReaderConsume(upstream_reader, upstream_length);
-    amount -= upstream_length;
-  }
-}
-
-static void
-gzip_transform_finish(GzipData * data)
-{
-  if (data->state == transform_state_output) {
-    TSIOBufferBlock downstream_blkp;
-    char *downstream_buffer;
-    int64_t downstream_length;
-    int err;
-
-    data->state = transform_state_finished;
-
-    for (;;) {
-      downstream_blkp = TSIOBufferStart(data->downstream_buffer);
-
-      downstream_buffer = TSIOBufferBlockWriteStart(downstream_blkp, &downstream_length);
-      data->zstrm.next_out = (unsigned char *) downstream_buffer;
-      data->zstrm.avail_out = downstream_length;
-
-      err = deflate(&data->zstrm, Z_FINISH);
-
-      if (downstream_length > (int64_t) data->zstrm.avail_out) {
-        TSIOBufferProduce(data->downstream_buffer, downstream_length - data->zstrm.avail_out);
-        data->downstream_length += (downstream_length - data->zstrm.avail_out);
-      }
-
-      if (err == Z_OK) {        /* some more data to encode */
-        continue;
-      }
-
-      if (err != Z_STREAM_END) {
-        warning("deflate should report Z_STREAM_END");
-      }
-      break;
-    }
-
-    if (data->downstream_length != (int64_t) (data->zstrm.total_out)) {
-      error("gzip-transform: ERROR: output lengths don't match (%d, %ld)", data->downstream_length,
-            data->zstrm.total_out);
-    }
-
-    gzip_log_ratio(data->zstrm.total_in, data->downstream_length);
-  }
-}
-
-
-static void
-gzip_transform_do(TSCont contp)
-{
-  TSVIO upstream_vio;
-  GzipData *data;
-  int64_t upstream_todo;
-  int64_t upstream_avail;
-  int64_t downstream_bytes_written;
-
-  data = (GzipData*)TSContDataGet(contp);
-  if (data->state == transform_state_initialized) {
-    gzip_transform_init(contp, data);
-  }
-
-  upstream_vio = TSVConnWriteVIOGet(contp);
-  downstream_bytes_written = data->downstream_length;
-
-  if (!TSVIOBufferGet(upstream_vio)) {
-    gzip_transform_finish(data);
-
-    TSVIONBytesSet(data->downstream_vio, data->downstream_length);
-
-    if (data->downstream_length > downstream_bytes_written) {
-      TSVIOReenable(data->downstream_vio);
-    }
-    return;
-  }
-
-  upstream_todo = TSVIONTodoGet(upstream_vio);
-
-  if (upstream_todo > 0) {
-    upstream_avail = TSIOBufferReaderAvail(TSVIOReaderGet(upstream_vio));
-
-    if (upstream_todo > upstream_avail) {
-      upstream_todo = upstream_avail;
-    }
-
-    if (upstream_todo > 0) {
-      gzip_transform_one(data, TSVIOReaderGet(upstream_vio), upstream_todo);
-      TSVIONDoneSet(upstream_vio, TSVIONDoneGet(upstream_vio) + upstream_todo);
-    }
-  }
-
-  if (TSVIONTodoGet(upstream_vio) > 0) {
-    if (upstream_todo > 0) {
-      if (data->downstream_length > downstream_bytes_written) {
-        TSVIOReenable(data->downstream_vio);
-      }
-      TSContCall(TSVIOContGet(upstream_vio), TS_EVENT_VCONN_WRITE_READY, upstream_vio);
-    }
-  } else {
-    gzip_transform_finish(data);
-    TSVIONBytesSet(data->downstream_vio, data->downstream_length);
-
-    if (data->downstream_length > downstream_bytes_written) {
-      TSVIOReenable(data->downstream_vio);
-    }
-
-    TSContCall(TSVIOContGet(upstream_vio), TS_EVENT_VCONN_WRITE_COMPLETE, upstream_vio);
-  }
-}
-
-
-static int
-gzip_transform(TSCont contp, TSEvent event, void * /* edata ATS_UNUSED */)
-{
-  if (TSVConnClosedGet(contp)) {
-    gzip_data_destroy((GzipData*)TSContDataGet(contp));
-    TSContDestroy(contp);
-    return 0;
-  } else {
-    switch (event) {
-    case TS_EVENT_ERROR:{
-        debug("gzip_transform: TS_EVENT_ERROR starts");
-        TSVIO upstream_vio = TSVConnWriteVIOGet(contp);
-        TSContCall(TSVIOContGet(upstream_vio), TS_EVENT_ERROR, upstream_vio);
-      }
-      break;
-    case TS_EVENT_VCONN_WRITE_COMPLETE:
-      TSVConnShutdown(TSTransformOutputVConnGet(contp), 0, 1);
-      break;
-    case TS_EVENT_VCONN_WRITE_READY:
-      gzip_transform_do(contp);
-      break;
-    case TS_EVENT_IMMEDIATE:
-      gzip_transform_do(contp);
-      break;
-    default:
-      warning("unknown event [%d]", event);
-      gzip_transform_do(contp);
-      break;
-    }
-  }
-
-  return 0;
-}
-
-
-static int
-gzip_transformable(TSHttpTxn txnp, int server, HostConfiguration * host_configuration, int *compress_type)
-{
-  /* Server response header */
-  TSMBuffer bufp;
-  TSMLoc hdr_loc;
-  TSMLoc field_loc;
-
-  /* Client request header */
-  TSMBuffer cbuf;
-  TSMLoc chdr;
-  TSMLoc cfield;
-
-  const char *value;
-  int nvalues;
-  int i, compression_acceptable, len;
-
-  TSHttpStatus resp_status;
-  if (server) {
-    TSHttpTxnServerRespGet(txnp, &bufp, &hdr_loc);
-  } else {
-    TSHttpTxnCachedRespGet(txnp, &bufp, &hdr_loc);
-  }
-  resp_status = TSHttpHdrStatusGet(bufp, hdr_loc);
-  TSHandleMLocRelease(bufp, TS_NULL_MLOC, hdr_loc);
-
-  //conservatively pick some statusses to compress
-  if (!(resp_status == 200 || resp_status == 404 || resp_status == 500)) {
-    info("http response status [%d] is not compressible", resp_status);
-    return 0;
-  }
-
-  TSHttpTxnClientReqGet(txnp, &cbuf, &chdr);
-
-  //the only compressible method is currently GET.
-  int method_length;
-  const char *method = TSHttpHdrMethodGet(cbuf, chdr, &method_length);
-  if (!(method_length == TS_HTTP_LEN_GET && memcmp(method, TS_HTTP_METHOD_GET, TS_HTTP_LEN_GET) == 0)) {
-    debug("method is not GET, not compressible");
-    TSHandleMLocRelease(cbuf, TS_NULL_MLOC, chdr);
-    return 0;
-  }
-
-  cfield = TSMimeHdrFieldFind(cbuf, chdr, TS_MIME_FIELD_ACCEPT_ENCODING, TS_MIME_LEN_ACCEPT_ENCODING);
-  if (cfield != TS_NULL_MLOC) {
-    compression_acceptable = 0;
-    nvalues = TSMimeHdrFieldValuesCount(cbuf, chdr, cfield);
-    for (i=0; i<nvalues; i++) {
-      value = TSMimeHdrFieldValueStringGet(cbuf, chdr, cfield, i, &len);
-      if (!value) {
-        continue;
-      }
-
-      if (strncasecmp(value, "deflate", sizeof("deflate") - 1) == 0) {
-        compression_acceptable = 1;
-        *compress_type = COMPRESSION_TYPE_DEFLATE;
-        break;
-      } else if (strncasecmp(value, "gzip", sizeof("gzip") - 1) == 0) {
-        compression_acceptable = 1;
-        *compress_type = COMPRESSION_TYPE_GZIP;
-        break;
-      }
-    }
-
-    TSHandleMLocRelease(cbuf, chdr, cfield);
-    TSHandleMLocRelease(cbuf, TS_NULL_MLOC, chdr);
-
-    if (!compression_acceptable) {
-      info("no acceptable encoding found in request header, not compressible");
-      return 0;
-    }
-  } else {
-    info("no acceptable encoding found in request header, not compressible");
-    TSHandleMLocRelease(cbuf, chdr, cfield);
-    TSHandleMLocRelease(cbuf, TS_NULL_MLOC, chdr);
-    return 0;
-  }
-
-  if (server) {
-    TSHttpTxnServerRespGet(txnp, &bufp, &hdr_loc);
-  } else {
-    TSHttpTxnCachedRespGet(txnp, &bufp, &hdr_loc);
-  }
-
-  /* If there already exists a content encoding then we don't want
-     to do anything. */
-  field_loc = TSMimeHdrFieldFind(bufp, hdr_loc, TS_MIME_FIELD_CONTENT_ENCODING, -1);
-  if (field_loc) {
-    info("response is already content encoded, not compressible");
-    TSHandleMLocRelease(bufp, hdr_loc, field_loc);
-    TSHandleMLocRelease(bufp, TS_NULL_MLOC, hdr_loc);
-    return 0;
-  }
-
-  /* We only want to do gzip compression on documents that have a
-     content type of "text/" or "application/x-javascript". */
-  field_loc = TSMimeHdrFieldFind(bufp, hdr_loc, TS_MIME_FIELD_CONTENT_TYPE, -1);
-  if (!field_loc) {
-    info("no content type header found, not compressible");
-    TSHandleMLocRelease(bufp, TS_NULL_MLOC, hdr_loc);
-    return 0;
-  }
-
-  value = TSMimeHdrFieldValueStringGet(bufp, hdr_loc, field_loc, 0, &len);
-
-  int rv = host_configuration->ContentTypeIsCompressible(value, len);
-  if (!rv) { 
-    info("content-type [%.*s] not compressible", len, value);
-  }
-  TSHandleMLocRelease(bufp, hdr_loc, field_loc);
-  TSHandleMLocRelease(bufp, TS_NULL_MLOC, hdr_loc);
-  return rv;
-}
-
-
-static void
-gzip_transform_add(TSHttpTxn txnp, int /* server ATS_UNUSED */, HostConfiguration * hc, int compress_type)
-{
-  int *tmp = (int *) TSHttpTxnArgGet(txnp, arg_idx_hooked);
-  if (tmp) {
-    //happens on cache_stale_hit
-    debug("transform hook already set, bail");
-    return;
-  } else {
-    TSHttpTxnArgSet(txnp, arg_idx_hooked, (void *) &GZIP_ONE);
-    info("adding compression transform");
-  }
-
-  TSHttpTxnUntransformedRespCache(txnp, 1);
-
-  if (!hc->cache()) {
-    debug("@@@@@ Gzip cache disabled");
-    TSHttpTxnTransformedRespCache(txnp, 0);
-  } else {
-    TSMBuffer bufp;
-    TSMLoc hdr_loc, field_loc;
-    int cache = 1;
-    if (TSHttpTxnServerRespGet(txnp, &bufp, &hdr_loc) == TS_SUCCESS || TSHttpTxnCachedRespGet(txnp, &bufp, &hdr_loc) == TS_SUCCESS) {
-      field_loc = TSMimeHdrFieldFind(bufp, hdr_loc, "@gzip_nocache", strlen("@gzip_nocache"));
-      if (field_loc) {
-        cache = 0;
-        debug("@@@@@ Gzip disallows cacheing of transformed response");
-        TSHandleMLocRelease(bufp, hdr_loc, field_loc);
-      } else  {
-        debug("@@@@ Gzip allows cacheing of transformed response");
-      }
-      TSHandleMLocRelease(bufp, TS_NULL_MLOC, hdr_loc);
-    }
-    
-    TSHttpTxnTransformedRespCache(txnp, cache);
-  }
-
-  TSVConn connp;
-  GzipData *data;
-
-  connp = TSTransformCreate(gzip_transform, txnp);
-  data = gzip_data_alloc(compress_type);
-  data->txn = txnp;
-
-  TSContDataSet(connp, data);
-  TSHttpTxnHookAdd(txnp, TS_HTTP_RESPONSE_TRANSFORM_HOOK, connp);
-}
-
-static int
-cache_transformable(TSHttpTxn txnp)
-{
-  int obj_status;
-
-  if (TSHttpTxnCacheLookupStatusGet(txnp, &obj_status) == TS_ERROR) {
-    warning("Couldn't get cache status of object");
-    return 0;
-  }
-  if (obj_status == TS_CACHE_LOOKUP_HIT_STALE) {
-    info("stale cache hit");
-    return 0;
-  }
-  if (obj_status == TS_CACHE_LOOKUP_HIT_FRESH) {
-    info("fresh cache hit");
-    return 1;
-  }
-
-  return 0;
-}
-
-HostConfiguration * 
-find_host_configuration(TSHttpTxn /* txnp ATS_UNUSED */, TSMBuffer bufp, TSMLoc locp)
-{
-  TSMLoc fieldp = TSMimeHdrFieldFind(bufp, locp, TS_MIME_FIELD_HOST, TS_MIME_LEN_HOST);
-
-  if (fieldp) {
-    int strl;
-    const char *strv = TSMimeHdrFieldValueStringGet(bufp, locp, fieldp, -1, &strl);
-    TSHandleMLocRelease(bufp, locp, fieldp);
-
-    HostConfiguration * host_configuration = config->Find(strv, strl);   
-    return host_configuration;
-  }
-
-  return config->GlobalConfiguration();
-}
-
-
-static int
-transform_plugin(TSCont /* contp ATS_UNUSED */, TSEvent event, void *edata)
-{
-  TSHttpTxn txnp = (TSHttpTxn) edata;
-  int compress_type = COMPRESSION_TYPE_DEFLATE;
-
-  switch (event) {
-    case TS_EVENT_HTTP_READ_REQUEST_HDR:
-      {
-        TSMBuffer req_buf;
-        TSMLoc req_loc;
-        if (TSHttpTxnClientReqGet(txnp, &req_buf, &req_loc) == TS_SUCCESS) {
-          int url_len;
-          char * url = TSHttpTxnEffectiveUrlStringGet(txnp, &url_len);
-          HostConfiguration * hc = find_host_configuration(txnp, req_buf, req_loc);
-          //we could clone the hosting configuration here, to make it deletable on reload?
-          TSHttpTxnArgSet(txnp, arg_idx_host_configuration, (void *) hc);
-
-          if (!hc->enabled() || !hc->IsUrlAllowed(url, url_len)) {
-            //FIXME: no double negatives
-            TSHttpTxnArgSet(txnp, arg_idx_url_disallowed, (void *) &GZIP_ONE);
-            info("url [%.*s] not allowed", url_len, url);
-          } else {
-            normalize_accept_encoding(txnp, req_buf, req_loc);	
-          }
-          TSfree(url);
-          TSHandleMLocRelease(req_buf, TS_NULL_MLOC, req_loc);
-        }
-        TSHttpTxnReenable(txnp, TS_EVENT_HTTP_CONTINUE);
-      }
-      break;
-
-    case TS_EVENT_HTTP_READ_RESPONSE_HDR:
-      {
-        //os: the accept encoding header needs to be restored..
-        //otherwise the next request won't get a cache hit on this
-        HostConfiguration * hc = (HostConfiguration*)TSHttpTxnArgGet(txnp, arg_idx_host_configuration);
-        if (hc != NULL) { 
-          if (hc->remove_accept_encoding()) {
-            TSMBuffer req_buf;
-            TSMLoc req_loc;
-            if (TSHttpTxnServerReqGet(txnp, &req_buf, &req_loc) == TS_SUCCESS) {
-              restore_accept_encoding(txnp, req_buf, req_loc, global_hidden_header_name);
-              TSHandleMLocRelease(req_buf, TS_NULL_MLOC, req_loc);
-            }
-          }
-
-          int allowed = !TSHttpTxnArgGet(txnp, arg_idx_url_disallowed);
-          if ( allowed && gzip_transformable(txnp, 1, hc, &compress_type)) {
-            gzip_transform_add(txnp, 1, hc, compress_type);
-          }
-        }
-        TSHttpTxnReenable(txnp, TS_EVENT_HTTP_CONTINUE);
-      }
-      break;
-
-    case TS_EVENT_HTTP_SEND_REQUEST_HDR:
-      {
-        HostConfiguration * hc = (HostConfiguration*)TSHttpTxnArgGet(txnp, arg_idx_host_configuration);
-        if (hc!=NULL) {
-          if (hc->remove_accept_encoding()) {
-            TSMBuffer req_buf;
-            TSMLoc req_loc;
-            if (TSHttpTxnServerReqGet(txnp, &req_buf, &req_loc) == TS_SUCCESS) {
-              hide_accept_encoding(txnp, req_buf, req_loc, global_hidden_header_name);
-              TSHandleMLocRelease(req_buf, TS_NULL_MLOC, req_loc);
-            }
-          }
-        }
-        TSHttpTxnReenable(txnp, TS_EVENT_HTTP_CONTINUE);
-      }
-      break;
-
-    case TS_EVENT_HTTP_CACHE_LOOKUP_COMPLETE:
-      {
-        int allowed = !TSHttpTxnArgGet(txnp, arg_idx_url_disallowed);
-        HostConfiguration * hc = (HostConfiguration*)TSHttpTxnArgGet(txnp, arg_idx_host_configuration);
-        if ( hc != NULL ) { 
-          if (allowed && cache_transformable(txnp) && gzip_transformable(txnp, 0, hc, &compress_type)) {
-            gzip_transform_add(txnp, 0, hc, compress_type);
-          }
-        }
-        TSHttpTxnReenable(txnp, TS_EVENT_HTTP_CONTINUE);
-      }
-      break;
-
-    default:
-      fatal("gzip transform unknown event");
-  }
-
-  return 0;
-}
-
-
-static void
-read_configuration(TSCont contp) {
-  const char * path = (const char *)TSContDataGet(contp);
-  Configuration * newconfig = Configuration::Parse(path);
-
-  Configuration * oldconfig =__sync_lock_test_and_set(&config, newconfig);
-  debug("config swapped,old config %p", oldconfig);
-
-  //FIXME: we have leaked.
-  //consider cloning or refcounting the configuration passed to the txn
-  //to make deleting the old configuration possible
-  //if (config != NULL )
-  //  delete config;
-}
-
-static int
-management_update(TSCont contp, TSEvent event, void * /* edata ATS_UNUSED */)
-{
-  TSReleaseAssert(event == TS_EVENT_MGMT_UPDATE);
-  info("management update event received");
-  read_configuration(contp);
-  return 0;
-}
-
-
-void
-TSPluginInit(int argc, const char *argv[])
-{
-  string config_path;
-
-  if (argc > 2)  {
-    fatal("the gzip plugin does not accept more than 1 plugin argument");
-  } else if (argc == 2) { 
-    config_path = std::string(argv[1]);
-  }
-
-  info("TSPluginInit %s", argv[0]);
-
-  if (!register_plugin()) {
-    fatal("The gzip plugin failed to register");
-  }
-
-  //if (argc == 2) {
-  //  dictionary = load_dictionary(argv[1]);
-  //}
-
-  if (TSHttpArgIndexReserve("gzip", "for remembering if the hook was set", &arg_idx_hooked) != TS_SUCCESS) {
-    fatal("failed to reserve an argument index");
-  }
-  if (TSHttpArgIndexReserve("gzip", "for storing if compression is applicable", &arg_idx_host_configuration) != TS_SUCCESS) {
-    fatal("failed to reserve an argument index");
-  }
-  if (TSHttpArgIndexReserve("gzip", "for storing if compression is disallowed for this txn", &arg_idx_url_disallowed) != TS_SUCCESS) {
-    fatal("failed to reserve an argument index");
-  }
-
-  global_hidden_header_name = init_hidden_header_name();
-
-  TSCont management_contp = TSContCreate(management_update, NULL);
-  //fixme: never freed. there is no shutdown event?
-  char * p = (char*)TSmalloc(config_path.size()+1);
-  strcpy(p,config_path.c_str());
-  TSContDataSet(management_contp,(void*)p);
-  TSMgmtUpdateRegister(management_contp, TAG);
-  read_configuration(management_contp);
-
-  TSCont transform_contp = TSContCreate(transform_plugin, NULL);
-  TSHttpHookAdd(TS_HTTP_READ_REQUEST_HDR_HOOK, transform_contp);
-  TSHttpHookAdd(TS_HTTP_READ_RESPONSE_HDR_HOOK, transform_contp);
-  TSHttpHookAdd(TS_HTTP_SEND_REQUEST_HDR_HOOK, transform_contp);
-  TSHttpHookAdd(TS_HTTP_CACHE_LOOKUP_COMPLETE_HOOK, transform_contp);
-
-  info("loaded");
-}

http://git-wip-us.apache.org/repos/asf/trafficserver/blob/e8b899b0/plugins/experimental/ats_speed/gzip/gzip.config
----------------------------------------------------------------------
diff --git a/plugins/experimental/ats_speed/gzip/gzip.config b/plugins/experimental/ats_speed/gzip/gzip.config
deleted file mode 100644
index 81e9fa4..0000000
--- a/plugins/experimental/ats_speed/gzip/gzip.config
+++ /dev/null
@@ -1,6 +0,0 @@
-# Set some global options first
-cache true
-enabled true
-remove-accept-encoding false
-compressible-content-type text/*
-compressible-content-type *javascript*

http://git-wip-us.apache.org/repos/asf/trafficserver/blob/e8b899b0/plugins/experimental/ats_speed/gzip/misc.cc
----------------------------------------------------------------------
diff --git a/plugins/experimental/ats_speed/gzip/misc.cc b/plugins/experimental/ats_speed/gzip/misc.cc
deleted file mode 100644
index 0ea6911..0000000
--- a/plugins/experimental/ats_speed/gzip/misc.cc
+++ /dev/null
@@ -1,197 +0,0 @@
-/** @file
-
-  Transforms content using gzip or deflate
-
-  @section license License
-
-  Licensed to the Apache Software Foundation (ASF) under one
-  or more contributor license agreements.  See the NOTICE file
-  distributed with this work for additional information
-  regarding copyright ownership.  The ASF licenses this file
-  to you under the Apache License, Version 2.0 (the
-  "License"); you may not use this file except in compliance
-  with the License.  You may obtain a copy of the License at
-
-      http://www.apache.org/licenses/LICENSE-2.0
-
-  Unless required by applicable law or agreed to in writing, software
-  distributed under the License is distributed on an "AS IS" BASIS,
-  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-  See the License for the specific language governing permissions and
-  limitations under the License.
- */
-
-#include "ts/ts.h"
-//#include "ink_defs.h"
-#include <stdint.h>
-#include <inttypes.h>
-#include "misc.h"
-#include <string.h>
-#include "debug_macros.h"
-
-voidpf
-gzip_alloc(voidpf /* opaque ATS_UNUSED */, uInt items, uInt size)
-{
-  return (voidpf) TSmalloc(items * size);
-}
-
-void
-gzip_free(voidpf /* opaque ATS_UNUSED */, voidpf address)
-{
-  TSfree(address);
-}
-
-void
-normalize_accept_encoding(TSHttpTxn /* txnp ATS_UNUSED */, TSMBuffer reqp, TSMLoc hdr_loc)
-{
-  TSMLoc field = TSMimeHdrFieldFind(reqp, hdr_loc, TS_MIME_FIELD_ACCEPT_ENCODING, TS_MIME_LEN_ACCEPT_ENCODING);
-  int deflate = 0;
-  int gzip = 0;
-
-  //remove the accept encoding field(s), 
-  //while finding out if gzip or deflate is supported.    
-  while (field) {
-    TSMLoc tmp;
-
-    if (!deflate && !gzip) {
-      int value_count = TSMimeHdrFieldValuesCount(reqp, hdr_loc, field);
-
-      while (value_count > 0) {
-        int val_len = 0;
-        const char *val;
-
-        --value_count;
-        val = TSMimeHdrFieldValueStringGet(reqp, hdr_loc, field, value_count, &val_len);
-
-        if (val_len == (int) strlen("gzip"))
-          gzip = !strncmp(val, "gzip", val_len);
-        else if (val_len == (int) strlen("deflate"))
-          deflate = !strncmp(val, "deflate", val_len);
-      }
-    }
-
-    tmp = TSMimeHdrFieldNextDup(reqp, hdr_loc, field);
-    TSMimeHdrFieldDestroy(reqp, hdr_loc, field);        //catch retval?
-    TSHandleMLocRelease(reqp, hdr_loc, field);
-    field = tmp;
-  }
-
-  //append a new accept-encoding field in the header
-  if (deflate || gzip) {
-    TSMimeHdrFieldCreate(reqp, hdr_loc, &field);
-    TSMimeHdrFieldNameSet(reqp, hdr_loc, field, TS_MIME_FIELD_ACCEPT_ENCODING, TS_MIME_LEN_ACCEPT_ENCODING);
-
-    if (gzip) {
-      TSMimeHdrFieldValueStringInsert(reqp, hdr_loc, field, -1, "gzip", strlen("gzip"));
-      info("normalized accept encoding to gzip");
-    } else if (deflate) {
-      TSMimeHdrFieldValueStringInsert(reqp, hdr_loc, field, -1, "deflate", strlen("deflate"));
-      info("normalized accept encoding to deflate");
-    }
-
-    TSMimeHdrFieldAppend(reqp, hdr_loc, field);
-    TSHandleMLocRelease(reqp, hdr_loc, field);
-  }
-}
-
-void
-hide_accept_encoding(TSHttpTxn /* txnp ATS_UNUSED */, TSMBuffer reqp, TSMLoc hdr_loc, const char * hidden_header_name)
-{
-  TSMLoc field = TSMimeHdrFieldFind(reqp, hdr_loc, TS_MIME_FIELD_ACCEPT_ENCODING, TS_MIME_LEN_ACCEPT_ENCODING);
-  while (field) {
-    TSMLoc tmp;
-    tmp = TSMimeHdrFieldNextDup(reqp, hdr_loc, field);
-    TSMimeHdrFieldNameSet(reqp, hdr_loc, field, hidden_header_name, -1);
-    TSHandleMLocRelease(reqp, hdr_loc, field);
-    field = tmp;
-  }
-}
-
-void
-restore_accept_encoding(TSHttpTxn /* txnp ATS_UNUSED */, TSMBuffer reqp, TSMLoc hdr_loc, const char * hidden_header_name)
-{
-  TSMLoc field = TSMimeHdrFieldFind(reqp, hdr_loc, hidden_header_name, -1);
-
-  while (field) {
-    TSMLoc tmp;
-    tmp = TSMimeHdrFieldNextDup(reqp, hdr_loc, field);
-    TSMimeHdrFieldNameSet(reqp, hdr_loc, field, TS_MIME_FIELD_ACCEPT_ENCODING, TS_MIME_LEN_ACCEPT_ENCODING);
-    TSHandleMLocRelease(reqp, hdr_loc, field);
-    field = tmp;
-  }
-}
-
-const char *
-init_hidden_header_name()
-{
-  char * hidden_header_name;
-  const char *var_name = "proxy.config.proxy_name";
-  TSMgmtString result;
-
-  if (TSMgmtStringGet(var_name, &result) != TS_SUCCESS) {
-    fatal("failed to get server name");
-  } else {
-    int hidden_header_name_len = strlen("x-accept-encoding-") + strlen(result);
-    hidden_header_name = (char *) TSmalloc(hidden_header_name_len + 1);
-    hidden_header_name[hidden_header_name_len] = 0;
-    sprintf(hidden_header_name, "x-accept-encoding-%s", result);
-  }
-  return hidden_header_name;
-}
-
-int
-register_plugin()
-{
-  TSPluginRegistrationInfo info;
-
-  info.plugin_name = (char*)"gzip";
-  info.vendor_name = (char*)"Apache";
-  info.support_email = (char*)"dev@trafficserver.apache.org";
-
-  if (TSPluginRegister(TS_SDK_VERSION_3_0, &info) != TS_SUCCESS) {
-    return 0;
-  }
-  return 1;
-}
-
-const char *
-load_dictionary(const char *preload_file)
-{
-  char *dict = (char *) malloc(800000);
-  uLong dictId = adler32(0L, Z_NULL, 0);
-  uLong *adler = &dictId;
-
-  FILE *fp;
-  int i = 0;
-
-  fp = fopen(preload_file, "r");
-  if (!fp) {
-    fatal("gzip-transform: ERROR: Unable to open dict file %s", preload_file);
-  }
-
-  /* dict = (char *) calloc(8000, sizeof(char)); */
-
-  i = 0;
-  while (!feof(fp)) {
-    if (fscanf(fp, "%s\n", dict + i) == 1) {
-      i = strlen(dict);
-      strcat(dict + i, " ");
-      ++i;
-    }
-  }
-  dict[i - 1] = '\0';
-
-  /* TODO get the adler compute right */
-  *adler = adler32(*adler, (const Byte *) dict, sizeof(dict));
-  return dict;
-}
-
-void
-gzip_log_ratio(int64_t in, int64_t out)
-{
-  //  if (in) {
-  //  info("Compressed size %PRId64 (bytes), Original size %" PRId64", ratio: %f", out, in, ((float) (in - out) / in));
-  //} else {
-  //  debug("Compressed size %PRId64 (bytes), Original size %" PRId64", ratio: %f", out, in, 0.0F);
-  // }
-}

http://git-wip-us.apache.org/repos/asf/trafficserver/blob/e8b899b0/plugins/experimental/ats_speed/gzip/misc.h
----------------------------------------------------------------------
diff --git a/plugins/experimental/ats_speed/gzip/misc.h b/plugins/experimental/ats_speed/gzip/misc.h
deleted file mode 100644
index c44fb6b..0000000
--- a/plugins/experimental/ats_speed/gzip/misc.h
+++ /dev/null
@@ -1,84 +0,0 @@
-/** @file
-
-  Transforms content using gzip or deflate
-
-  @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 _GZIP_MISC_H_
-#define _GZIP_MISC_H_
-
-#define __STDC_LIMIT_MACROS
-#define __STDC_CONSTANT_MACROS
-#include <stdint.h>
-#include <zlib.h>
-#include <ts/ts.h>
-#include <stdlib.h>             //exit()
-#include <stdio.h>
-
-//zlib stuff, see [deflateInit2] at http://www.zlib.net/manual.html
-static const int ZLIB_MEMLEVEL = 9;     //min=1 (optimize for memory),max=9 (optimized for speed)
-static const int WINDOW_BITS_DEFLATE = -15;
-static const int WINDOW_BITS_GZIP = 31;
-
-//misc
-static const int COMPRESSION_TYPE_DEFLATE = 1;
-static const int COMPRESSION_TYPE_GZIP = 2;
-//this one is just for txnargset/get to point to
-static const int GZIP_ONE = 1;
-static const int DICT_PATH_MAX = 512;
-static const int DICT_ENTRY_MAX = 2048;
-
-//this one is used to rename the accept encoding header
-//it will be restored later on
-//to make it work, the name must be different then downstream proxies though
-//otherwise the downstream will restore the accept encoding header
-
-enum transform_state
-{
-  transform_state_initialized,
-  transform_state_output,
-  transform_state_finished
-};
-
-typedef struct
-{
-  TSHttpTxn txn;
-  TSVIO downstream_vio;
-  TSIOBuffer downstream_buffer;
-  TSIOBufferReader downstream_reader;
-  int downstream_length;
-  z_stream zstrm;
-  enum transform_state state;
-  int compression_type;
-} GzipData;
-
-
-voidpf gzip_alloc(voidpf opaque, uInt items, uInt size);
-void gzip_free(voidpf opaque, voidpf address);
-void normalize_accept_encoding(TSHttpTxn txnp, TSMBuffer reqp, TSMLoc hdr_loc);
-void hide_accept_encoding(TSHttpTxn txnp, TSMBuffer reqp, TSMLoc hdr_loc, const char * hidden_header_name);
-void restore_accept_encoding(TSHttpTxn txnp, TSMBuffer reqp, TSMLoc hdr_loc, const char * hidden_header_name);
-const char * init_hidden_header_name();
-int check_ts_version();
-int register_plugin();
-const char *load_dictionary(const char *preload_file);
-void gzip_log_ratio(int64_t in, int64_t out);
-
-#endif

http://git-wip-us.apache.org/repos/asf/trafficserver/blob/e8b899b0/plugins/experimental/ats_speed/scripts/prepare_psol.sh
----------------------------------------------------------------------
diff --git a/plugins/experimental/ats_speed/scripts/prepare_psol.sh b/plugins/experimental/ats_speed/scripts/prepare_psol.sh
deleted file mode 100755
index f265011..0000000
--- a/plugins/experimental/ats_speed/scripts/prepare_psol.sh
+++ /dev/null
@@ -1,93 +0,0 @@
-#!/bin/bash
-#
-# 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.
-#
-# Author: jefftk@google.com (Jeff Kaufman)
-# Author: oschaaf@we-amp.com (Otto van der Schaaf)
-#
-# Usage:
-#   scripts/prepare_psol.sh /path/to/mod_pagespeed/src
-#
-# Creates a directory psol/ and copies headers and a few source files from a
-# depot_tools (glient) checkout into psol/include.  Along with creating
-# binaries, this is a step in preparing psol.tar.gz for distribution.
-#
-
-set -u  # check for undefined variables
-set -e  # exit on failed commands
-
-if [ "$(basename "$PWD")" != "ats_speed" ] ; then
-  echo "$(basename $0) must be invoked from the ats_speed directory"
-  exit 1
-fi
-
-if [ $# -ne 1 ] ; then
-  echo "Usage: $(basename $0) /path/to/mod_pagespeed/src"
-  exit 1
-fi
-
-MOD_PAGESPEED_SRC="$1"
-
-if [ "$(basename "$(dirname "$MOD_PAGESPEED_SRC")")/$( \
-        basename "$MOD_PAGESPEED_SRC")" != "mod_pagespeed/src" ] ; then
-  echo "Usage: $(basename $0) /path/to/mod_pagespeed/src"
-  exit 1
-fi
-
-if [ -e psol ] ; then
-  echo "A psol/ directory already exists.  Move it somewhere else and rerun."
-  exit 1
-fi
-mkdir psol/
-# Copy over the .h files, plus a few selected .cc and .c files.
-rsync -arvz "$MOD_PAGESPEED_SRC/" "psol/include/" --prune-empty-dirs \
-  --exclude=".svn" \
-  --exclude=".git" \
-  --include='*.h' \
-  --include='*/' \
-  --include="apr_thread_compatible_pool.cc" \
-  --include="serf_url_async_fetcher.cc" \
-  --include="apr_mem_cache.cc" \
-  --include="key_value_codec.cc" \
-  --include="apr_memcache2.c" \
-  --include="loopback_route_fetcher.cc" \
-  --include="add_headers_fetcher.cc" \
-  --include="console_css_out.cc" \
-  --include="console_out.cc" \
-  --include="dense_hash_map" \
-  --include="dense_hash_set" \
-  --include="sparse_hash_map" \
-  --include="sparse_hash_set" \
-  --include="sparsetable" \
-  --include="mod_pagespeed_console_out.cc" \
-  --include="mod_pagespeed_console_css_out.cc" \
-  --include="mod_pagespeed_console_html_out.cc" \
-  --exclude='*'
-mkdir -p psol/lib/Debug/linux/ia32
-mkdir -p psol/lib/Debug/linux/x64
-mkdir -p psol/lib/Release/linux/ia32
-mkdir -p psol/lib/Release/linux/x64
-
-# Log that we did this.
-SVN_REVISION="$(svn info $MOD_PAGESPEED_SRC | grep Revision | awk '{print $2}')"
-SVN_TAG="$(svn info $MOD_PAGESPEED_SRC | grep URL |  awk -F/ '{print $(NF-1)}')"
-
-DATE="$(date +%F)"
-echo "${DATE}: Copied from mod_pagespeed ${SVN_TAG}@r${SVN_REVISION} ($USER)" \
-  >> psol/include_history.txt
-
-echo
-echo "Output is in psol/include.  Now put binaries in psol/lib following"
-echo "https://github.com/pagespeed/ngx_pagespeed/wiki/Building-Release-Binaries"
-echo "and then you can distribute PSOL."
-


[3/6] ats_pagespeed: rename ats_speed -> ats_pagespeed

Posted by am...@apache.org.
http://git-wip-us.apache.org/repos/asf/trafficserver/blob/e8b899b0/plugins/experimental/ats_speed/ats_beacon_intercept.cc
----------------------------------------------------------------------
diff --git a/plugins/experimental/ats_speed/ats_beacon_intercept.cc b/plugins/experimental/ats_speed/ats_beacon_intercept.cc
deleted file mode 100644
index 9b14244..0000000
--- a/plugins/experimental/ats_speed/ats_beacon_intercept.cc
+++ /dev/null
@@ -1,364 +0,0 @@
-/** @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.
-*/
-
-#include "ats_beacon_intercept.h"
-#include "ats_speed.h"
-#include "ats_server_context.h"
-
-#include "net/instaweb/system/public/system_request_context.h"
-
-#include <string>
-#include <limits.h>
-#include <strings.h>
-#include <stdio.h>
-
-using std::string;
-using namespace net_instaweb;
-
-#define DEBUG_TAG "ats_speed_beacon"
-
-struct InterceptCtx {
-  TSVConn net_vc;
-  TSCont contp;
-
-  struct IoHandle {
-    TSVIO vio;
-    TSIOBuffer buffer;
-    TSIOBufferReader reader;
-    IoHandle()
-      : vio(0), buffer(0), reader(0) { };
-    ~IoHandle() {
-      if (reader) {
-        TSIOBufferReaderFree(reader);
-      }
-      if (buffer) {
-        TSIOBufferDestroy(buffer);
-      }
-    };
-  };
-
-  IoHandle input;
-  IoHandle output;
-
-  TSHttpParser http_parser;
-  string body;
-  int req_content_len;
-  TSMBuffer req_hdr_bufp;
-  TSMLoc req_hdr_loc;
-  bool req_hdr_parsed;
-  bool initialized;
-  TransformCtx* request_context;
-  InterceptCtx(TSCont cont) 
-    : net_vc(0), contp(cont), input(), output(), body(""), req_content_len(0), req_hdr_bufp(0), req_hdr_loc(0),
-      req_hdr_parsed(false), initialized(false) {
-    http_parser = TSHttpParserCreate();
-  }
-
-  bool init(TSVConn vconn);
-
-  void setupWrite();
-
-  ~InterceptCtx() {
-    TSDebug(DEBUG_TAG, "[%s] Destroying continuation data", __FUNCTION__);
-    TSHttpParserDestroy(http_parser); 
-    if (req_hdr_loc) {
-      TSHandleMLocRelease(req_hdr_bufp, TS_NULL_MLOC, req_hdr_loc);
-    }
-    if (req_hdr_bufp) {
-      TSMBufferDestroy(req_hdr_bufp);
-    }
-    if (request_context) {
-      ats_ctx_destroy(request_context);
-      request_context = NULL;
-    }
-  };
-};
-
-bool
-InterceptCtx::init(TSVConn vconn)
-{
-  if (initialized) {
-    TSError("[%s] InterceptCtx already initialized!", __FUNCTION__);
-    return false;
-  }
-  
-  net_vc = vconn;
-
-  input.buffer = TSIOBufferCreate();
-  input.reader = TSIOBufferReaderAlloc(input.buffer);
-  input.vio = TSVConnRead(net_vc, contp, input.buffer, INT_MAX);
-
-  req_hdr_bufp = TSMBufferCreate();
-  req_hdr_loc = TSHttpHdrCreate(req_hdr_bufp);
-  TSHttpHdrTypeSet(req_hdr_bufp, req_hdr_loc, TS_HTTP_TYPE_REQUEST);
-
-  initialized = true;
-  TSDebug(DEBUG_TAG, "[%s] InterceptCtx initialized!", __FUNCTION__);
-  return true;
-}
-
-void
-InterceptCtx::setupWrite() {
-  TSAssert(output.buffer == 0);
-  output.buffer = TSIOBufferCreate();
-  output.reader = TSIOBufferReaderAlloc(output.buffer);
-  output.vio = TSVConnWrite(net_vc, contp, output.reader, INT_MAX);
-}
-
-// Parses out query params from the request.
-void ps_query_params_handler(StringPiece unparsed_uri, StringPiece* data) {
-  stringpiece_ssize_type question_mark_index = unparsed_uri.find("?");
-  if (question_mark_index == StringPiece::npos) {
-    *data = "";
-  } else {
-    *data = unparsed_uri.substr(
-        question_mark_index+1, unparsed_uri.size() - (question_mark_index+1));
-  }
-}
-
-static bool
-handleRead(InterceptCtx *cont_data, bool &read_complete) {
-  int avail = TSIOBufferReaderAvail(cont_data->input.reader);
-  if (avail == TS_ERROR) {
-    TSError("[%s] Error while getting number of bytes available", __FUNCTION__);
-    return false;
-  }
-  
-  TSDebug(DEBUG_TAG, "[%s] Parsed header, avail: %d", __FUNCTION__, avail);
-
-  int consumed = 0;
-  if (avail > 0) {
-    int64_t data_len;
-    const char *data;
-    TSIOBufferBlock block = TSIOBufferReaderStart(cont_data->input.reader);
-    while (block != NULL) {
-      data = TSIOBufferBlockReadStart(block, cont_data->input.reader, &data_len);
-      if (!cont_data->req_hdr_parsed) {
-        const char *endptr = data + data_len;
-        if (TSHttpHdrParseReq(cont_data->http_parser, cont_data->req_hdr_bufp, cont_data->req_hdr_loc,
-                               &data, endptr) == TS_PARSE_DONE) {
-          TSDebug(DEBUG_TAG, "[%s] Parsed header", __FUNCTION__);
-          TSMLoc content_len_loc = TSMimeHdrFieldFind(cont_data->req_hdr_bufp, cont_data->req_hdr_loc,
-                                                        TS_MIME_FIELD_CONTENT_LENGTH, -1);
-          
-          /*if (!content_len_loc) {
-            TSError("[%s] Error while searching content length header [%s]",
-                     __FUNCTION__, TS_MIME_FIELD_CONTENT_LENGTH);
-            return false;
-          }
-          if (!content_len_loc) {
-            TSError("[%s] request doesn't contain content length header [%s]",
-                     __FUNCTION__, TS_MIME_FIELD_CONTENT_TYPE);
-            return false;
-            }*/
-          if (!content_len_loc) {
-            cont_data->req_content_len = 0;
-          } else {
-            cont_data->req_content_len = TSMimeHdrFieldValueIntGet(cont_data->req_hdr_bufp, cont_data->req_hdr_loc,
-                                         content_len_loc, 0);
-            TSHandleMLocRelease(cont_data->req_hdr_bufp, cont_data->req_hdr_loc, content_len_loc);
-          }
-          TSDebug(DEBUG_TAG, "[%s] Got content length as %d", __FUNCTION__, cont_data->req_content_len);
-          if (cont_data->req_content_len < 0) {
-            TSError("[%s] Invalid content length [%d]", __FUNCTION__, cont_data->req_content_len);
-            return false;
-          }
-          if (endptr - data) {
-            TSDebug(DEBUG_TAG, "[%s] Appending %ld bytes to body", __FUNCTION__, static_cast<long int>(endptr - data));
-            cont_data->body.append(data, endptr - data);
-          }
-          cont_data->req_hdr_parsed = true;
-        }
-      } else {
-        //TSDebug(DEBUG_TAG, "[%s] Appending %" PRId64" bytes to body", __FUNCTION__, data_len);
-        cont_data->body.append(data, data_len);
-      }
-      consumed += data_len;
-      block = TSIOBufferBlockNext(block);
-    }
-  }
-  
-  TSIOBufferReaderConsume(cont_data->input.reader, consumed);
-
-  TSDebug(DEBUG_TAG, "[%s] Consumed %d bytes from input vio, avail: %d", __FUNCTION__, consumed, avail);
-  
-  // Modify the input VIO to reflect how much data we've completed.
-  TSVIONDoneSet(cont_data->input.vio, TSVIONDoneGet(cont_data->input.vio) + consumed);
-
-  if (static_cast<int>(cont_data->body.size()) == cont_data->req_content_len) {
-    TSDebug(DEBUG_TAG, "[%s] Completely read body of size %d", __FUNCTION__, cont_data->req_content_len);
-    read_complete = true;
-  } else {
-    read_complete = false;
-    TSDebug(DEBUG_TAG, "[%s] Reenabling input vio as %ld bytes still need to be read",
-             __FUNCTION__, static_cast<long int>(cont_data->req_content_len - cont_data->body.size()));
-    TSVIOReenable(cont_data->input.vio);
-  }
-  return true;
-}
-
-static bool
-processRequest(InterceptCtx *cont_data) {
-  // OS: Looks like on 5.x we sometimes receive read complete / EOS events twice,
-  // which needs looking into. Probably this intercept is doing something it shouldn't
-  if (cont_data->output.buffer) { 
-    TSDebug("ats_speed", "Received read complete / EOS twice?!");
-    return true;
-  }
-  string reply_header("HTTP/1.1 204 No Content\r\n");
-  int body_size = static_cast<int>(cont_data->body.size());
-  if (cont_data->req_content_len != body_size) {
-    TSError("[%s] Read only %d bytes of body; expecting %d bytes", __FUNCTION__, body_size,
-             cont_data->req_content_len);
-  }
-
-  char buf[64];
-  //snprintf(buf, 64, "%s: %d\r\n\r\n", TS_MIME_FIELD_CONTENT_LENGTH, body_size);
-  snprintf(buf, 64, "%s: %d\r\n\r\n", TS_MIME_FIELD_CONTENT_LENGTH, 0);
-  reply_header.append(buf);
-  reply_header.append("Cache-Control: max-age=0, no-cache");
-  //TSError("[%s] reply header: \n%s", __FUNCTION__, reply_header.data());
-
-  StringPiece query_param_beacon_data;
-  ps_query_params_handler(cont_data->request_context->url_string->c_str(), &query_param_beacon_data);
-  
-  GoogleString beacon_data = net_instaweb::StrCat(
-      query_param_beacon_data, "&", cont_data->body);
-  ServerContext* server_context = cont_data->request_context->server_context;
-  
-  SystemRequestContext* system_request_context = 
-      new SystemRequestContext(server_context->thread_system()->NewMutex(),
-                               server_context->timer(),
-			       // TODO(oschaaf): determine these for real.
-			       "www.foo.com",
-                               80,
-                               "127.0.0.1");
-  
-  if (!server_context->HandleBeacon(
-          beacon_data,
-            cont_data->request_context->user_agent->c_str(),
-          net_instaweb::RequestContextPtr(system_request_context))) {
-    TSError("Beacon handling failure!");
-  } else {
-    TSDebug(DEBUG_TAG,  "Beacon post data processed OK: [%s]", beacon_data.c_str());
-  }
-  
-  cont_data->setupWrite();
-  if (TSIOBufferWrite(cont_data->output.buffer, reply_header.data(), reply_header.size()) == TS_ERROR) {
-    TSError("[%s] Error while writing reply header", __FUNCTION__);
-    return false;
-  }
-  /*
-  if (TSIOBufferWrite(cont_data->output.buffer, cont_data->body.data(), body_size) == TS_ERROR) {
-    TSError("[%s] Error while writing content", __FUNCTION__);
-    return false;
-    }*/
-  int total_bytes_written = reply_header.size() + body_size;
-  TSDebug(DEBUG_TAG, "[%s] Wrote reply of size %d", __FUNCTION__, total_bytes_written);
-  TSVIONBytesSet(cont_data->output.vio, total_bytes_written);
-  
-  TSVIOReenable(cont_data->output.vio);
-  return true;
-}
-
-static int
-txn_intercept(TSCont contp, TSEvent event, void *edata) {
-    TSDebug(DEBUG_TAG, "[%s] Received event: %d", __FUNCTION__, (int)event);
-
-  InterceptCtx *cont_data = static_cast<InterceptCtx *>(TSContDataGet(contp));
-  bool read_complete = false;
-  bool shutdown = false;
-  switch (event) {
-  case TS_EVENT_NET_ACCEPT:
-    TSDebug(DEBUG_TAG, "[%s] Received net accept event", __FUNCTION__);
-    TSAssert(cont_data->initialized == false);
-    if (!cont_data->init(static_cast<TSVConn>(edata))) {
-      TSError("[%s] Could not initialize continuation data!", __FUNCTION__);
-      return 1;
-    }
-    break;
-  case TS_EVENT_VCONN_READ_READY:
-    TSDebug(DEBUG_TAG, "[%s] Received read ready event", __FUNCTION__);
-    if (!handleRead(cont_data, read_complete)) {
-      TSError("[%s] Error while reading from input vio", __FUNCTION__);
-      //return 0;
-      read_complete = true;
-    }
-    break;
-  case TS_EVENT_VCONN_READ_COMPLETE:
-  case TS_EVENT_VCONN_EOS:
-    // intentional fall-through
-    TSDebug(DEBUG_TAG, "[%s] Received read complete/eos event %d", __FUNCTION__, event);
-    read_complete = true;
-    break;
-  case TS_EVENT_VCONN_WRITE_READY:
-    TSDebug(DEBUG_TAG, "[%s] Received write ready event", __FUNCTION__);
-    break;
-  case TS_EVENT_VCONN_WRITE_COMPLETE:
-    TSDebug(DEBUG_TAG, "[%s] Received write complete event", __FUNCTION__);
-    shutdown = true;
-    break;
-  case TS_EVENT_ERROR:
-    // todo: do some error handling here
-    TSDebug(DEBUG_TAG, "[%s] Received error event; going to shutdown, event: %d", __FUNCTION__, event);    
-    TSError("[%s] Received error event; going to shutdown, event: %d", __FUNCTION__, event);
-    shutdown = true;
-    break;
-  default:
-    break;
-  }
-
-  if (read_complete) {
-    if (!processRequest(cont_data)) {
-      TSError("[%s] Failed to process process", __FUNCTION__);
-    } else {
-      TSDebug(DEBUG_TAG, "[%s] Processed request successfully", __FUNCTION__);
-    }
-  }
-
-  if (shutdown) {
-    TSDebug(DEBUG_TAG, "[%s] Completed request processing. Shutting down...", __FUNCTION__);
-    if (cont_data->net_vc) {
-      TSVConnClose(cont_data->net_vc);
-    }
-    delete cont_data;
-    TSContDestroy(contp);
-  } 
-
-  return 1;
-}
-
-bool
-hook_beacon_intercept(TSHttpTxn txnp) {
-  TSCont contp = TSContCreate(txn_intercept, TSMutexCreate());
-  if (!contp) {
-    TSError("[%s] Could not create intercept request", __FUNCTION__);
-    return false;
-  }
-  InterceptCtx *cont_data = new InterceptCtx(contp);
-  cont_data->request_context = get_transaction_context(txnp);
-  TSContDataSet(contp, cont_data);
-  TSHttpTxnIntercept(contp, txnp);
-  TSDebug(DEBUG_TAG, "[%s] Setup server intercept successfully", __FUNCTION__);
-  return true;
-}

http://git-wip-us.apache.org/repos/asf/trafficserver/blob/e8b899b0/plugins/experimental/ats_speed/ats_beacon_intercept.h
----------------------------------------------------------------------
diff --git a/plugins/experimental/ats_speed/ats_beacon_intercept.h b/plugins/experimental/ats_speed/ats_beacon_intercept.h
deleted file mode 100644
index d53d81c..0000000
--- a/plugins/experimental/ats_speed/ats_beacon_intercept.h
+++ /dev/null
@@ -1,31 +0,0 @@
-/** @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.
-*/
-
-#ifndef _ATS_BEACON_INTERCEPT_H
-#define _ATS_BEACON_INTERCEPT_H
-
-#include "ts/ts.h"
-
-bool hook_beacon_intercept(TSHttpTxn txnp);
-
-#endif

http://git-wip-us.apache.org/repos/asf/trafficserver/blob/e8b899b0/plugins/experimental/ats_speed/ats_config.cc
----------------------------------------------------------------------
diff --git a/plugins/experimental/ats_speed/ats_config.cc b/plugins/experimental/ats_speed/ats_config.cc
deleted file mode 100644
index e0adf42..0000000
--- a/plugins/experimental/ats_speed/ats_config.cc
+++ /dev/null
@@ -1,204 +0,0 @@
-/** @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.
-*/
-
-#include "ats_config.h"
-
-#include <ts/ts.h>
-#include <fstream>
-
-#include "net/instaweb/util/public/string_util.h"
-
-#include "ats_message_handler.h"
-#include "ats_rewrite_options.h"
-
-namespace net_instaweb {
-
-using namespace std;
-
-
-
-void ltrim_if(string& s, int (* fp) (int)) {
-  for (size_t i = 0; i < s.size();) {
-    if (fp(s[i])) {
-      s.erase(i,1);
-    } else  {
-      break;
-    }
-  }
-}
-
-void rtrim_if(string& s, int (* fp) (int)) {
-  for (ssize_t i = (ssize_t)s.size() - 1; i >= 0; i--) {
-    if (fp(s[i])) {
-      s.erase(i,1);
-    } else  {
-      break;
-    }
-  }
-}
-
-void trim_if(string& s, int (* fp) (int)) {
-  ltrim_if(s, fp);
-  rtrim_if(s, fp);
-}
-
-vector<string> tokenize(const string &s, int (* fp) (int)) {
-  vector<string> r;
-  string tmp;
-
-  for (size_t i = 0; i < s.size(); i++) {
-    if ( fp(s[i]) ) {
-      if ( tmp.size()  ) {
-        r.push_back(tmp);
-        tmp = "";
-      }
-    } else {
-      tmp += s[i];
-    }
-  }
-
-  if ( tmp.size()  ) {
-    r.push_back(tmp);
-  }
-
-  return r;
-}
-
-AtsConfig::AtsConfig(AtsThreadSystem* thread_system)
-      : thread_system_(thread_system) {
-  AddHostConfig(new AtsHostConfig(GoogleString("(XXXXXX)"), new AtsRewriteOptions(thread_system_)));
-}
-
-AtsConfig::~AtsConfig() {
-  for (size_t i = 0; i < host_configurations_.size(); i++) {
-    delete host_configurations_[i];
-    host_configurations_.clear();
-  }
-}
-
-void AtsConfig::AddHostConfig(AtsHostConfig* hc){
-  host_configurations_.push_back(hc);
-}
-
-AtsHostConfig::~AtsHostConfig() {
-  if (options_ != NULL) {
-    delete options_;
-    options_ = NULL;
-  }
-}
-
-AtsHostConfig * AtsConfig::Find(const char * host, int host_length) {
-  AtsHostConfig * host_configuration = host_configurations_[0];
-
-  std::string shost(host, host_length);
-
-  for (size_t i = 1; i < host_configurations_.size(); i++ ) {
-    if (host_configurations_[i]->host() == shost){
-      host_configuration = host_configurations_[i];
-      break;
-    }
-  }
-
-  return host_configuration;
-}
-
-bool AtsConfig::Parse(const char * path ) {
-  string pathstring(path);
-
-  // If we have a path and it's not an absolute path, make it relative to the
-  // configuration directory.
-  if (!pathstring.empty() && pathstring[0] != '/') {
-    pathstring.assign(TSConfigDirGet());
-    pathstring.append("/");
-    pathstring.append(path);
-  }
-
-  trim_if(pathstring, isspace);
-
-  AtsHostConfig* current_host_configuration = host_configurations_[0];
-
-  if (pathstring.empty())  {
-    TSError("Empty path passed in AtsConfig::Parse");
-    return false;
-  }
-
-  path = pathstring.c_str();
-  std::ifstream f;
-
-  size_t lineno = 0;
-
-  f.open(path, std::ios::in);
-
-  if (!f.is_open()) {
-    TSError("could not open file [%s], skip",path);
-    return false;
-  }
-
-
-  while (!f.eof()) {
-    std::string line;
-    getline(f, line);
-    ++lineno;
-
-    trim_if(line, isspace);
-    if (line.size() == 0) {
-      continue;
-    }
-    if (line[0] == '#') {
-      continue;
-    }
-    
-    vector<string> v = tokenize( line, isspace );
-    if (v.size() == 0)
-      continue;
-    GoogleString msg;
-    AtsMessageHandler handler(thread_system_->NewMutex());
-    if (v.size() == 1) {
-      string token = v[0];
-      if ((token[0] == '[') && (token[token.size()-1] == ']')) {
-        GoogleString current_host = token.substr(1, token.size() - 2);
-        current_host_configuration = new AtsHostConfig(current_host, new AtsRewriteOptions(thread_system_));
-        AddHostConfig(current_host_configuration);
-      } else if (StringCaseEqual(token,"override_expiry")) {
-        current_host_configuration->set_override_expiry(true);
-      } else {
-        msg = "unknown single token on a line";
-      }
-    } else {
-      global_settings settings;
-      v.erase (v.begin());
-      const char* err = current_host_configuration->options()->ParseAndSetOptions(v, &handler, settings);
-      if (err) {
-        msg.append(err);
-      }
-    }
-    if (msg.size() > 0) {
-      TSDebug("ats-speed", "Error parsing line [%s]: [%s]", line.c_str(), msg.c_str());
-    }
-  }
-
-  return true;
-}
-
-
-} //  namespace net_instaweb

http://git-wip-us.apache.org/repos/asf/trafficserver/blob/e8b899b0/plugins/experimental/ats_speed/ats_config.h
----------------------------------------------------------------------
diff --git a/plugins/experimental/ats_speed/ats_config.h b/plugins/experimental/ats_speed/ats_config.h
deleted file mode 100644
index d3b0e40..0000000
--- a/plugins/experimental/ats_speed/ats_config.h
+++ /dev/null
@@ -1,90 +0,0 @@
-/** @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.
-*/
-
-#ifndef ATS_CONFIG_H_
-#define ATS_CONFIG_H_
-
-#include <string>
-#include <vector>
-
-#include <ts/ts.h>
-
-#include "ats_thread_system.h"
-
-#include "net/instaweb/util/public/string.h"
-#include "net/instaweb/util/public/string_util.h"
-
-
-namespace net_instaweb {
-
-class AtsRewriteOptions;
-
-class AtsHostConfig {
-public:
-  explicit AtsHostConfig(const GoogleString & host, AtsRewriteOptions* options)
-      : host_(host)
-      , options_(options)
-  {
-  }
-  virtual ~AtsHostConfig();
-
-  inline GoogleString host() { return host_; }
-  inline AtsRewriteOptions* options() { return options_; }
-  inline bool override_expiry() { return override_expiry_; }
-  inline void set_override_expiry(bool x) { override_expiry_ = x; }
-private:
-  GoogleString host_;
-  AtsRewriteOptions* options_;
-  bool override_expiry_;
-  DISALLOW_COPY_AND_ASSIGN(AtsHostConfig);
-}; // class AtsHostConfig
-
-class AtsConfig {
-  friend class AtsHostConfig;
-public:
-  explicit AtsConfig(AtsThreadSystem* thread_system);
-  virtual ~AtsConfig();
-  
-  // TODO(oschaaf): destructor??
-  bool Parse(const char * path);
-  AtsHostConfig * Find(const char * host, int host_length);
-  inline AtsHostConfig * GlobalConfiguration() {
-    return host_configurations_[0];
-  }
-  AtsThreadSystem* thread_system() {
-    return thread_system_;
-  }
-
-private:
-  void AddHostConfig(AtsHostConfig* hc);
-
-  std::vector<AtsHostConfig *> host_configurations_;
-  AtsThreadSystem* thread_system_;
-  //todo: destructor. delete owned host configurations
-  DISALLOW_COPY_AND_ASSIGN(AtsConfig);
-}; // class Configuration
-
-
-}  // namespace net_instaweb
-
-#endif  // ATS_CONFIG_H

http://git-wip-us.apache.org/repos/asf/trafficserver/blob/e8b899b0/plugins/experimental/ats_speed/ats_header_utils.cc
----------------------------------------------------------------------
diff --git a/plugins/experimental/ats_speed/ats_header_utils.cc b/plugins/experimental/ats_speed/ats_header_utils.cc
deleted file mode 100644
index a61c784..0000000
--- a/plugins/experimental/ats_speed/ats_header_utils.cc
+++ /dev/null
@@ -1,96 +0,0 @@
-/** @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.
-*/
-
-#include "ats_header_utils.h"
-
-GoogleString get_header(TSMBuffer bufp, TSMLoc hdr_loc, const char * header_name)
-{
-  const char * val = NULL;
-  int val_len;
-  TSMLoc field_loc = TSMimeHdrFieldFind( bufp, hdr_loc, header_name, -1);
-
-  if (field_loc) {
-    val = TSMimeHdrFieldValueStringGet (bufp, hdr_loc, field_loc, 0, &val_len);
-    TSHandleMLocRelease(bufp,hdr_loc,field_loc);
-    return GoogleString(val,val_len);
-  }
-
-  return GoogleString("");
-}
-
-void unset_header(TSMBuffer bufp, TSMLoc hdr_loc, const char * header_name)
-{
-  TSMLoc field_loc = TSMimeHdrFieldFind( bufp, hdr_loc, header_name, -1);
-
-  if (field_loc) {
-    TSMimeHdrFieldDestroy(bufp, hdr_loc, field_loc);
-    TSHandleMLocRelease(bufp, hdr_loc, field_loc);
-  }
-}
-
-void hide_accept_encoding(TSMBuffer reqp, TSMLoc hdr_loc, const char * hidden_header_name)
-{
-  TSMLoc field = TSMimeHdrFieldFind(reqp, hdr_loc, TS_MIME_FIELD_ACCEPT_ENCODING, TS_MIME_LEN_ACCEPT_ENCODING);
-  while (field) {
-    TSMLoc tmp;
-    tmp = TSMimeHdrFieldNextDup(reqp, hdr_loc, field);
-    TSMimeHdrFieldNameSet(reqp, hdr_loc, field, hidden_header_name, -1);
-    TSHandleMLocRelease(reqp, hdr_loc, field);
-    field = tmp;
-  }
-}
-
-void restore_accept_encoding(TSMBuffer reqp, TSMLoc hdr_loc, const char * hidden_header_name)
-{
-  TSMLoc field = TSMimeHdrFieldFind(reqp, hdr_loc, hidden_header_name, -1);
-
-  while (field) {
-    TSMLoc tmp;
-    tmp = TSMimeHdrFieldNextDup(reqp, hdr_loc, field);
-    TSMimeHdrFieldNameSet(reqp, hdr_loc, field, TS_MIME_FIELD_ACCEPT_ENCODING, TS_MIME_LEN_ACCEPT_ENCODING);
-    TSHandleMLocRelease(reqp, hdr_loc, field);
-    field = tmp;
-  }
-}
-
-void set_header(TSMBuffer bufp, TSMLoc hdr_loc, const char * header_name, const char * header_value)
-{
-  TSMLoc field_loc = TSMimeHdrFieldFind( bufp, hdr_loc, header_name, -1);
-
-  if (field_loc) {
-    TSMimeHdrFieldValueStringSet(bufp, hdr_loc, field_loc, -1, header_value, -1);
-  } else {    
-    if ( TSMimeHdrFieldCreate(bufp, hdr_loc, &field_loc) == TS_SUCCESS ) {
-      TSMimeHdrFieldNameSet(bufp, hdr_loc, field_loc, header_name, -1);
-      TSMimeHdrFieldAppend(bufp, hdr_loc, field_loc);
-      TSMimeHdrFieldValueStringSet(bufp,hdr_loc,field_loc,-1,header_value,-1);
-    } else {
-      TSError("field creation error for field [%s]", header_name);
-      return;
-    }
-  }
-
-  if (field_loc) {
-    TSHandleMLocRelease(bufp,hdr_loc,field_loc);
-  }
-}

http://git-wip-us.apache.org/repos/asf/trafficserver/blob/e8b899b0/plugins/experimental/ats_speed/ats_header_utils.h
----------------------------------------------------------------------
diff --git a/plugins/experimental/ats_speed/ats_header_utils.h b/plugins/experimental/ats_speed/ats_header_utils.h
deleted file mode 100644
index 1d6c567..0000000
--- a/plugins/experimental/ats_speed/ats_header_utils.h
+++ /dev/null
@@ -1,41 +0,0 @@
-/** @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.
-*/
-
-#ifndef ATS_HEADER_UTILS_H
-#define ATS_HEADER_UTILS_H
-
-#include <string>
-
-#include <ts/ts.h>
-
-#include "net/instaweb/util/public/string.h"
-#include "net/instaweb/util/public/string_util.h"
-
-
-GoogleString get_header(TSMBuffer bufp, TSMLoc hdr_loc, const char * header_name);
-void unset_header(TSMBuffer bufp, TSMLoc hdr_loc, const char * header_name);
-void hide_accept_encoding(TSMBuffer reqp, TSMLoc hdr_loc, const char * hidden_header_name);
-void restore_accept_encoding(TSMBuffer reqp, TSMLoc hdr_loc, const char * hidden_header_name);
-void set_header(TSMBuffer bufp, TSMLoc hdr_loc, const char * header_name, const char * header_value);
-
-#endif //  ATS_HEADER_UTILS_H

http://git-wip-us.apache.org/repos/asf/trafficserver/blob/e8b899b0/plugins/experimental/ats_speed/ats_log_message_handler.cc
----------------------------------------------------------------------
diff --git a/plugins/experimental/ats_speed/ats_log_message_handler.cc b/plugins/experimental/ats_speed/ats_log_message_handler.cc
deleted file mode 100644
index f41b9cc..0000000
--- a/plugins/experimental/ats_speed/ats_log_message_handler.cc
+++ /dev/null
@@ -1,101 +0,0 @@
-/** @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.
-*/
-
-#include "ats_log_message_handler.h"
-
-#include <ts/ts.h>
-
-#include <unistd.h>
-
-#include <limits>
-#include <string>
-
-#include "base/debug/debugger.h"
-#include "base/debug/stack_trace.h"
-#include "base/logging.h"
-#include "net/instaweb/public/version.h"
-#include "net/instaweb/util/public/string_util.h"
-
-// Make sure we don't attempt to use LOG macros here, since doing so
-// would cause us to go into an infinite log loop.
-#undef LOG
-#define LOG USING_LOG_HERE_WOULD_CAUSE_INFINITE_RECURSION
-
-namespace {
-
-bool LogMessageHandler(int severity, const char* file, int line,
-                       size_t message_start, const GoogleString& str) {
-  GoogleString message = str;
-  if (severity == logging::LOG_FATAL) {
-    if (base::debug::BeingDebugged()) {
-      base::debug::BreakDebugger();
-    } else {
-      base::debug::StackTrace trace;
-      std::ostringstream stream;
-      trace.OutputToStream(&stream);
-      message.append(stream.str());
-    }
-  }
-
-  // Trim the newline off the end of the message string.
-  size_t last_msg_character_index = message.length() - 1;
-  if (message[last_msg_character_index] == '\n') {
-    message.resize(last_msg_character_index);
-  }
-
-  TSDebug("ats-speed-vlog", "[%s] %s",
-                net_instaweb::kModPagespeedVersion,
-                message.c_str());
-
-  if (severity == logging::LOG_FATAL) {
-    // Crash the process to generate a dump.
-    base::debug::BreakDebugger();
-  }
-
-  return true;
-}
-
-}  // namespace
-
-
-namespace net_instaweb {
-
-namespace log_message_handler {
-
-
-const int kDebugLogLevel = -2;
-
-void Install() {
-  logging::SetLogMessageHandler(&LogMessageHandler);
-
-  // All VLOG(2) and higher will be displayed as DEBUG logs if the nginx log
-  // level is DEBUG.
-  // TODO(oschaaf): from config
-  //if (log->log_level >= NGX_LOG_DEBUG) {
-    logging::SetMinLogLevel(-2);
-  //}
-}
-
-}  // namespace log_message_handler
-
-}  // namespace net_instaweb

http://git-wip-us.apache.org/repos/asf/trafficserver/blob/e8b899b0/plugins/experimental/ats_speed/ats_log_message_handler.h
----------------------------------------------------------------------
diff --git a/plugins/experimental/ats_speed/ats_log_message_handler.h b/plugins/experimental/ats_speed/ats_log_message_handler.h
deleted file mode 100644
index bf57634..0000000
--- a/plugins/experimental/ats_speed/ats_log_message_handler.h
+++ /dev/null
@@ -1,36 +0,0 @@
-/** @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.
-*/
-
-#ifndef ATS_LOG_MESSAGE_HANDLER_H_
-#define ATS_LOG_MESSAGE_HANDLER_H_
-
-
-namespace net_instaweb {
-
-  namespace log_message_handler {
-    void Install();
-  }  // namespace log_message_handler
-
-}  // namespace net_instaweb
-
-#endif  // ATS_LOG_MESSAGE_HANDLER_H_

http://git-wip-us.apache.org/repos/asf/trafficserver/blob/e8b899b0/plugins/experimental/ats_speed/ats_message_handler.cc
----------------------------------------------------------------------
diff --git a/plugins/experimental/ats_speed/ats_message_handler.cc b/plugins/experimental/ats_speed/ats_message_handler.cc
deleted file mode 100644
index 370f317..0000000
--- a/plugins/experimental/ats_speed/ats_message_handler.cc
+++ /dev/null
@@ -1,114 +0,0 @@
-/** @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.
-*/
-
-#include "ats_message_handler.h"
-
-#include <signal.h>
-#include <unistd.h>
-
-#include "net/instaweb/util/public/abstract_mutex.h"
-#include "net/instaweb/util/public/debug.h"
-#include "net/instaweb/util/public/shared_circular_buffer.h"
-#include "net/instaweb/util/public/string_util.h"
-#include "net/instaweb/public/version.h"
-#include "pagespeed/kernel/base/posix_timer.h"
-#include "pagespeed/kernel/base/time_util.h"
-   
-
-namespace {
-
-// This will be prefixed to every logged message.
-const char kModuleName[] = "ats_pagespeed";
-
-}  // namespace
-
-namespace net_instaweb {
-
-AtsMessageHandler::AtsMessageHandler(AbstractMutex* mutex)
-    : mutex_(mutex),
-      buffer_(NULL) {
-  SetPidString(static_cast<int64>(getpid()));
-}
-
-
-bool AtsMessageHandler::Dump(Writer* writer) {
-  // Can't dump before SharedCircularBuffer is set up.
-  if (buffer_ == NULL) {
-    return false;
-  }
-  return buffer_->Dump(writer, &handler_);
-}
-
-void AtsMessageHandler::set_buffer(SharedCircularBuffer* buff) {
-  ScopedMutex lock(mutex_.get());
-  buffer_ = buff;
-}
-
-void AtsMessageHandler::MessageVImpl(MessageType type, const char* msg,
-                                     va_list args) {
-  GoogleString formatted_message = Format(msg, args);
-  
-  TSDebug("ats-speed", "[%s %s] %s", kModuleName, kModPagespeedVersion,
-          formatted_message.c_str());
- 
-  // Prepare a log message for the SharedCircularBuffer only.
-  // Prepend time and severity to message.
-  // Format is [time] [severity] [pid] message.
-  GoogleString message;
-  GoogleString time;
-  PosixTimer timer;
-  if (!ConvertTimeToString(timer.NowMs(), &time)) {
-    time = "?";
-  }
-  
-  StrAppend(&message, "[", time, "] ",
-            "[", MessageTypeToString(type), "] ");
-  StrAppend(&message, pid_string_, " ", formatted_message, "\n");
-  {
-    ScopedMutex lock(mutex_.get());
-    if (buffer_ != NULL) {
-      buffer_->Write(message);
-    }
-  }
-}
-
-void AtsMessageHandler::FileMessageVImpl(MessageType type, const char* file,
-                                         int line, const char* msg,
-                                         va_list args) {
-  GoogleString formatted_message = Format(msg, args);
-  TSDebug("ats-speed", "[%s %s] %s:%d:%s",
-                kModuleName, kModPagespeedVersion, file, line,
-                formatted_message.c_str());
-}
-
-// TODO(sligocki): It'd be nice not to do so much string copying.
-GoogleString AtsMessageHandler::Format(const char* msg, va_list args) {
-  GoogleString buffer;
-
-  // Ignore the name of this routine: it formats with vsnprintf.
-  // See base/stringprintf.cc.
-  StringAppendV(&buffer, msg, args);
-  return buffer;
-}
-
-}  // namespace net_instaweb

http://git-wip-us.apache.org/repos/asf/trafficserver/blob/e8b899b0/plugins/experimental/ats_speed/ats_message_handler.h
----------------------------------------------------------------------
diff --git a/plugins/experimental/ats_speed/ats_message_handler.h b/plugins/experimental/ats_speed/ats_message_handler.h
deleted file mode 100644
index b8248cf..0000000
--- a/plugins/experimental/ats_speed/ats_message_handler.h
+++ /dev/null
@@ -1,75 +0,0 @@
-/** @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.
-*/
-
-#ifndef NGX_MESSAGE_HANDLER_H_
-#define NGX_MESSAGE_HANDLER_H_
-
-#include <ts/ts.h>
-#include <cstdarg>
-
-#include "net/instaweb/util/public/basictypes.h"
-#include "net/instaweb/util/public/google_message_handler.h"
-#include "net/instaweb/util/public/message_handler.h"
-#include "net/instaweb/util/public/scoped_ptr.h"
-#include "net/instaweb/util/public/string.h"
-#include "net/instaweb/util/public/string_util.h"
-
-namespace net_instaweb {
-
-  class AbstractMutex;
-  class SharedCircularBuffer;
-  class Timer;
-  class Writer;
-
-  class AtsMessageHandler : public GoogleMessageHandler {
- public:
-    explicit AtsMessageHandler(AbstractMutex* mutex);
-
-    void set_buffer(SharedCircularBuffer* buff);
-
-    void SetPidString(const int64 pid) {
-      pid_string_ = StrCat("[", Integer64ToString(pid), "]");
-    }
-    // Dump contents of SharedCircularBuffer.
-    bool Dump(Writer* writer);
-
- protected:
-    virtual void MessageVImpl(MessageType type, const char* msg, va_list args);
-
-    virtual void FileMessageVImpl(MessageType type, const char* filename,
-                                  int line, const char* msg, va_list args);
-
- private:
-    GoogleString Format(const char* msg, va_list args);
-
-    scoped_ptr<AbstractMutex> mutex_;
-    GoogleString pid_string_;
-    GoogleMessageHandler handler_;
-    SharedCircularBuffer* buffer_;
-
-    DISALLOW_COPY_AND_ASSIGN(AtsMessageHandler);
-  };
-
-}  // namespace net_instaweb
-
-#endif  // NGX_MESSAGE_HANDLER_H_

http://git-wip-us.apache.org/repos/asf/trafficserver/blob/e8b899b0/plugins/experimental/ats_speed/ats_process_context.cc
----------------------------------------------------------------------
diff --git a/plugins/experimental/ats_speed/ats_process_context.cc b/plugins/experimental/ats_speed/ats_process_context.cc
deleted file mode 100644
index f3ca481..0000000
--- a/plugins/experimental/ats_speed/ats_process_context.cc
+++ /dev/null
@@ -1,86 +0,0 @@
-/** @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.
-*/
-
-#include "ats_process_context.h"
-
-#include <vector>
-
-#include "ats_rewrite_driver_factory.h"
-#include "ats_server_context.h"
-#include "ats_message_handler.h"
-#include "ats_thread_system.h"
-
-#include "net/instaweb/automatic/public/proxy_fetch.h"
-#include "net/instaweb/util/public/pthread_shared_mem.h"
-
-namespace net_instaweb {
-
-  AtsProcessContext::AtsProcessContext() : ProcessContext() {
-  AtsThreadSystem* ts = new AtsThreadSystem();
-  message_handler_.reset(new AtsMessageHandler(ts->NewMutex()));
-  driver_factory_.reset(
-    new AtsRewriteDriverFactory(
-      *this, ts, ""/*hostname, not used*/, -1/*port, not used*/));
-  server_context_ = driver_factory()->MakeAtsServerContext();
-
-  AtsRewriteOptions* root_options_ = (AtsRewriteOptions*)driver_factory_->default_options();
-  AtsRewriteOptions* server_options = root_options_->Clone();
-  AtsRewriteOptions* options = new AtsRewriteOptions(driver_factory_->thread_system());
-  server_options->Merge(*options);
-  delete options;
-
-  server_context_->global_options()->Merge(*server_options);
-  delete server_options;
-
-  message_handler_->Message(kInfo,"global default options:\r\n[%s]",driver_factory_->default_options()->OptionsToString().c_str());
-  message_handler_->Message(kInfo,"server ctx default options:\r\n[%s]",server_context_->global_options()->OptionsToString().c_str());
-  std::vector<SystemServerContext*> server_contexts;
-  server_contexts.push_back(server_context_);
-  
-  //Statistics* statistics =
-  //    driver_factory_->MakeGlobalSharedMemStatistics(*(SystemRewriteOptions*)server_context_->global_options());
-  GoogleString error_message;
-  int error_index = -1;
-  Statistics* global_statistics = NULL;
-  driver_factory_.get()->PostConfig(
-      server_contexts, &error_message, &error_index, &global_statistics);
-  if (error_index != -1) {
-     server_contexts[error_index]->message_handler()->Message(
-         kError, "ngx_pagespeed is enabled. %s", error_message.c_str());
-     //return NGX_ERROR;
-     CHECK(false);
-  }
-  
-  AtsRewriteDriverFactory::InitStats(global_statistics);
-    
-  driver_factory()->RootInit();
-  driver_factory()->ChildInit();
-
-  proxy_fetch_factory_.reset(new ProxyFetchFactory(server_context_));
-  message_handler_->Message(kInfo, "Process context constructed");
-}
-
-AtsProcessContext::~AtsProcessContext() {
-}
-
-}  // namespace net_instaweb

http://git-wip-us.apache.org/repos/asf/trafficserver/blob/e8b899b0/plugins/experimental/ats_speed/ats_process_context.h
----------------------------------------------------------------------
diff --git a/plugins/experimental/ats_speed/ats_process_context.h b/plugins/experimental/ats_speed/ats_process_context.h
deleted file mode 100644
index aa344b2..0000000
--- a/plugins/experimental/ats_speed/ats_process_context.h
+++ /dev/null
@@ -1,58 +0,0 @@
-/** @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.
-*/
-
-#ifndef ATS_PROCESS_CONTEXT_H_
-#define ATS_PROCESS_CONTEXT_H_
-
-#include "net/instaweb/util/public/google_message_handler.h"
-#include "net/instaweb/util/public/message_handler.h"
-#include "net/instaweb/util/public/scoped_ptr.h"
-#include "net/instaweb/rewriter/public/process_context.h"
-
-namespace net_instaweb {
-
-class AtsRewriteDriverFactory;
-class ProxyFetchFactory;
-class AtsServerContext;
-
-class AtsProcessContext : ProcessContext {
- public:
-  explicit AtsProcessContext();
-  virtual ~AtsProcessContext();
-
-  // TODO(oschaaf): const correctness
-  MessageHandler* message_handler() { return message_handler_.get(); }
-  AtsRewriteDriverFactory* driver_factory() { return driver_factory_.get(); }
-  ProxyFetchFactory* proxy_fetch_factory() { return proxy_fetch_factory_.get(); }
-  AtsServerContext* server_context() { return server_context_; }
- private:
-  scoped_ptr<MessageHandler> message_handler_;
-  scoped_ptr<AtsRewriteDriverFactory> driver_factory_;
-  scoped_ptr<ProxyFetchFactory> proxy_fetch_factory_;
-  AtsServerContext* server_context_;
-};
-
-
-}  // namespace net_instaweb
-
-#endif // ATS_PROCESS_CONTEXT_H_

http://git-wip-us.apache.org/repos/asf/trafficserver/blob/e8b899b0/plugins/experimental/ats_speed/ats_resource_intercept.cc
----------------------------------------------------------------------
diff --git a/plugins/experimental/ats_speed/ats_resource_intercept.cc b/plugins/experimental/ats_speed/ats_resource_intercept.cc
deleted file mode 100644
index 0afeae5..0000000
--- a/plugins/experimental/ats_speed/ats_resource_intercept.cc
+++ /dev/null
@@ -1,363 +0,0 @@
-/** @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.
-*/
-
-#include <ts/ts.h>
-
-#include <stdio.h>
-
-#include "ats_resource_intercept.h"
-
-
-#include "ats_base_fetch.h"
-#include "ats_rewrite_driver_factory.h"
-#include "ats_rewrite_options.h"
-#include "ats_server_context.h"
-#include "ats_speed.h"
-
-#include "net/instaweb/http/public/request_context.h"
-#include "net/instaweb/rewriter/public/resource_fetch.h"
-#include "net/instaweb/rewriter/public/static_asset_manager.h"
-#include "net/instaweb/system/public/system_request_context.h"
-
-#include "net/instaweb/util/public/string_writer.h"
-
-
-using namespace net_instaweb;
-
-struct InterceptCtx
-{
-  TSVConn vconn;
-  TSIOBuffer req_buffer;
-  TSIOBufferReader req_reader;
-  TSIOBuffer resp_buffer;
-  TSIOBufferReader resp_reader;
-  GoogleString* response;
-  TransformCtx* request_ctx;
-  RequestHeaders* request_headers;
-  
-  InterceptCtx()
-      : vconn(NULL)
-      , req_buffer(NULL)
-      , req_reader(NULL)
-      , resp_buffer(NULL)
-      , resp_reader(NULL)
-      , response( new GoogleString() )
-      , request_ctx(NULL)
-      , request_headers(NULL)
-  {
-  };
-};
-
-static void
-shutdown (TSCont cont, InterceptCtx * intercept_ctx) {
-  if (intercept_ctx->req_reader != NULL) {
-    TSIOBufferReaderFree(intercept_ctx->req_reader);
-    intercept_ctx->req_reader = NULL;
-  }
-  if (intercept_ctx->req_buffer != NULL) {
-    TSIOBufferDestroy(intercept_ctx->req_buffer);
-    intercept_ctx->req_buffer = NULL;
-  }
-  if (intercept_ctx->resp_reader != NULL) {
-    TSIOBufferReaderFree(intercept_ctx->resp_reader);
-    intercept_ctx->resp_reader = NULL;
-  }
-  if (intercept_ctx->resp_buffer != NULL) {
-    TSIOBufferDestroy(intercept_ctx->resp_buffer);
-    intercept_ctx->resp_buffer = NULL;
-  }
-  if (intercept_ctx->vconn != NULL) {
-    TSVConnShutdown(intercept_ctx->vconn, 0, 1);
-    TSVConnClose(intercept_ctx->vconn);
-    intercept_ctx->vconn = NULL;
-  }
-  if (intercept_ctx->response != NULL) {
-    delete intercept_ctx->response;
-    intercept_ctx->response = NULL;
-  }
-  // TODO(oschaaf): think the ordering of this one through.
-  if (intercept_ctx->request_ctx) {
-    ats_ctx_destroy(intercept_ctx->request_ctx);
-    intercept_ctx->request_ctx = NULL;
-  }
-  if (intercept_ctx->request_headers != NULL) {
-    delete intercept_ctx->request_headers;
-    intercept_ctx->request_headers = NULL;
-  }
-  delete intercept_ctx;
-  TSContDestroy(cont);
-}
-
-static int
-resource_intercept(TSCont cont, TSEvent event, void *edata)
-{
-  InterceptCtx *intercept_ctx = static_cast<InterceptCtx *>(TSContDataGet(cont));
-  bool shutDown = false;
-
-  // TODO(oschaaf): have a look at https://github.com/apache/trafficserver/blob/master/plugins/experimental/esi/serverIntercept.c
-  // and see if we have any edge cases we should fix.
-  switch (event) {
-    case TS_EVENT_NET_ACCEPT: {
-      intercept_ctx->vconn = static_cast<TSVConn>(edata);
-      intercept_ctx->req_buffer = TSIOBufferCreate();
-      intercept_ctx->req_reader = TSIOBufferReaderAlloc(intercept_ctx->req_buffer);
-      intercept_ctx->resp_buffer = TSIOBufferCreate();
-      intercept_ctx->resp_reader = TSIOBufferReaderAlloc(intercept_ctx->resp_buffer);
-      TSVConnRead(intercept_ctx->vconn, cont, intercept_ctx->req_buffer, 0x7fffffff);
-    } break;
-    case TS_EVENT_VCONN_READ_READY: {
-      CHECK(intercept_ctx->request_ctx->base_fetch == NULL) << "Base fetch must not be set!";
-      CHECK(intercept_ctx->request_ctx->url_string != NULL) << "Url must be set!";
-
-      TSVConnShutdown(intercept_ctx->vconn, 1, 0);
-
-      // response will already have a size for internal pages at this point.
-      // resources, however, will have to be fetched.
-      // TODO(oschaaf): this is extremely ugly.
-      if (intercept_ctx->response->size() == 0) { 
-        // TODO(oschaaf): unused - must we close / clean this up?
-        TSVIO downstream_vio = TSVConnWrite(
-            intercept_ctx->vconn, cont, intercept_ctx->resp_reader, 0x7fffffff);
-
-        AtsServerContext* server_context = intercept_ctx->request_ctx->server_context;
-
-        // TODO:(oschaaf) host/port
-        SystemRequestContext* system_request_context = 
-            new SystemRequestContext(server_context->thread_system()->NewMutex(),
-                                     server_context->timer(),
-				     "www.foo.com",// TODO(oschaaf): compute these
-                                     80,
-                                     "127.0.0.1");
-
-        intercept_ctx->request_ctx->base_fetch = new AtsBaseFetch(
-            server_context, RequestContextPtr(system_request_context),
-            downstream_vio, intercept_ctx->resp_buffer, true);
-        intercept_ctx->request_ctx->base_fetch->set_request_headers(
-            intercept_ctx->request_headers);
-
-        RewriteOptions* options = NULL;
-         
-        //const char* host = intercept_ctx->request_headers->Lookup1(HttpAttributes::kHost);
-        const char* host = intercept_ctx->request_ctx->gurl->HostAndPort().as_string().c_str();
-        if (host != NULL && strlen(host) > 0) {
-          intercept_ctx->request_ctx->options = get_host_options(host);
-        }
-        
-        // TODO(oschaaf): directory options should be coming from configuration!
-        bool ok = ps_determine_options(server_context,
-                                       intercept_ctx->request_ctx->options,
-                                       intercept_ctx->request_ctx->base_fetch->request_headers(),
-                                       intercept_ctx->request_ctx->base_fetch->response_headers(),
-                                       &options,
-                                       intercept_ctx->request_ctx->gurl);
-        
-        // Take ownership of custom_options.
-        scoped_ptr<RewriteOptions> custom_options(options);
-        
-        if (!ok) {
-          TSError("Failure while determining request options for psol resource");
-          // options = server_context->global_options();
-        } else {
-          // ps_determine_options modified url, removing any ModPagespeedFoo=Bar query
-          // parameters.  Keep url_string in sync with url.
-          // TODO(oschaaf): we really should determine if we have to do the lookup
-          intercept_ctx->request_ctx->gurl->Spec().CopyToString(intercept_ctx->request_ctx->url_string);
-        }
-
-        // The url we have here is already checked for IsWebValid()
-        net_instaweb::ResourceFetch::Start(
-            GoogleUrl(*intercept_ctx->request_ctx->url_string),
-            custom_options.release() /* null if there aren't custom options */,
-            false /* using_spdy */, server_context, intercept_ctx->request_ctx->base_fetch);
-      } else {
-        int64_t numBytesToWrite, numBytesWritten;
-        numBytesToWrite = intercept_ctx->response->size();
-        numBytesWritten = TSIOBufferWrite(intercept_ctx->resp_buffer,
-                                          intercept_ctx->response->c_str(), numBytesToWrite);
-        
-        if (numBytesWritten == numBytesToWrite) {
-          TSVConnWrite(intercept_ctx->vconn, cont, intercept_ctx->resp_reader, numBytesToWrite);
-        } else {
-          TSError("Not all output could be written in one go");
-          DCHECK(false);
-        }
-      }
-    }  break;
-    case TS_EVENT_VCONN_EOS:
-      TSVConnShutdown(intercept_ctx->vconn, 1, 0);
-      break;
-    case TS_EVENT_VCONN_READ_COMPLETE: {
-      TSVConnShutdown(intercept_ctx->vconn, 1, 0);
-    } break;
-    case TS_EVENT_VCONN_WRITE_READY:
-      break;
-    case TS_EVENT_VCONN_WRITE_COMPLETE:
-      shutDown = true;
-      break;
-    case TS_EVENT_ERROR:
-      TSError("vconn event: error %s", intercept_ctx->request_ctx->url_string->c_str());
-      shutDown = true;
-      break;
-    case TS_EVENT_NET_ACCEPT_FAILED:
-      TSError("vconn event: accept failed");
-      shutDown = true;
-      break;
-    case TS_EVENT_IMMEDIATE:
-    case TS_EVENT_TIMEOUT:
-      break;
-    default:
-      TSError("default clause event: %d", event);
-      break;
-  }
-
-  if (shutDown) {
-    shutdown(cont, intercept_ctx);
-  }
-
-  return 1;
-}
-
-// We intercept here because serving from ats's own cache is faster
-// then serving from pagespeed's cache. (which needs to be looked in to)
-static int
-read_cache_header_callback(TSCont cont, TSEvent event, void *edata)
-{
-  TSHttpTxn txn = static_cast<TSHttpTxn>(edata);
-  TransformCtx* ctx = get_transaction_context(txn);
-
-  if (ctx == NULL) {
-    TSHttpTxnReenable(txn, TS_EVENT_HTTP_CONTINUE);
-    return 0;
-  }
-  if (!ctx->resource_request) {
-    TSHttpTxnReenable(txn, TS_EVENT_HTTP_CONTINUE);
-    return 0;    
-  }
-  // TODO(oschaaf): FIXME: Ownership of ctx has become too mucky.
-  // This is because I realised too late that the intercepts
-  // are able to outlive the transaction, which I hacked
-  // to work.
-  if (TSHttpIsInternalRequest(txn) == TS_SUCCESS) {
-    ats_ctx_destroy(ctx);
-    TSHttpTxnReenable(txn, TS_EVENT_HTTP_CONTINUE);
-    return 0;
-  }
-  
-  if (cache_hit(txn)) {
-    ats_ctx_destroy(ctx);
-    TSHttpTxnReenable(txn, TS_EVENT_HTTP_CONTINUE);
-    return 0;
-  }
-
-  AtsServerContext* server_context = ctx->server_context;
-  AtsRewriteDriverFactory* factory = (AtsRewriteDriverFactory*)server_context->factory();
-  GoogleString output;
-  StringWriter writer(&output);
-  HttpStatus::Code status = HttpStatus::kOK;
-  ContentType content_type = kContentTypeHtml;
-  StringPiece cache_control = HttpAttributes::kNoCache;
-  const char* error_message = NULL;
-  StringPiece request_uri_path = ctx->gurl->PathAndLeaf();  
-  
-  if (false && ctx->gurl->PathSansQuery() == "/robots.txt") {
-    content_type = kContentTypeText;
-    writer.Write("User-agent: *\n", server_context->message_handler());
-    writer.Write("Disallow: /\n", server_context->message_handler());
-  }
- 
-  // TODO(oschaaf): /pagespeed_admin handling
-  else { 
-    // Optimized resource are highly cacheable (1 year expiry)
-    // TODO(oschaaf): configuration
-    TSHttpTxnRespCacheableSet(txn, 1);
-    TSHttpTxnReqCacheableSet(txn, 1);
-
-    TSMBuffer reqp;
-    TSMLoc req_hdr_loc;
-    if (TSHttpTxnClientReqGet(ctx->txn, &reqp, &req_hdr_loc) != TS_SUCCESS) {
-      TSError("Error TSHttpTxnClientReqGet for resource!");
-      TSHttpTxnReenable(txn, TS_EVENT_HTTP_CONTINUE);
-      return 0;
-    }
-    
-    TSCont interceptCont = TSContCreate(resource_intercept, TSMutexCreate());
-    InterceptCtx *intercept_ctx = new InterceptCtx();
-    intercept_ctx->request_ctx = ctx;
-    intercept_ctx->request_headers = new RequestHeaders();
-    copy_request_headers_to_psol(reqp, req_hdr_loc, intercept_ctx->request_headers);
-    TSHandleMLocRelease(reqp, TS_NULL_MLOC, req_hdr_loc);
-
-    
-    TSContDataSet(interceptCont, intercept_ctx);
-    TSHttpTxnServerIntercept(interceptCont, txn);
-    TSHttpTxnReenable(txn, TS_EVENT_HTTP_CONTINUE);
-    return 0;
-  } 
-
-  if (error_message != NULL) {
-    status = HttpStatus::kNotFound;
-    content_type = kContentTypeHtml;
-    output = error_message;
-  }
-
-  ResponseHeaders response_headers;
-  response_headers.SetStatusAndReason(status);
-  response_headers.set_major_version(1);
-  response_headers.set_minor_version(0);
-
-  response_headers.Add(HttpAttributes::kContentType, content_type.mime_type());
-
-  int64 now_ms = factory->timer()->NowMs();
-  response_headers.SetDate(now_ms);
-  response_headers.SetLastModified(now_ms);
-  response_headers.Add(HttpAttributes::kCacheControl, cache_control);
-
-  if (FindIgnoreCase(cache_control, "private") ==
-      static_cast<int>(StringPiece::npos)) {
-    response_headers.Add(HttpAttributes::kEtag, "W/\"0\"");
-  }
-
-  GoogleString header;
-  StringWriter header_writer(&header);
-  response_headers.WriteAsHttp(&header_writer, server_context->message_handler());
-  
-  TSCont interceptCont = TSContCreate(resource_intercept, TSMutexCreate());
-  InterceptCtx *intercept_ctx = new InterceptCtx(); 
-  intercept_ctx->request_ctx = ctx;
-  header.append(output);
-  TSHttpTxnRespCacheableSet(txn, 0);
-  TSHttpTxnReqCacheableSet(txn, 0);
-  TSContDataSet(interceptCont, intercept_ctx);
-  TSHttpTxnServerIntercept(interceptCont, txn);
-  intercept_ctx->response->append(header);
-  
-  TSHttpTxnReenable(txn, TS_EVENT_HTTP_CONTINUE);
-  return 0;
-}
-
-void setup_resource_intercept()
-{
-  TSCont cont = TSContCreate(read_cache_header_callback, NULL);
-  TSHttpHookAdd(TS_HTTP_CACHE_LOOKUP_COMPLETE_HOOK, cont);
-}
-

http://git-wip-us.apache.org/repos/asf/trafficserver/blob/e8b899b0/plugins/experimental/ats_speed/ats_resource_intercept.h
----------------------------------------------------------------------
diff --git a/plugins/experimental/ats_speed/ats_resource_intercept.h b/plugins/experimental/ats_speed/ats_resource_intercept.h
deleted file mode 100644
index 933f20f..0000000
--- a/plugins/experimental/ats_speed/ats_resource_intercept.h
+++ /dev/null
@@ -1,29 +0,0 @@
-/** @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.
-*/
-
-#ifndef ATS_RESOURCE_INTERCEPT_H
-#define ATS_RESOURCE_INTERCEPT_H
-
-void setup_resource_intercept();
-
-#endif // ATS_INTERCEPT_H

http://git-wip-us.apache.org/repos/asf/trafficserver/blob/e8b899b0/plugins/experimental/ats_speed/ats_rewrite_driver_factory.cc
----------------------------------------------------------------------
diff --git a/plugins/experimental/ats_speed/ats_rewrite_driver_factory.cc b/plugins/experimental/ats_speed/ats_rewrite_driver_factory.cc
deleted file mode 100644
index cf73ed3..0000000
--- a/plugins/experimental/ats_speed/ats_rewrite_driver_factory.cc
+++ /dev/null
@@ -1,196 +0,0 @@
-/** @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.
-*/
-
-#include "ats_rewrite_driver_factory.h"
-
-#include <cstdio>
-#include <vector>
-
-#include "ats_thread_system.h"
-#include "ats_message_handler.h"
-#include "ats_server_context.h"
-
-#include "net/instaweb/http/public/content_type.h"
-#include "net/instaweb/http/public/rate_controller.h"
-#include "net/instaweb/http/public/rate_controlling_url_async_fetcher.h"
-#include "net/instaweb/http/public/wget_url_fetcher.h"
-#include "net/instaweb/rewriter/public/rewrite_driver.h"
-#include "net/instaweb/rewriter/public/rewrite_driver_factory.h"
-#include "net/instaweb/rewriter/public/server_context.h"
-#include "net/instaweb/rewriter/public/static_asset_manager.h"
-#include "net/instaweb/system/public/in_place_resource_recorder.h"
-#include "net/instaweb/system/public/serf_url_async_fetcher.h"
-#include "net/instaweb/system/public/system_caches.h"
-#include "net/instaweb/system/public/system_rewrite_options.h"
-#include "net/instaweb/util/public/google_message_handler.h"
-#include "net/instaweb/util/public/null_shared_mem.h"
-#include "net/instaweb/util/public/posix_timer.h"
-#include "net/instaweb/util/public/property_cache.h"
-#include "net/instaweb/util/public/pthread_shared_mem.h"
-#include "net/instaweb/util/public/scheduler_thread.h"
-#include "net/instaweb/util/public/shared_circular_buffer.h"
-#include "net/instaweb/util/public/shared_mem_statistics.h"
-#include "net/instaweb/util/public/slow_worker.h"
-#include "net/instaweb/util/public/stdio_file_system.h"
-#include "net/instaweb/util/public/string.h"
-#include "net/instaweb/util/public/string_util.h"
-#include "net/instaweb/util/public/thread_system.h"
-
-
-namespace net_instaweb {
-
-
-  AtsRewriteDriverFactory::AtsRewriteDriverFactory(
-						   const ProcessContext& process_context,
-						   AtsThreadSystem* thread_system,
-						   StringPiece hostname, int port)
-    : SystemRewriteDriverFactory(process_context, 
-				 thread_system, NULL /*default shared mem runtime*/,
-				 "" /*hostname, not used*/, -1/*port, not used*/)
-      , ats_message_handler_(new AtsMessageHandler(thread_system->NewMutex()))
-      , ats_html_parse_message_handler_(new AtsMessageHandler(thread_system->NewMutex()))
-      , use_per_vhost_statistics_(false)
-      , threads_started_(false)
-  {
-    InitializeDefaultOptions();
-    default_options()->set_beacon_url("/ats_speed_beacon");
-    default_options()->set_enabled(RewriteOptions::kEnabledOn);
-    default_options()->SetRewriteLevel(RewriteOptions::kCoreFilters);
-    
-    SystemRewriteOptions* system_options = dynamic_cast<SystemRewriteOptions*>(
-									       default_options());
-    system_options->set_log_dir("/tmp/ps_log/");
-    system_options->set_statistics_logging_enabled(true);
-
-    system_options->set_file_cache_clean_inode_limit(500000);
-    system_options->set_file_cache_clean_size_kb(1024*10000);// 10 GB
-    system_options->set_avoid_renaming_introspective_javascript(true);
-    system_options->set_file_cache_path("/tmp/ats_ps/");
-    system_options->set_lru_cache_byte_limit(163840);
-    system_options->set_lru_cache_kb_per_process(1024*500);//500 MB
-
-    system_options->set_flush_html(true);
-    
-    AtsRewriteOptions* ats_options = (AtsRewriteOptions*)system_options;
-    std::vector<std::string> args;
-    args.push_back("RateLimitBackgroundFetches");
-    args.push_back("on");
-    global_settings settings;
-    const char* msg = ats_options->ParseAndSetOptions(args, ats_message_handler_, settings);
-    CHECK(!msg);
-    
-    set_message_buffer_size(1024*128);
-    set_message_handler(ats_message_handler_);
-    set_html_parse_message_handler(ats_html_parse_message_handler_);
-    StartThreads();
-  }
-
-  AtsRewriteDriverFactory::~AtsRewriteDriverFactory() {
-    ShutDown();
-    delete ats_message_handler_;
-    ats_message_handler_ = NULL;
-    delete ats_html_parse_message_handler_;
-    ats_html_parse_message_handler_ = NULL;
-    STLDeleteElements(&uninitialized_server_contexts_);
-  }
-
-  void AtsRewriteDriverFactory::InitStaticAssetManager(StaticAssetManager* static_js_manager) {
-    static_js_manager->set_library_url_prefix("/ats_speed_static/");
-  }
-
-  Hasher* AtsRewriteDriverFactory::NewHasher() {
-    return new MD5Hasher;
-  }
-
-  MessageHandler* AtsRewriteDriverFactory::DefaultHtmlParseMessageHandler() {
-    return ats_html_parse_message_handler_;
-  }
-
-  MessageHandler* AtsRewriteDriverFactory::DefaultMessageHandler() {
-    return ats_message_handler_;
-  }
-
-  FileSystem* AtsRewriteDriverFactory::DefaultFileSystem() {
-    return new StdioFileSystem();
-  }
-
-  Timer* AtsRewriteDriverFactory::DefaultTimer() {
-    return new PosixTimer;
-  }
-
-  NamedLockManager* AtsRewriteDriverFactory::DefaultLockManager() {
-    CHECK(false) << "default lock manager should not be called";
-    return NULL;
-  }
-
-  RewriteOptions* AtsRewriteDriverFactory::NewRewriteOptions() {
-    AtsRewriteOptions* options = new AtsRewriteOptions(thread_system());
-    options->SetRewriteLevel(RewriteOptions::kCoreFilters);
-    return options;
-  }
-
-  ServerContext* AtsRewriteDriverFactory::NewDecodingServerContext() {
-    ServerContext* sc = new AtsServerContext(this);
-    InitStubDecodingServerContext(sc);
-    return sc;
-  }
-
-  void AtsRewriteDriverFactory::InitStats(Statistics* statistics) {
-    // Init standard PSOL stats.
-    SystemRewriteDriverFactory::InitStats(statistics);
-    // Init Ats-specific stats.
-    AtsServerContext::InitStats(statistics);
-  }
-
-
-  AtsServerContext* AtsRewriteDriverFactory::MakeAtsServerContext() {
-    AtsServerContext* server_context = new AtsServerContext(this);
-    uninitialized_server_contexts_.insert(server_context);
-    return server_context;
-  }
-
-  ServerContext* AtsRewriteDriverFactory::NewServerContext() {
-    LOG(DFATAL) << "MakeAtsServerContext should be used instead";
-    return NULL;
-  }
-
-net_instaweb::QueuedWorkerPool* AtsRewriteDriverFactory::CreateWorkerPool(net_instaweb::RewriteDriverFactory::WorkerPoolCategory pool,
-                                                                          StringPiece name) {
-  int tc = 8;
-  TSDebug("ats_speed", "Created new QueuedWorkerPool of type %d named '%s' of size %d", pool, name.data(), tc);
-  net_instaweb::QueuedWorkerPool *q_pool = new net_instaweb::QueuedWorkerPool(tc, name, thread_system());
-  return q_pool;
-}
-
-void AtsRewriteDriverFactory::StartThreads() {
-  if (threads_started_) {
-    CHECK(false) << "threads already started";
-  }
-  SchedulerThread* thread = new SchedulerThread(thread_system(), scheduler());
-  bool ok = thread->Start();
-  CHECK(ok) << "Unable to start scheduler thread";
-  defer_cleanup(thread->MakeDeleter());
-  threads_started_ = true;
-}
-
-}  // namespace net_instaweb

http://git-wip-us.apache.org/repos/asf/trafficserver/blob/e8b899b0/plugins/experimental/ats_speed/ats_rewrite_driver_factory.h
----------------------------------------------------------------------
diff --git a/plugins/experimental/ats_speed/ats_rewrite_driver_factory.h b/plugins/experimental/ats_speed/ats_rewrite_driver_factory.h
deleted file mode 100644
index de18a28..0000000
--- a/plugins/experimental/ats_speed/ats_rewrite_driver_factory.h
+++ /dev/null
@@ -1,113 +0,0 @@
-/** @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.
-*/
-
-#ifndef ATS_REWRITE_DRIVER_FACTORY_H_
-#define ATS_REWRITE_DRIVER_FACTORY_H_
-
-#include <set>
-
-#include "net/instaweb/system/public/system_rewrite_driver_factory.h"
-#include "net/instaweb/util/public/md5_hasher.h"
-#include "net/instaweb/util/public/scoped_ptr.h"
-
-
-namespace net_instaweb {
-
-
-  class AbstractSharedMem;
-  //class NgxMessageHandler;
-  //class NgxRewriteOptions;
-  class AtsServerContext;
-  class AtsThreadSystem;
-  class GoogleMessageHandler;
-  //class NgxUrlAsyncFetcher;
-  class SharedCircularBuffer;
-  class SharedMemRefererStatistics;
-  class SharedMemStatistics;
-  class SlowWorker;
-  class StaticAssetManager;
-  class Statistics;
-  class StaticAssetManager;
-  //class SystemCaches;
-
-class AtsRewriteDriverFactory : public SystemRewriteDriverFactory { 
- public:
-  explicit AtsRewriteDriverFactory(const ProcessContext& process_context,
-				   AtsThreadSystem* thread_system,
-				   StringPiece hostname, int port);
-  virtual ~AtsRewriteDriverFactory();
-
-  virtual Hasher* NewHasher();
-  virtual MessageHandler* DefaultHtmlParseMessageHandler();
-  virtual MessageHandler* DefaultMessageHandler();
-  virtual FileSystem* DefaultFileSystem();
-  virtual Timer* DefaultTimer();
-  virtual NamedLockManager* DefaultLockManager();
-  virtual RewriteOptions* NewRewriteOptions();
-  virtual ServerContext* NewDecodingServerContext();
-
-  virtual bool UseBeaconResultsInFilters() const {
-    return true;
-  }
-
-  virtual void InitStaticAssetManager(StaticAssetManager* static_js_manager);
-  
-  // Initializes all the statistics objects created transitively by
-  // AtsRewriteDriverFactory, including nginx-specific and
-  // platform-independent statistics.
-  static void InitStats(Statistics* statistics);
-
-  virtual net_instaweb::QueuedWorkerPool* CreateWorkerPool(WorkerPoolCategory pool,
-                                                           StringPiece name);
-  virtual void NonStaticInitStats(Statistics* statistics) {
-    InitStats(statistics);
-  }
-
-  AtsServerContext* MakeAtsServerContext();
-  ServerContext* NewServerContext();
-  //AbstractSharedMem* shared_mem_runtime() const {
-  //  return shared_mem_runtime_.get();
-  //}
-
-  // Starts pagespeed threads if they've not been started already.  Must be
-  // called after the caller has finished any forking it intends to do.
-  void StartThreads();
-  bool use_per_vhost_statistics() const {
-    return use_per_vhost_statistics_;
-  }
-  void set_use_per_vhost_statistics(bool x) {
-    use_per_vhost_statistics_ = x;
-  }
-
- protected:
- private:
-  //scoped_ptr<AbstractSharedMem> shared_mem_runtime_;
-  GoogleMessageHandler* ats_message_handler_;
-  GoogleMessageHandler* ats_html_parse_message_handler_;
-  bool use_per_vhost_statistics_;
-  bool threads_started_;
-};
-
-}  // namespace net_instaweb
-
-#endif // ATS_REWRITE_DRIVER_FACTORY_H_

http://git-wip-us.apache.org/repos/asf/trafficserver/blob/e8b899b0/plugins/experimental/ats_speed/ats_rewrite_options.cc
----------------------------------------------------------------------
diff --git a/plugins/experimental/ats_speed/ats_rewrite_options.cc b/plugins/experimental/ats_speed/ats_rewrite_options.cc
deleted file mode 100644
index 172db83..0000000
--- a/plugins/experimental/ats_speed/ats_rewrite_options.cc
+++ /dev/null
@@ -1,263 +0,0 @@
-/** @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.
-*/
-
-#include "ats_rewrite_options.h"
-
-#include "net/instaweb/public/version.h"
-#include "net/instaweb/rewriter/public/rewrite_options.h"
-#include "net/instaweb/util/public/timer.h"
-
-#include "net/instaweb/util/public/message_handler.h"
-#include "net/instaweb/rewriter/public/file_load_policy.h"
-
-#include "net/instaweb/util/public/stdio_file_system.h"
-
-#include "ats_message_handler.h"
-#include "ats_rewrite_driver_factory.h"
-
-using namespace std;
-
-namespace net_instaweb {
-
-
-RewriteOptions::Properties* AtsRewriteOptions::ats_properties_ = NULL;
-
-AtsRewriteOptions::AtsRewriteOptions(ThreadSystem* thread_system)
-    : SystemRewriteOptions(thread_system) {
-
-  Init();
-}
-
-void AtsRewriteOptions::Init() {
-  DCHECK(ats_properties_ != NULL)
-      << "Call AtsRewriteOptions::Initialize() before construction";
-  InitializeOptions(ats_properties_);
-}
-
-void AtsRewriteOptions::AddProperties() {
-  MergeSubclassProperties(ats_properties_);
-  AtsRewriteOptions dummy_config(NULL);
-
-  dummy_config.set_default_x_header_value(MOD_PAGESPEED_VERSION_STRING "-" LASTCHANGE_STRING);
-}
-
-void AtsRewriteOptions::Initialize() {
-  if (Properties::Initialize(&ats_properties_)) {
-    SystemRewriteOptions::Initialize();
-    AddProperties();
-  }
-}
-
-void AtsRewriteOptions::Terminate() {
-  if (Properties::Terminate(&ats_properties_)) {
-    SystemRewriteOptions::Terminate();
-  }
-}
-
-bool AtsRewriteOptions::IsDirective(StringPiece config_directive,
-                                    StringPiece compare_directive) {
-  return StringCaseEqual(config_directive, compare_directive);
-}
-
-RewriteOptions::OptionSettingResult AtsRewriteOptions::ParseAndSetOptions0(
-    StringPiece directive, GoogleString* msg, MessageHandler* handler) {
-  if (IsDirective(directive, "on")) {
-    set_enabled(RewriteOptions::kEnabledOn);
-  } else if (IsDirective(directive, "off")) {
-    set_enabled(RewriteOptions::kEnabledOff);
-  } else if (IsDirective(directive, "unplugged")) {
-    set_enabled(RewriteOptions::kEnabledUnplugged);
-  } else {
-    return RewriteOptions::kOptionNameUnknown;
-  }
-  return RewriteOptions::kOptionOk;
-}
-
-
-RewriteOptions::OptionSettingResult
-AtsRewriteOptions::ParseAndSetOptionFromName1(
-    StringPiece name, StringPiece arg,
-    GoogleString* msg, MessageHandler* handler) {
-  // FileCachePath needs error checking.
-  if (StringCaseEqual(name, kFileCachePath)) {
-    if (!StringCaseStartsWith(arg, "/")) {
-      *msg = "must start with a slash";
-      return RewriteOptions::kOptionValueInvalid;
-    }
-  }
-
-  return SystemRewriteOptions::ParseAndSetOptionFromName1(
-      name, arg, msg, handler);
-}
-
-bool AtsRewriteOptions::SetBoolFlag(bool* v, StringPiece arg) {
-  if (IsDirective(arg, "on")) {
-    *v=true;
-    return true;
-  } else if (IsDirective(arg, "off")) {
-    *v=false;
-    return true;
-  }
-  return false;
-}
-
-const char*
-AtsRewriteOptions::ParseAndSetOptions(
-    vector<string> args, MessageHandler* handler, global_settings& global_config) {
-  int n_args = args.size();
-  CHECK_GE(n_args, 1);
-
-  StringPiece directive = args[0];
-
-  // Remove initial "ModPagespeed" if there is one.
-  StringPiece mod_pagespeed("ModPagespeed");
-  if (StringCaseStartsWith(directive, mod_pagespeed)) {
-    directive.remove_prefix(mod_pagespeed.size());
-  }
-
-  GoogleString msg;
-  OptionSettingResult result;
-  if (n_args == 1) {
-    result = ParseAndSetOptions0(directive, &msg, handler);
-  } else if (n_args == 2) {
-    StringPiece arg = args[1];
-    if (IsDirective(directive, "UsePerVHostStatistics")) {
-      if (!SetBoolFlag(&global_config.use_per_vhost_statistics,arg)) {
-        msg = "Failed to set UsePerVHostStatistics value";
-        result = RewriteOptions::kOptionValueInvalid;
-      } else {
-        result = RewriteOptions::kOptionOk;
-      }
-    } /* else if (IsDirective(directive, "InstallCrashHandler")) {
-         // Not applicable
-         } */ else if (IsDirective(directive, "MessageBufferSize")) {
-      int message_buffer_size;
-      bool ok = StringToInt(arg.as_string(), &message_buffer_size);
-      if (ok && message_buffer_size >= 0) {
-        global_config.message_buffer_size = message_buffer_size;
-        result = RewriteOptions::kOptionOk;
-      } else {
-        msg = "Failed to set MessageBufferSize value";
-        result = RewriteOptions::kOptionValueInvalid;
-      }
-    } else if (IsDirective(directive, "UseNativeFetcher")) {
-      if (!SetBoolFlag(&global_config.info_urls_local_only,arg)) {
-        msg = "Failed to set UseNativeFetcher value";
-        result = RewriteOptions::kOptionValueInvalid;
-      } else {
-        msg = "Native fetcher is not available in this release";
-
-        result = RewriteOptions::kOptionValueInvalid;
-      }
-    } else if (IsDirective(directive, "InfoUrlsLocalOnly")) {
-      if (!SetBoolFlag(&global_config.info_urls_local_only, arg)) {
-        msg = "Failed to set InfoUrlsLocalOnly value";
-        result = RewriteOptions::kOptionValueInvalid;
-      } else {
-        result = RewriteOptions::kOptionOk;
-      }
-    }/* else if (IsDirective(directive, "RateLimitBackgroundFetches")) {
-        if (!SetBoolFlag(&global_config.rate_limit_background_fetches, arg)) {
-        msg = "Failed to set RateLimitBackgroundFetches value";
-        result = RewriteOptions::kOptionValueInvalid;
-        } else {
-        result = RewriteOptions::kOptionOk;
-        }
-            }  else if (IsDirective(directive, "ForceCaching")) {
-            if (!SetBoolFlag(&global_config.force_caching, arg)) {
-            msg = "Failed to set ForceCaching value";
-            result = RewriteOptions::kOptionValueInvalid;
-            } else {
-            result = RewriteOptions::kOptionOk;
-            }
-                } else if (IsDirective(directive, "ListOutstandingUrlsOnError")) {
-                if (!SetBoolFlag(&global_config.list_outstanding_urls_on_error, arg)) {
-                msg = "Failed to set ListOutstandingUrlsOnError value";
-                result = RewriteOptions::kOptionValueInvalid;
-                } else {
-                result = RewriteOptions::kOptionOk;
-                }
-                    } else if (IsDirective(directive, "TrackOriginalContentLength")) {
-                    if (!SetBoolFlag(&global_config.track_original_content_length, arg)) {
-                    msg = "Failed to set TrackOriginalContentLength value";
-                    result = RewriteOptions::kOptionValueInvalid;
-                    } else {
-                    result = RewriteOptions::kOptionOk;
-                    }
-                    } */else {
-      result = ParseAndSetOptionFromName1(directive, args[1], &msg, handler);
-    }
-  } else if (n_args == 3) {
-    if (StringCaseEqual(directive, "CreateSharedMemoryMetadataCache")) {
-      int64 kb = 0;
-      if (!StringToInt64(args[2], &kb) || kb < 0) {
-        result = RewriteOptions::kOptionValueInvalid;
-        msg = "size_kb must be a positive 64-bit integer";
-      } else {
-        global_config.shm_cache_size_kb = kb;
-        result = kOptionOk;
-        //bool ok = driver_factory->caches()->CreateShmMetadataCache(
-        //    args[1].as_string(), kb, &msg);
-        //result = ok ? kOptionOk : kOptionValueInvalid;
-      }
-    } else {
-      result = ParseAndSetOptionFromName2(directive, args[1], args[2],
-                                          &msg, handler);
-    }
-  } else if (n_args == 4) {
-    result = ParseAndSetOptionFromName3(
-        directive, args[1], args[2], args[3], &msg, handler);
-  } else {
-    return "unknown option";
-  }
-
-  if (msg.size()) {
-    handler->Message(kWarning, "Error handling config line [%s]: [%s]",
-                     JoinString(args, ' ').c_str(), msg.c_str());
-  }
-
-  switch (result) {
-    case RewriteOptions::kOptionOk:
-      return NULL;
-    case RewriteOptions::kOptionNameUnknown:
-      handler->Message(kWarning, "%s", JoinString(args, ' ').c_str());
-      return "unknown option";
-    case RewriteOptions::kOptionValueInvalid: {
-      handler->Message(kWarning, "%s", JoinString(args, ' ').c_str());
-      return "Invalid value";
-    }
-  }
-
-  CHECK(false);
-  return NULL;
-}
-
-AtsRewriteOptions* AtsRewriteOptions::Clone() const {
-  AtsRewriteOptions* options = new AtsRewriteOptions(this->thread_system());
-  options->Merge(*this);
-  return options;
-}
-
-
-}  // namespace net_instaweb
-

http://git-wip-us.apache.org/repos/asf/trafficserver/blob/e8b899b0/plugins/experimental/ats_speed/ats_rewrite_options.h
----------------------------------------------------------------------
diff --git a/plugins/experimental/ats_speed/ats_rewrite_options.h b/plugins/experimental/ats_speed/ats_rewrite_options.h
deleted file mode 100644
index 4a39dcd..0000000
--- a/plugins/experimental/ats_speed/ats_rewrite_options.h
+++ /dev/null
@@ -1,103 +0,0 @@
-/** @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.
-*/
-
-#ifndef ATS_REWRITE_OPTIONS_H_
-#define ATS_REWRITE_OPTIONS_H_
-
-#include <string>
-#include <vector>
-
-#include "net/instaweb/util/public/string.h"
-#include "net/instaweb/util/public/string_util.h"
-#include "net/instaweb/rewriter/public/rewrite_options.h"
-#include "net/instaweb/system/public/system_rewrite_options.h"
-
-
-//#include "ats_configuration.h"
-
-
-namespace net_instaweb {
-
-class ThreadSystem;
-
-struct global_settings {
-  global_settings()
-  : info_urls_local_only(true)
-  , use_native_fetcher(false)
-      , use_per_vhost_statistics(true)
-      , message_buffer_size(1024*128)
-      , shm_cache_size_kb(0)
-      //, rate_limit_background_fetches(true)
-      //, force_caching(false)
-      //, list_outstanding_urls_on_error(false)
-      //, track_original_content_length(false)
-  {
-  }
-  bool info_urls_local_only;
-  bool use_native_fetcher;
-  bool use_per_vhost_statistics;
-  int message_buffer_size;
-  //bool rate_limit_background_fetches;
-  //bool force_caching;
-  //bool list_outstanding_urls_on_error;
-  //bool track_original_content_length;
-  int shm_cache_size_kb;
-};
-
-
-class AtsRewriteOptions : public SystemRewriteOptions {
- public:
-    // See rewrite_options::Initialize and ::Terminate
-    static void Initialize();
-    static void Terminate();
-
-    AtsRewriteOptions(ThreadSystem* thread_system);
-    virtual ~AtsRewriteOptions() {
-    }
-
-    const char* ParseAndSetOptions(
-        std::vector<std::string> args, MessageHandler* handler, global_settings& global_config);
-
-    virtual AtsRewriteOptions* Clone() const;
-    OptionSettingResult ParseAndSetOptions0(
-        StringPiece directive, GoogleString* msg, MessageHandler* handler);
-
-    virtual OptionSettingResult ParseAndSetOptionFromName1(
-        StringPiece name, StringPiece arg,
-        GoogleString* msg, MessageHandler* handler);
-
-
- private:
-    bool SetBoolFlag(bool* v, StringPiece arg);
-    static Properties* ats_properties_;
-    static void AddProperties();
-    void Init();
-
-    bool IsDirective(StringPiece config_directive, StringPiece compare_directive);
-
-    DISALLOW_COPY_AND_ASSIGN(AtsRewriteOptions);
-  };
-
-} // namespace net_instaweb
-
-#endif  // ATS_REWRITE_OPTIONS_H_


[2/6] ats_pagespeed: rename ats_speed -> ats_pagespeed

Posted by am...@apache.org.
http://git-wip-us.apache.org/repos/asf/trafficserver/blob/e8b899b0/plugins/experimental/ats_speed/ats_server_context.cc
----------------------------------------------------------------------
diff --git a/plugins/experimental/ats_speed/ats_server_context.cc b/plugins/experimental/ats_speed/ats_server_context.cc
deleted file mode 100644
index 4fc9eff..0000000
--- a/plugins/experimental/ats_speed/ats_server_context.cc
+++ /dev/null
@@ -1,46 +0,0 @@
-/** @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.
-*/
-
-#include "ats_server_context.h"
-#include "ats_rewrite_driver_factory.h"
-#include "ats_rewrite_options.h"
-
-#include "net/instaweb/system/public/system_caches.h"
-
-
-using namespace net_instaweb;
-
-AtsRewriteOptions* AtsServerContext::config() {
-  return (AtsRewriteOptions*)global_options();
-}
-
-AtsServerContext::AtsServerContext(AtsRewriteDriverFactory* factory) :
-  // TODO(oschaaf): host/port
-  SystemServerContext(factory, "foo.com" /*hostname*/, 8080/*port*/),
-    initialized_(false),
-    ats_factory_(factory) {
-}
-
-AtsServerContext::~AtsServerContext() {
-
-}

http://git-wip-us.apache.org/repos/asf/trafficserver/blob/e8b899b0/plugins/experimental/ats_speed/ats_server_context.h
----------------------------------------------------------------------
diff --git a/plugins/experimental/ats_speed/ats_server_context.h b/plugins/experimental/ats_speed/ats_server_context.h
deleted file mode 100644
index e156ed3..0000000
--- a/plugins/experimental/ats_speed/ats_server_context.h
+++ /dev/null
@@ -1,56 +0,0 @@
-/** @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.
-*/
-
-#ifndef ATS_SERVER_CONTEXT_H_
-#define ATS_SERVER_CONTEXT_H_
-
-#include "ats_rewrite_options.h"
-
-#include "net/instaweb/system/public/system_server_context.h"
-#include "net/instaweb/util/public/statistics.h"
-
-namespace net_instaweb {
-
-class AtsRewriteOptions;
-class AtsRewriteDriverFactory;
-
-class AtsServerContext : public net_instaweb::SystemServerContext {
- public:
-  explicit AtsServerContext(AtsRewriteDriverFactory* factory);
-  virtual ~AtsServerContext();
-
-  virtual bool ProxiesHtml() const {
-    return true;
-  }
-
-  AtsRewriteOptions *config();
-  AtsRewriteDriverFactory *ats_rewrite_driver_factory() { return ats_factory_; }
-
- private:
-  bool initialized_;
-  AtsRewriteDriverFactory* ats_factory_;
-};
-
-} /* ats_pagespeed */
-
-#endif /* ATS_SERVER_CONTEXT_H_ */

http://git-wip-us.apache.org/repos/asf/trafficserver/blob/e8b899b0/plugins/experimental/ats_speed/ats_speed.cc
----------------------------------------------------------------------
diff --git a/plugins/experimental/ats_speed/ats_speed.cc b/plugins/experimental/ats_speed/ats_speed.cc
deleted file mode 100644
index 7bde30c..0000000
--- a/plugins/experimental/ats_speed/ats_speed.cc
+++ /dev/null
@@ -1,1093 +0,0 @@
-/** @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.
-*/
-
-// TODO(oschaaf): remove what isn't used
-#ifndef __STDC_LIMIT_MACROS
-#define __STDC_LIMIT_MACROS
-#endif
-#include <stdlib.h>
-#include <errno.h>
-#include <stdio.h>
-#include <limits.h>
-#include <stdint.h>
-#include <sys/inotify.h>
-#include <unistd.h>
-
-#include <ts/ts.h>
-
-#include <vector>
-#include <set>
-
-
-#include "ats_speed.h"
-
-#include "ats_config.h"
-#include "ats_header_utils.h"
-#include "ats_rewrite_options.h"
-#include "ats_log_message_handler.h"
-
-#include "base/logging.h"
-#include "net/instaweb/http/public/response_headers.h"
-#include "net/instaweb/util/public/string_util.h"
-
-#include "ats_base_fetch.h"
-#include "ats_resource_intercept.h"
-#include "ats_beacon_intercept.h"
-#include "ats_process_context.h"
-#include "ats_rewrite_driver_factory.h"
-#include "ats_rewrite_options.h"
-#include "ats_server_context.h"
-
-#include "net/instaweb/rewriter/public/rewrite_stats.h"
-#include "net/instaweb/system/public/in_place_resource_recorder.h"
-
-#include "net/instaweb/automatic/public/proxy_fetch.h"
-#include "net/instaweb/http/public/content_type.h"
-#include "net/instaweb/http/public/request_context.h"
-#include "net/instaweb/rewriter/public/experiment_matcher.h"
-#include "net/instaweb/rewriter/public/experiment_util.h"
-#include "net/instaweb/rewriter/public/process_context.h"
-#include "net/instaweb/rewriter/public/resource_fetch.h"
-#include "net/instaweb/rewriter/public/rewrite_driver.h"
-#include "net/instaweb/rewriter/public/rewrite_query.h"
-#include "net/instaweb/rewriter/public/static_asset_manager.h"
-#include "net/instaweb/public/global_constants.h"
-#include "net/instaweb/public/version.h"
-#include "net/instaweb/util/public/google_message_handler.h"
-#include "net/instaweb/util/public/google_url.h"
-#include "net/instaweb/util/public/gzip_inflater.h"
-#include "net/instaweb/util/public/query_params.h"
-#include "net/instaweb/util/public/statistics_logger.h"
-#include "net/instaweb/util/public/stdio_file_system.h"
-#include "net/instaweb/util/public/string.h"
-#include "net/instaweb/util/public/string_writer.h"
-#include "net/instaweb/util/public/time_util.h"
-#include "net/instaweb/util/stack_buffer.h"
-#include "net/instaweb/system/public/system_request_context.h"
-
-
-#include <dirent.h>
-
-using namespace net_instaweb;
-
-static AtsProcessContext* ats_process_context;
-static const char* DEBUG_TAG = "ats_speed_transform";
-static int TXN_INDEX_ARG;
-static int TXN_INDEX_OWNED_ARG;
-static int TXN_INDEX_OWNED_ARG_SET;
-static int TXN_INDEX_OWNED_ARG_UNSET;
-TSMutex config_mutex = TSMutexCreate();
-AtsConfig* config = NULL;
-TransformCtx* get_transaction_context(TSHttpTxn txnp) {
-  return (TransformCtx *) TSHttpTxnArgGet(txnp, TXN_INDEX_ARG);
-}
-
-static TransformCtx *
-ats_ctx_alloc()
-{
-  TransformCtx *ctx;
- 
-  ctx = (TransformCtx *) TSmalloc(sizeof(TransformCtx));
-  ctx->downstream_vio = NULL;
-  ctx->downstream_buffer = NULL;
-  ctx->downstream_length = 0;
-  ctx->state = transform_state_initialized;
-
-  ctx->base_fetch = NULL;
-  ctx->proxy_fetch = NULL;
-  
-  ctx->inflater = NULL;
-  ctx->url_string = NULL;
-  ctx->gurl = NULL;
-  ctx->write_pending = false;
-  ctx->fetch_done = false;
-  ctx->resource_request = false;
-  ctx->beacon_request = false;
-  ctx->transform_added = false;
-  ctx->mps_user_agent = false;
-  ctx->user_agent = NULL;
-  ctx->server_context = NULL;
-  ctx->html_rewrite = false;
-  ctx->request_method = NULL;
-  ctx->alive = 0xaaaa;
-  ctx->options = NULL;
-  ctx->to_host = NULL;
-  return ctx;
-}
-
-void
-ats_ctx_destroy(TransformCtx * ctx)
-{
-  TSReleaseAssert(ctx);
-  CHECK(ctx->alive == 0xaaaa) << "Already dead!";
-  ctx->alive = 0xbbbb;
-
-  if (ctx->base_fetch != NULL) {
-    ctx->base_fetch->Release();
-    ctx->base_fetch = NULL;
-  }
-
-  if (ctx->proxy_fetch != NULL) {
-    ctx->proxy_fetch->Done(false /* failure */);
-    ctx->proxy_fetch = NULL;
-  }
-
-  if (ctx->inflater != NULL) {
-    delete ctx->inflater;
-    ctx->inflater = NULL;
-  }
-
-  if (ctx->downstream_buffer) {
-    TSIOBufferDestroy(ctx->downstream_buffer);
-  }
-
-  if (ctx->url_string != NULL) {
-    delete ctx->url_string;
-    ctx->url_string = NULL;
-  }
-
-  if (ctx->gurl != NULL) {
-    delete ctx->gurl;
-    ctx->gurl = NULL;
-  }
-  if (ctx->user_agent != NULL) {
-    delete ctx->user_agent;
-    ctx->user_agent = NULL;
-  }
-  ctx->request_method = NULL;
-  if (ctx->options != NULL) {
-    delete ctx->options;
-    ctx->options = NULL;
-  }
-  if (ctx->to_host != NULL) {
-    delete ctx->to_host;
-    ctx->to_host = NULL;
-  }
-  TSfree(ctx);
-}
-
-RewriteOptions* ps_determine_request_options(
-    ServerContext* server_context,
-    RequestHeaders* request_headers,
-    ResponseHeaders* response_headers,
-    GoogleUrl* url) {
-  // Stripping ModPagespeed query params before the property cache lookup to
-  // make cache key consistent for both lookup and storing in cache.
-  //
-  // Sets option from request headers and url.
-  RewriteQuery rewrite_query;
-  if (!server_context->GetQueryOptions(url, request_headers,
-				       response_headers, &rewrite_query)) {
-    // Failed to parse query params or request headers.  Treat this as if there
-    // were no query params given.
-    TSError("ps_route rerquest: parsing headers or query params failed.");
-    return NULL;
-  }
-
-  // Will be NULL if there aren't any options set with query params or in
-  // headers.
-  return rewrite_query.ReleaseOptions();
-}
-
-bool ps_determine_options(ServerContext* server_context,
-  // Directory-specific options, usually null.  They've already been rebased off
-  // of the global options as part of the configuration process.
-                          RewriteOptions* directory_options,
-                          RequestHeaders* request_headers,
-                          ResponseHeaders* response_headers,
-                          RewriteOptions** options,
-                          GoogleUrl* url) {
-  // Global options for this server.  Never null.
-  RewriteOptions* global_options = server_context->global_options();
-
-  // Request-specific options, nearly always null.  If set they need to be
-  // rebased on the directory options or the global options.
-  RewriteOptions* request_options = ps_determine_request_options(
-      server_context, request_headers, response_headers, url);
-
-  // Because the caller takes ownership of any options we return, the only
-  // situation in which we can avoid allocating a new RewriteOptions is if the
-  // global options are ok as are.
-  if (directory_options == NULL && request_options == NULL &&
-      !global_options->running_experiment()) {
-    return true;
-  }
-
-  // Start with directory options if we have them, otherwise request options.
-  if (directory_options != NULL) {
-    //*options = directory_options->Clone();
-    // OS: HACK! TODO!
-    *options = global_options->Clone();
-    (*options)->Merge(*directory_options);
-  } else {
-    *options = global_options->Clone();
-  }
-
-  // Modify our options in response to request options or experiment settings,
-  // if we need to.  If there are request options then ignore the experiment
-  // because we don't want experiments to be contaminated with unexpected
-  // settings.
-  if (request_options != NULL) {
-    (*options)->Merge(*request_options);
-    delete request_options;
-  }
-  // TODO(oschaaf): experiments
-  /*else if ((*options)->running_experiment()) {
-    bool ok = ps_set_experiment_state_and_cookie(
-        r, request_headers, *options, url->Host());
-    if (!ok) {
-      delete *options;
-      *options = NULL;
-      return false;
-      }
-  }*/
-
-  return true;
-}
-
-void
-handle_send_response_headers(TSHttpTxn txnp) {
-  TransformCtx* ctx = get_transaction_context(txnp);
-  // TODO(oschaaf): Fix the response headers!!
-  bool is_owned = TSHttpTxnArgGet(txnp, TXN_INDEX_OWNED_ARG) == &TXN_INDEX_OWNED_ARG_SET;
-  if (!is_owned) {
-    return;
-  }
-  CHECK(ctx->alive == 0xaaaa) << "Already dead !";
-  if (ctx->html_rewrite) {
-    TSMBuffer bufp = NULL;
-    TSMLoc hdr_loc = NULL;
-    if (ctx->base_fetch == NULL) {
-      // TODO(oschaaf): figure out when this happens.
-      return;
-    }
-    
-    if (TSHttpTxnClientRespGet(txnp, &bufp, &hdr_loc) == TS_SUCCESS) {
-      ResponseHeaders* pagespeed_headers =
-          ctx->base_fetch->response_headers();
-      for (int i = 0 ; i < pagespeed_headers->NumAttributes() ; i++) {
-        const GoogleString& name_gs = pagespeed_headers->Name(i);
-        const GoogleString& value_gs = pagespeed_headers->Value(i);
-
-        // We should avoid touching these fields, as ATS will drop keepalive when we do.
-        if ( StringCaseEqual(name_gs, "Connection") || StringCaseEqual(name_gs, "Transfer-Encoding") ) {
-          continue;
-        }
-        
-        TSMLoc field_loc = TSMimeHdrFieldFind(bufp, hdr_loc, name_gs.data(), name_gs.size());
-        if (field_loc != NULL) {
-          TSMimeHdrFieldValuesClear(bufp, hdr_loc, field_loc);
-          TSMimeHdrFieldValueStringInsert(bufp, hdr_loc, field_loc, -1,
-                                          value_gs.data(), value_gs.size());
-        } else if (TSMimeHdrFieldCreate(bufp, hdr_loc, &field_loc) == TS_SUCCESS) {
-          if (TSMimeHdrFieldNameSet(bufp, hdr_loc, field_loc, name_gs.data(), name_gs.size()) == TS_SUCCESS) {
-            TSMimeHdrFieldValueStringInsert(bufp, hdr_loc, field_loc, -1,
-                                            value_gs.data(), value_gs.size());
-            TSMimeHdrFieldAppend(bufp, hdr_loc, field_loc);
-          } else {
-            CHECK(false) << "Field name set failure";
-          }
-          TSHandleMLocRelease(bufp, hdr_loc, field_loc);
-        } else {
-          CHECK(false) << "Field create failure";
-        }        
-      }
-      
-      TSHandleMLocRelease(bufp, TS_NULL_MLOC, hdr_loc);
-    } else  {
-      DCHECK(false) << "Could not get response headers?!";
-    }
-  }
-}
-
-static void
-copy_response_headers_to_psol(TSMBuffer bufp, TSMLoc hdr_loc, ResponseHeaders* psol_headers) {
-  int n_mime_headers = TSMimeHdrFieldsCount(bufp, hdr_loc);
-  TSMLoc field_loc;
-  const char *name, *value;
-  int name_len, value_len;
-  GoogleString header;
-  for (int i = 0; i < n_mime_headers; ++i) {
-    field_loc = TSMimeHdrFieldGet(bufp, hdr_loc, i);
-    if (!field_loc) {
-      TSDebug(DEBUG_TAG, "[%s] Error while obtaining header field #%d", __FUNCTION__, i);
-      continue;
-    }
-    name = TSMimeHdrFieldNameGet(bufp, hdr_loc, field_loc, &name_len);
-    StringPiece s_name(name, name_len);
-    int n_field_values = TSMimeHdrFieldValuesCount(bufp, hdr_loc, field_loc);
-    for (int j = 0; j < n_field_values; ++j) {
-      value = TSMimeHdrFieldValueStringGet(bufp, hdr_loc, field_loc, j, &value_len);
-      if ( NULL == value || !value_len ) {
-        TSDebug(DEBUG_TAG, "[%s] Error while getting value #%d of header [%.*s]",
-                __FUNCTION__, j, name_len, name);
-      } else {
-        StringPiece s_value(value, value_len);
-        psol_headers->Add(s_name, s_value);
-        //TSDebug(DEBUG_TAG, "Add response header [%.*s:%.*s]",name_len, name, value_len, value);
-      }
-    }
-    TSHandleMLocRelease(bufp, hdr_loc, field_loc);
-  }
-}
-
-void
-copy_request_headers_to_psol(TSMBuffer bufp, TSMLoc hdr_loc, RequestHeaders* psol_headers) {
-  int n_mime_headers = TSMimeHdrFieldsCount(bufp, hdr_loc);
-  TSMLoc field_loc;
-  const char *name, *value;
-  int name_len, value_len;
-  GoogleString header;
-  for (int i = 0; i < n_mime_headers; ++i) {
-    field_loc = TSMimeHdrFieldGet(bufp, hdr_loc, i);
-    if (!field_loc) {
-      TSDebug(DEBUG_TAG, "[%s] Error while obtaining header field #%d", __FUNCTION__, i);
-      continue;
-    }
-    name = TSMimeHdrFieldNameGet(bufp, hdr_loc, field_loc, &name_len);
-    StringPiece s_name(name, name_len);
-    int n_field_values = TSMimeHdrFieldValuesCount(bufp, hdr_loc, field_loc);
-    for (int j = 0; j < n_field_values; ++j) {
-      value = TSMimeHdrFieldValueStringGet(bufp, hdr_loc, field_loc, j, &value_len);
-      if ( NULL == value || !value_len ) {
-        TSDebug(DEBUG_TAG, "[%s] Error while getting value #%d of header [%.*s]",
-                __FUNCTION__, j, name_len, name);
-      } else {
-        StringPiece s_value(value, value_len);
-        psol_headers->Add(s_name, s_value);
-        //TSDebug(DEBUG_TAG, "Add request header [%.*s:%.*s]",name_len, name, value_len, value);
-      }
-    }
-    TSHandleMLocRelease(bufp, hdr_loc, field_loc);
-  }
-}
-
-// TODO(oschaaf): this is not sustainable when we get more
-// configuration options like this.
-bool get_override_expiry(const StringPiece& host) {
-  TSMutexLock(config_mutex);
-  AtsHostConfig* hc = config->Find(host.data(), host.size());
-  TSMutexUnlock(config_mutex);
-  return hc->override_expiry();
-}
-
-AtsRewriteOptions* get_host_options(const StringPiece& host) {
-  TSMutexLock(config_mutex);
-  AtsRewriteOptions* r = NULL;
-  AtsHostConfig* hc = config->Find(host.data(), host.size());
-  if (hc->options() != NULL) {
-    // We return a clone here to avoid having to thing about
-    // configuration reloads and outstanding options
-    r = hc->options()->Clone();
-  }
-  TSMutexUnlock(config_mutex);
-  return r;
-}
-
-std::string get_remapped_host(TSHttpTxn txn) {
-  TSMBuffer server_req_buf;
-  TSMLoc server_req_loc;
-  std::string to_host;
-  if (TSHttpTxnServerReqGet(txn, &server_req_buf, &server_req_loc) == TS_SUCCESS
-      || TSHttpTxnCachedReqGet(txn, &server_req_buf, &server_req_loc) == TS_SUCCESS) {
-    to_host = get_header(server_req_buf, server_req_loc, "Host");
-    TSHandleMLocRelease(server_req_buf, TS_NULL_MLOC, server_req_loc);
-  } else  {
-    fprintf(stderr, "@@@@@@@ FAILED \n");
-  }
-  return to_host;
-}
-
-static void
-ats_transform_init(TSCont contp, TransformCtx * ctx)
-{
-  //prepare the downstream for transforming
-  TSVConn downstream_conn;
-  TSMBuffer bufp;
-  TSMLoc hdr_loc;
-  TSMBuffer reqp;
-  TSMLoc req_hdr_loc;
-  ctx->state = transform_state_output;
-
-
-  // TODO: check cleanup flow
-  if (TSHttpTxnTransformRespGet(ctx->txn, &bufp, &hdr_loc) != TS_SUCCESS) {
-    TSError("Error TSHttpTxnTransformRespGet");
-    return;
-  }
-  if (TSHttpTxnClientReqGet(ctx->txn, &reqp, &req_hdr_loc) != TS_SUCCESS) {
-    TSError("Error TSHttpTxnClientReqGet");
-    return;
-  }
-  
-  AtsServerContext* server_context = ats_process_context->server_context();
-  if (server_context->IsPagespeedResource(*ctx->gurl)) {
-    CHECK(false) << "PageSpeed resource should not get here!";
-  }
-
-  downstream_conn = TSTransformOutputVConnGet(contp);
-  ctx->downstream_buffer = TSIOBufferCreate();
-  ctx->downstream_vio = TSVConnWrite(downstream_conn, contp, TSIOBufferReaderAlloc(ctx->downstream_buffer), INT64_MAX);
-
-  // TODO(oschaaf): fix host/ip(?)
-  SystemRequestContext* system_request_context = 
-    new SystemRequestContext(server_context->thread_system()->NewMutex(),
-			     server_context->timer(),
-			     "www.foo.com",
-			     80,
-			     "127.0.0.1");
-
-  ctx->base_fetch = new AtsBaseFetch(server_context, RequestContextPtr(system_request_context),
-                                      ctx->downstream_vio, ctx->downstream_buffer, false);
-
-  
-  RewriteOptions* options = NULL;
-  RequestHeaders* request_headers = new RequestHeaders();
-  ctx->base_fetch->SetRequestHeadersTakingOwnership(request_headers);
-  copy_request_headers_to_psol(reqp, req_hdr_loc, request_headers);
- 
-  TSHttpStatus status = TSHttpHdrStatusGet(bufp, hdr_loc);
-  // TODO(oschaaf): http version
-  ctx->base_fetch->response_headers()->set_status_code(status);
-  copy_response_headers_to_psol(bufp, hdr_loc, ctx->base_fetch->response_headers());
-  ctx->base_fetch->response_headers()->ComputeCaching();
-  const char* host = ctx->gurl->HostAndPort().as_string().c_str();
-      //request_headers->Lookup1(HttpAttributes::kHost);
-  if (host != NULL && strlen(host) > 0) {
-    ctx->options = get_host_options(host);
-  }
-  bool ok = ps_determine_options(server_context,
-                                 ctx->options,
-                                 request_headers,
-                                 ctx->base_fetch->response_headers(),
-                                 &options,
-                                 ctx->gurl);
-
-  // Take ownership of custom_options.
-  scoped_ptr<RewriteOptions> custom_options(options);
-  
-  if (!ok) {
-    TSError("Failure while determining request options for psol");
-    options = server_context->global_options();
-  } else {
-    // ps_determine_options modified url, removing any ModPagespeedFoo=Bar query
-    // parameters.  Keep url_string in sync with url.
-    ctx->gurl->Spec().CopyToString(ctx->url_string);
-  }
-  
-  RewriteDriver* driver;
-  if (custom_options.get() == NULL) {
-    driver = server_context->NewRewriteDriver(ctx->base_fetch->request_context());
-  } else {
-    driver = server_context->NewCustomRewriteDriver(custom_options.release(), ctx->base_fetch->request_context());
-  }
-  
-  driver->SetUserAgent(ctx->user_agent->c_str());
-  driver->SetRequestHeaders(*request_headers);
-   
-  bool page_callback_added = false;
-  scoped_ptr<ProxyFetchPropertyCallbackCollector>
-      property_callback(
-          ProxyFetchFactory::InitiatePropertyCacheLookup(
-              false /*  is resource fetch?*/,
-              *ctx->gurl,
-              server_context,
-              options,
-              ctx->base_fetch,
-              false /* requires_blink_cohort (no longer unused) */,
-              &page_callback_added));
-  
-  ctx->proxy_fetch =
-    ats_process_context->proxy_fetch_factory()->CreateNewProxyFetch(
-								    *(ctx->url_string), ctx->base_fetch, driver,
-                                                                    property_callback.release(),
-								  NULL /* original_content_fetch */);
-
-  TSHandleMLocRelease(reqp, TS_NULL_MLOC, req_hdr_loc);
-  TSHandleMLocRelease(bufp, TS_NULL_MLOC, hdr_loc);
-}
-
-static void
-ats_transform_one(TransformCtx * ctx, TSIOBufferReader upstream_reader, int amount)
-{
-  TSIOBufferBlock downstream_blkp;
-  const char *upstream_buffer;
-  int64_t upstream_length;
-
-  while (amount > 0) {
-    downstream_blkp = TSIOBufferReaderStart(upstream_reader);
-    if (!downstream_blkp) {
-      TSError("couldn't get from IOBufferBlock");
-      return;
-    }
-
-    upstream_buffer = TSIOBufferBlockReadStart(downstream_blkp, upstream_reader, &upstream_length);
-    if (!upstream_buffer) {
-      TSError("couldn't get from TSIOBufferBlockReadStart");
-      return;
-    }
-
-    if (upstream_length > amount) {
-      upstream_length = amount;
-    }
-    
-    TSDebug("ats-speed", "transform!");
-    // TODO(oschaaf): use at least the message handler from the server conrtext here?
-    if (ctx->inflater == NULL) {
-      ctx->proxy_fetch->Write(StringPiece((char*)upstream_buffer, upstream_length), ats_process_context->message_handler());
-    } else {
-      char buf[net_instaweb::kStackBufferSize];
-      
-      ctx->inflater->SetInput((char*)upstream_buffer, upstream_length);
-      
-      while (ctx->inflater->HasUnconsumedInput()) {
-        int num_inflated_bytes = ctx->inflater->InflateBytes(
-            buf, net_instaweb::kStackBufferSize);
-        if (num_inflated_bytes < 0) {
-          TSError("Corrupted inflation");
-        } else if (num_inflated_bytes > 0) {
-          ctx->proxy_fetch->Write(StringPiece(buf, num_inflated_bytes),
-                                   ats_process_context->message_handler());
-        }
-      }
-    }
-    //ctx->proxy_fetch->Flush(NULL);
-    TSIOBufferReaderConsume(upstream_reader, upstream_length);
-    amount -= upstream_length;
-  }
-  // TODO(oschaaf): get the output from the base fetch, and send it downstream.
-  // This would require proper locking around the base fetch buffer
-  // We could also have a look at directly writing to the traffic server buffers
-}
-
-
-static void
-ats_transform_finish(TransformCtx * ctx)
-{
-  if (ctx->state == transform_state_output) {
-    ctx->state = transform_state_finished;
-    ctx->proxy_fetch->Done(true);
-    ctx->proxy_fetch = NULL;
-  }
-}
-
-static void
-ats_transform_do(TSCont contp)
-{
-  TSVIO upstream_vio;
-  TransformCtx *ctx;
-  int64_t upstream_todo;
-  int64_t upstream_avail;
-  int64_t downstream_bytes_written;
-
-  ctx = (TransformCtx*)TSContDataGet(contp);
-
-  if (ctx->state == transform_state_initialized) {
-    ats_transform_init(contp, ctx);
-  }
-
-  upstream_vio = TSVConnWriteVIOGet(contp);
-  downstream_bytes_written = ctx->downstream_length;
-
-  if (!TSVIOBufferGet(upstream_vio)) {
-    ats_transform_finish(ctx);
-    return;
-  }
-
-  upstream_todo = TSVIONTodoGet(upstream_vio);
-
-  if (upstream_todo > 0) {
-    upstream_avail = TSIOBufferReaderAvail(TSVIOReaderGet(upstream_vio));
-
-    if (upstream_todo > upstream_avail) {
-      upstream_todo = upstream_avail;
-    }
-
-    if (upstream_todo > 0) {
-      ats_transform_one(ctx, TSVIOReaderGet(upstream_vio), upstream_todo);
-      TSVIONDoneSet(upstream_vio, TSVIONDoneGet(upstream_vio) + upstream_todo);
-    }
-  }
-
-  if (TSVIONTodoGet(upstream_vio) > 0) {
-    if (upstream_todo > 0) {
-      if (ctx->downstream_length > downstream_bytes_written) {
-        TSVIOReenable(ctx->downstream_vio);
-      }
-      TSContCall(TSVIOContGet(upstream_vio), TS_EVENT_VCONN_WRITE_READY, upstream_vio);
-    }
-  } else {
-    ats_transform_finish(ctx);
-    TSContCall(TSVIOContGet(upstream_vio), TS_EVENT_VCONN_WRITE_COMPLETE, upstream_vio);
-  }
-}
-
-
-static int
-ats_speed_transform(TSCont contp, TSEvent event, void * /* edata ATS_UNUSED */)
-{
-  if (TSVConnClosedGet(contp)) {
-    //ats_ctx_destroy((TransformCtx*)TSContDataGet(contp));
-    TSContDestroy(contp);
-    return 0;
-  } else {
-    switch (event) {
-    case TS_EVENT_ERROR:{
-      fprintf(stderr, "ats speed transform event: [%d] TS EVENT ERROR?!\n", event);
-      TSVIO upstream_vio = TSVConnWriteVIOGet(contp);
-      TSContCall(TSVIOContGet(upstream_vio), TS_EVENT_ERROR, upstream_vio);
-    }
-      break;
-    case TS_EVENT_VCONN_WRITE_COMPLETE:
-      TSVConnShutdown(TSTransformOutputVConnGet(contp), 0, 1);
-      break;
-    case TS_EVENT_VCONN_WRITE_READY:
-      ats_transform_do(contp);
-      break;
-    case TS_EVENT_IMMEDIATE:
-      ats_transform_do(contp);
-      break;
-    default:
-      DCHECK(false) << "unknown event: " << event;
-      ats_transform_do(contp);
-      break;
-    }
-  }
-
-  return 0;
-}
-
-static void
-ats_speed_transform_add(TSHttpTxn txnp)
-{
-  TransformCtx* ctx = get_transaction_context(txnp);
-  CHECK(ctx);
-  if (ctx->transform_added) { // Happens with a stale cache hit
-    return;
-  } else {
-    ctx->transform_added = true;
-  }
-
-  TSHttpTxnUntransformedRespCache(txnp, 1);
-  TSHttpTxnTransformedRespCache(txnp, 0);
-
-  TSVConn connp;
-
-  connp = TSTransformCreate(ats_speed_transform, txnp);
-  TSContDataSet(connp, ctx);
-  TSHttpTxnHookAdd(txnp, TS_HTTP_RESPONSE_TRANSFORM_HOOK, connp);
-}
-
-// Returns true if a server intercept was set up
-// Which means we should not attempt any further transformation
-void
-handle_read_request_header(TSHttpTxn txnp) {
-  TSMBuffer reqp = NULL;
-  TSMLoc hdr_loc = NULL;
-  char *url = NULL;
-  int url_length = -1;
-  
-  TransformCtx* ctx = ats_ctx_alloc();
-  ctx->txn = txnp;
-  TSHttpTxnArgSet(txnp, TXN_INDEX_ARG, (void*) ctx);
-  TSHttpTxnArgSet(txnp, TXN_INDEX_OWNED_ARG, &TXN_INDEX_OWNED_ARG_SET);
-  
-  if (TSHttpTxnClientReqGet(txnp, &reqp, &hdr_loc) == TS_SUCCESS) {
-    url = TSHttpTxnEffectiveUrlStringGet(txnp, &url_length);
-    if (!url || url_length <= 0) {
-      DCHECK(false) << "Could not get url!";
-    } else {
-      std::string s_url = std::string(url,url_length);
-      GoogleUrl gurl(s_url);
- 
-      ctx->url_string = new GoogleString(url, url_length);
-      ctx->gurl = new GoogleUrl(*(ctx->url_string));
-      if (!ctx->gurl->IsWebValid()) {
-        TSDebug("ats-speed", "URL != WebValid(): %s", ctx->url_string->c_str());
-      } else {
-        const char * method;
-        int method_len;
-        method = TSHttpHdrMethodGet(reqp, hdr_loc, &method_len);
-        bool head_or_get = method == TS_HTTP_METHOD_GET || method == TS_HTTP_METHOD_HEAD;
-        ctx->request_method = method;
-        GoogleString user_agent = get_header(reqp, hdr_loc, "User-Agent");
-        ctx->user_agent = new GoogleString(user_agent);
-        ctx->server_context = ats_process_context->server_context();
-        if (user_agent.find(kModPagespeedSubrequestUserAgent) != user_agent.npos) {
-          ctx->mps_user_agent = true;
-        }
-        if (ats_process_context->server_context()->IsPagespeedResource(gurl)) {
-          if (head_or_get && !ctx->mps_user_agent) { 
-            ctx->resource_request = true;
-            TSHttpTxnArgSet(txnp, TXN_INDEX_OWNED_ARG, &TXN_INDEX_OWNED_ARG_UNSET);
-          }
-        } else if (ctx->gurl->PathSansQuery() == "/pagespeed_message"
-                   || ctx->gurl->PathSansQuery() == "/pagespeed_statistics"
-                   || ctx->gurl->PathSansQuery() == "/pagespeed_global_statistics"
-                   || ctx->gurl->PathSansQuery() == "/pagespeed_console"
-                   || ctx->gurl->PathSansLeaf() == "/ats_speed_static/"
-                   || ctx->gurl->PathSansQuery() == "/robots.txt"
-                   ) {
-          ctx->resource_request = true;
-          TSHttpTxnArgSet(txnp, TXN_INDEX_OWNED_ARG, &TXN_INDEX_OWNED_ARG_UNSET);
-        }
-        else if (StringCaseEqual(gurl.PathSansQuery() ,"/ats_speed_beacon")) {
-          ctx->beacon_request = true;
-          TSHttpTxnArgSet(txnp, TXN_INDEX_OWNED_ARG, &TXN_INDEX_OWNED_ARG_UNSET);
-          hook_beacon_intercept(txnp);
-        }
-      }
-      TSfree((void*)url);
-    } // gurl->IsWebValid() == true
-    TSHandleMLocRelease(reqp, TS_NULL_MLOC, hdr_loc);
-  } else {
-    DCHECK(false) << "Could not get client request header\n";
-  }
-  
-  TSHttpTxnReenable(txnp, TS_EVENT_HTTP_CONTINUE);
-}
-
-bool
-cache_hit(TSHttpTxn txnp) {
-  int obj_status;
-  if (TSHttpTxnCacheLookupStatusGet(txnp, &obj_status) == TS_ERROR) {
-    // TODO(oschaaf): log warning
-    return false;
-  }
-  return obj_status == TS_CACHE_LOOKUP_HIT_FRESH;
-}
-
-static int
-transform_plugin(TSCont contp, TSEvent event, void *edata)
-{
-  TSHttpTxn txn = (TSHttpTxn) edata;
-
-  CHECK(event == TS_EVENT_HTTP_READ_RESPONSE_HDR || event == TS_EVENT_HTTP_READ_CACHE_HDR
-        || event == TS_EVENT_HTTP_SEND_REQUEST_HDR || event == TS_EVENT_HTTP_READ_REQUEST_HDR
-        || event == TS_EVENT_HTTP_TXN_CLOSE || event == TS_EVENT_HTTP_SEND_RESPONSE_HDR) 
-      << "Invalid transform event";
-
-  if (event != TS_EVENT_HTTP_READ_REQUEST_HDR) {
-    // Bail if an intercept is running
-    bool is_owned = TSHttpTxnArgGet(txn, TXN_INDEX_OWNED_ARG) == &TXN_INDEX_OWNED_ARG_SET;
-    if (!is_owned) {
-      TSHttpTxnReenable(txn, TS_EVENT_HTTP_CONTINUE);
-      return 0;
-    }
-  }
-
-  if (event == TS_EVENT_HTTP_SEND_RESPONSE_HDR) {
-    handle_send_response_headers(txn);
-    TSHttpTxnReenable(txn, TS_EVENT_HTTP_CONTINUE);
-    return 0;
-  } if (event == TS_EVENT_HTTP_TXN_CLOSE) {
-    TransformCtx* ctx = get_transaction_context(txn);
-    //if (ctx != NULL && !ctx->resource_request && !ctx->beacon_request && !ctx->html_rewrite) {
-    // For intercepted requests like beacons and resource requests, we don't own the 
-    // ctx here - the interceptor does.
-    
-    if (ctx != NULL) {
-      bool is_owned = TSHttpTxnArgGet(txn, TXN_INDEX_OWNED_ARG) == &TXN_INDEX_OWNED_ARG_SET;
-      if (is_owned) {
-        ats_ctx_destroy(ctx);
-      }
-    }
-    TSHttpTxnReenable(txn, TS_EVENT_HTTP_CONTINUE);
-    return 0;
-  } if (event == TS_EVENT_HTTP_READ_REQUEST_HDR) {
-    handle_read_request_header(txn);
-    return 0;    
-  } else if (event == TS_EVENT_HTTP_SEND_REQUEST_HDR) {
-    TSMBuffer request_header_buf = NULL;
-    TSMLoc request_header_loc = NULL;
-  
-    if (TSHttpTxnServerReqGet(txn, &request_header_buf, &request_header_loc) == TS_SUCCESS) {
-      hide_accept_encoding(request_header_buf, request_header_loc, "@xxAccept-Encoding");
-      // Turn off pagespeed optimization at the origin
-      set_header(request_header_buf, request_header_loc, "PageSpeed", "off");
-      TSHandleMLocRelease(request_header_buf, TS_NULL_MLOC, request_header_loc);
-    } else {
-      CHECK(false) << "Could not find server request header";
-    }
-    TSHttpTxnReenable(txn, TS_EVENT_HTTP_CONTINUE);
-    return 0;
-  } else if (event == TS_EVENT_HTTP_READ_RESPONSE_HDR) {
-    TSMBuffer request_header_buf = NULL;
-    TSMLoc request_header_loc = NULL;
-    
-    if (TSHttpTxnServerReqGet(txn, &request_header_buf, &request_header_loc) == TS_SUCCESS) {
-      restore_accept_encoding(request_header_buf, request_header_loc, "@xxAccept-Encoding");
-      TSHandleMLocRelease(request_header_buf, TS_NULL_MLOC, request_header_loc);
-    } else {
-      CHECK(false) << "Could not find server request header";
-    }
-  }
-
-  CHECK(event == TS_EVENT_HTTP_READ_RESPONSE_HDR || event == TS_EVENT_HTTP_READ_CACHE_HDR);
-
-  TransformCtx* ctx = get_transaction_context(txn);
-  if (ctx == NULL) {
-      // TODO(oschaaf): document how and when this happens.
-    TSHttpTxnReenable(txn, TS_EVENT_HTTP_CONTINUE);
-    return 0;
-  }
-  std::string* to_host = new std::string();
-  to_host->append(get_remapped_host(ctx->txn));
-  ctx->to_host = to_host;
-  TSMBuffer response_header_buf = NULL;
-  TSMLoc response_header_loc = NULL;
-
-  // TODO(oschaaf): from configuration!
-  bool override_expiry = false;
-
-  const char* host = ctx->gurl->HostAndPort().as_string().c_str();
-      //request_headers->Lookup1(HttpAttributes::kHost);
-  if (host != NULL && strlen(host) > 0) {
-    override_expiry = get_override_expiry(host);
-  }
-
-  
-  if (ctx->mps_user_agent && override_expiry) {
-    if (TSHttpTxnServerRespGet(txn, &response_header_buf, &response_header_loc) == TS_SUCCESS) {
-      // TODO => set cacheable.
-      unset_header(response_header_buf, response_header_loc, "Cache-Control");
-      unset_header(response_header_buf, response_header_loc, "Expires");
-      unset_header(response_header_buf, response_header_loc, "Age");
-      set_header(response_header_buf, response_header_loc, "Cache-Control", "public, max-age=3600");    
-      TSHandleMLocRelease(response_header_buf, TS_NULL_MLOC, response_header_loc);    
-    }
-  }
-  bool ok = ctx->gurl->IsWebValid() &&
-            !(ctx->resource_request || ctx->beacon_request || ctx->mps_user_agent);
-  if (!ok) {
-    TSHttpTxnReenable(txn, TS_EVENT_HTTP_CONTINUE);
-    return 0;
-  }
-  
-  bool have_response_header = false;
-  
-  if (TSHttpTxnServerRespGet(txn, &response_header_buf, &response_header_loc) == TS_SUCCESS) {
-    have_response_header = true;
-    if (override_expiry) {
-      unset_header(response_header_buf, response_header_loc, "Cache-Control");
-      unset_header(response_header_buf, response_header_loc, "Expires");
-      unset_header(response_header_buf, response_header_loc, "Age");
-      set_header(response_header_buf, response_header_loc, "Cache-Control", "public, max-age=3600");
-    }
-  }
-  else if (TSHttpTxnCachedRespGet(txn, &response_header_buf, &response_header_loc) == TS_SUCCESS) {
-    have_response_header = true;
-  }  
-  if (!have_response_header) {
-    TSHttpTxnReenable(txn, TS_EVENT_HTTP_CONTINUE);
-    return 0;
-  }
-
-  if (ok) {
-    if (ctx->request_method != TS_HTTP_METHOD_GET && ctx->request_method != TS_HTTP_METHOD_HEAD
-        && ctx->request_method != TS_HTTP_METHOD_POST) {
-      ok = false;
-      TSHttpTxnReenable(txn, TS_EVENT_HTTP_CONTINUE);
-      return 0;
-    }
-  }
-
-  TSHttpStatus status = TSHttpHdrStatusGet(response_header_buf, response_header_loc);
-  if (ok) {
-    if (!(status == TS_HTTP_STATUS_OK || status == TS_HTTP_STATUS_NOT_FOUND)) {
-      ok = false;
-      TSHttpTxnReenable(txn, TS_EVENT_HTTP_CONTINUE);
-      return 0;
-    }
-  }
-  if (ok) { 
-    StringPiece s_content_type = get_header(response_header_buf, response_header_loc, "Content-Type");
-    const net_instaweb::ContentType* content_type =
-        net_instaweb::MimeTypeToContentType(s_content_type);
-
-    if ((content_type == NULL || !content_type->IsHtmlLike())) {
-      ok = false;
-      TSHttpTxnReenable(txn, TS_EVENT_HTTP_CONTINUE);
-      return 0;
-    }
-  }
-  
-  if (ok) {
-    StringPiece content_encoding = get_header(response_header_buf, response_header_loc, "Content-Encoding");
-    net_instaweb::GzipInflater::InflateType inflate_type;
-    bool is_encoded = false;
-  
-    if (StringCaseEqual(content_encoding, "deflate")) {
-      is_encoded = true;
-      inflate_type = GzipInflater::kDeflate;
-    } else if (StringCaseEqual(content_encoding, "gzip")) {
-      is_encoded = true;
-      inflate_type = GzipInflater::kGzip;
-    }
-
-    if (is_encoded) {
-      ctx->inflater = new GzipInflater(inflate_type);
-      ctx->inflater->Init();
-    }
-    TSDebug(DEBUG_TAG, "Will optimize [%s]", ctx->url_string->c_str());
-    ctx->html_rewrite = true;
-    set_header(response_header_buf,response_header_loc,"@gzip_nocache","0");
-    ats_speed_transform_add(txn);
-  }
-
-  TSHandleMLocRelease(response_header_buf, TS_NULL_MLOC, response_header_loc);    
-  TSHttpTxnReenable(txn, TS_EVENT_HTTP_CONTINUE);
-    
-  return 0;
-}
-
-bool RegisterPlugin() {
-  TSPluginRegistrationInfo info;
-
-  info.plugin_name = (char *)"ats_speed";
-  info.vendor_name = (char *)"Apache Software Foundation";
-  info.support_email = (char *)"dev@trafficserver.apache.org";
-
-  if (TSPluginRegister(TS_SDK_VERSION_3_0, &info) != TS_SUCCESS) {
-    TSError("Failed to register ATSSpeed");
-    return false;
-  }
-
-  return true;
-}
-
-void cleanup_process() {
-  delete ats_process_context;
-  AtsRewriteDriverFactory::Terminate(); 
-  AtsRewriteOptions::Terminate(); 
-}
-
-static void
-process_configuration()
-{
-  AtsConfig* new_config = new AtsConfig((AtsThreadSystem*)ats_process_context->server_context()->thread_system());
-  DIR *dir;
-  struct dirent *ent;
-  
-  if ((dir = opendir ("/usr/local/etc/trafficserver/psol/")) != NULL) {
-    while ((ent = readdir (dir)) != NULL) {
-      size_t len = strlen(ent->d_name);
-      if (len <= 0) continue;
-      if (ent->d_name[0] == '.') continue;
-      if (ent->d_name[len-1] == '~') continue;
-      if (ent->d_name[0] == '#') continue;
-      GoogleString s("/usr/local/etc/trafficserver/psol/");
-      s.append(ent->d_name);
-      fprintf (stderr, "parse [%s]\n", s.c_str());
-      if (!new_config->Parse(s.c_str())) {
-        TSError("Error parsing %s", s.c_str());
-      }
-    }
-    closedir (dir);
-  }
-
-  AtsConfig* old_config;
-  TSMutexLock(config_mutex);
-  fprintf(stderr, "Update configuration\n");
-  old_config = config;
-  config = new_config;
-  TSMutexUnlock(config_mutex);
-  if (old_config != NULL) {
-    delete old_config;
-  }
-}
-
-static void *
-config_notification_callback(void *data)
-{
-  int BUF_MAX = 1024 * (sizeof(struct inotify_event) + 16);
-  char buf[BUF_MAX];
-  int fd,wd;
-  
-  fd = inotify_init();
-
-  if (fd < 0) {
-    perror( "inotify_init" );
-    CHECK(false) << "Failed to initialize inotify";
-  }
-  
-  wd = inotify_add_watch(fd, "/usr/local/etc/trafficserver/psol/", IN_MODIFY | IN_CREATE | IN_DELETE);
-
-  while (1) {
-    int len = read(fd, buf, BUF_MAX);
-    int i = 0;
-    bool do_update = false;
-    while ( i < len ) {
-      struct inotify_event *event = ( struct inotify_event * ) &buf[ i ];
-      if ( event->len ) {
-        if (!(event->mask & IN_ISDIR)) {
-          const char* name = event->name;
-          size_t name_len = strlen(event->name);
-          if (name_len > 0 && name[0] != '.' && name[0] != '#' && name[name_len-1] != '~' ) {
-            do_update = true;
-          }
-        }
-      }
-      i += ( sizeof (struct inotify_event) ) + event->len;
-    }
-    if (do_update) {
-      process_configuration();
-    }
-  }
-
-  inotify_rm_watch( fd, wd );
-  close( fd );
-
-  return NULL;
-}
-
-
-void TSPluginInit(int argc, const char *argv[]) {
-  if (RegisterPlugin() == true) {
-    if (TSHttpArgIndexReserve("ats_speed", "Stores the transaction context", &TXN_INDEX_ARG) != TS_SUCCESS) {
-      CHECK(false) << "failed to reserve an argument index";
-    }
-    if (TSHttpArgIndexReserve("ats_speed", "Stores the transaction context", &TXN_INDEX_OWNED_ARG) != TS_SUCCESS) {
-      CHECK(false) << "failed to reserve an argument index";
-    }
-
-    AtsRewriteOptions::Initialize(); 
-    AtsRewriteDriverFactory::Initialize(); 
-    net_instaweb::log_message_handler::Install();
-    atexit(cleanup_process);
-    ats_process_context = new AtsProcessContext();
-    process_configuration();
-    TSCont transform_contp = TSContCreate(transform_plugin, NULL);
-    TSHttpHookAdd(TS_HTTP_READ_RESPONSE_HDR_HOOK, transform_contp);
-    TSHttpHookAdd(TS_HTTP_READ_CACHE_HDR_HOOK, transform_contp);
-    TSHttpHookAdd(TS_HTTP_SEND_REQUEST_HDR_HOOK, transform_contp);
-    TSHttpHookAdd(TS_HTTP_READ_REQUEST_HDR_HOOK, transform_contp);
-    TSHttpHookAdd(TS_HTTP_TXN_CLOSE_HOOK, transform_contp);
-    TSHttpHookAdd(TS_HTTP_SEND_RESPONSE_HDR_HOOK, transform_contp);
-
-    setup_resource_intercept();
-    CHECK(TSThreadCreate(config_notification_callback, NULL)) << "";
-    ats_process_context->message_handler()->Message(
-        kInfo, "TSPluginInit OK");
-  }
-}

http://git-wip-us.apache.org/repos/asf/trafficserver/blob/e8b899b0/plugins/experimental/ats_speed/ats_speed.h
----------------------------------------------------------------------
diff --git a/plugins/experimental/ats_speed/ats_speed.h b/plugins/experimental/ats_speed/ats_speed.h
deleted file mode 100644
index 5f46992..0000000
--- a/plugins/experimental/ats_speed/ats_speed.h
+++ /dev/null
@@ -1,102 +0,0 @@
-/** @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.
-*/
-
-#ifndef ATS_SPEED_H_
-#define ATS_SPEED_H_
-
-#include <string>
-
-#include <ts/ts.h>
-
-#include "net/instaweb/util/public/google_url.h"
-#include "net/instaweb/util/public/string.h"
-#include "net/instaweb/util/public/string_util.h"
-
-namespace net_instaweb {
-
-class AtsBaseFetch;
-class AtsRewriteOptions;
-class AtsServerContext;
-class GzipInflater;
-class ProxyFetch;
-class RewriteOptions;
-class RequestHeaders;
-class ResponseHeaders;
-class ServerContext;
-
-}  // namespace net_instaweb
-
-enum transform_state {
-    transform_state_initialized,
-    transform_state_output,
-    transform_state_finished
-};
-
-typedef struct
-{
-  TSHttpTxn txn;
-  TSVIO downstream_vio;
-  TSIOBuffer downstream_buffer;
-  int64_t downstream_length;
-  enum transform_state state;
-
-  net_instaweb::AtsBaseFetch* base_fetch;
-  net_instaweb::ProxyFetch* proxy_fetch;
-  net_instaweb::GzipInflater* inflater;
-
-  bool write_pending;
-  bool fetch_done;
-  GoogleString* url_string;
-  bool beacon_request;
-  bool resource_request;
-  bool mps_user_agent;
-  bool transform_added;
-  net_instaweb::GoogleUrl* gurl;
-  net_instaweb::AtsServerContext* server_context;
-  GoogleString* user_agent;
-  bool html_rewrite;
-  const char* request_method;
-  int alive;
-  net_instaweb::AtsRewriteOptions* options;
-  // TODO: Use GoogleString*
-  std::string* to_host;
-} TransformCtx;
-
-TransformCtx* get_transaction_context(TSHttpTxn txnp);
-void ats_ctx_destroy(TransformCtx * ctx);
-bool cache_hit(TSHttpTxn txnp);
-
-bool ps_determine_options(net_instaweb::ServerContext* server_context,
-  // Directory-specific options, usually null.  They've already been rebased off
-  // of the global options as part of the configuration process.
-                          net_instaweb::RewriteOptions* directory_options,
-                          net_instaweb::RequestHeaders* request_headers,
-                          net_instaweb::ResponseHeaders* response_headers,
-                          net_instaweb::RewriteOptions** options,
-                          net_instaweb::GoogleUrl* url);
-
-void copy_request_headers_to_psol(TSMBuffer bufp, TSMLoc hdr_loc, net_instaweb::RequestHeaders* psol_headers);
-// You will own options returned by this:
-net_instaweb::AtsRewriteOptions* get_host_options(const StringPiece& host);
-
-#endif /* ATS_SPEED_H_ */

http://git-wip-us.apache.org/repos/asf/trafficserver/blob/e8b899b0/plugins/experimental/ats_speed/ats_thread_system.h
----------------------------------------------------------------------
diff --git a/plugins/experimental/ats_speed/ats_thread_system.h b/plugins/experimental/ats_speed/ats_thread_system.h
deleted file mode 100644
index e3565a8..0000000
--- a/plugins/experimental/ats_speed/ats_thread_system.h
+++ /dev/null
@@ -1,50 +0,0 @@
-/** @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.
-*/
-
-#ifndef ATS_THREAD_SYSTEM_H_
-#define ATS_THREAD_SYSTEM_H_
-
-#include <pthread.h>
-
-#include <ts/ts.h>
-#include "net/instaweb/system/public/system_thread_system.h"
-#include "net/instaweb/util/public/thread.h"
-#include "net/instaweb/util/public/thread_system.h"
-#include "net/instaweb/util/public/pthread_rw_lock.h"
-#include "net/instaweb/util/public/condvar.h"
-
-namespace net_instaweb {
-
-class AtsThreadSystem : public net_instaweb::SystemThreadSystem {
- public:
-  virtual void BeforeThreadRunHook() {
-    TSThreadInit();
-  }
-
-  virtual ~AtsThreadSystem() { }
-};
-
-} // net_instaweb
-
-
-#endif // ATS_THREAD_SYSTEM_H_

http://git-wip-us.apache.org/repos/asf/trafficserver/blob/e8b899b0/plugins/experimental/ats_speed/gzip/Makefile
----------------------------------------------------------------------
diff --git a/plugins/experimental/ats_speed/gzip/Makefile b/plugins/experimental/ats_speed/gzip/Makefile
deleted file mode 100644
index 6a02ae2..0000000
--- a/plugins/experimental/ats_speed/gzip/Makefile
+++ /dev/null
@@ -1,24 +0,0 @@
-#  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.
-
-TSXS?=tsxs
-
-all:
-	$(TSXS) -o gzip.so -v -C *.cc
-install: 
-	$(TSXS) -v -i -o gzip.so
-clean:
-	rm -f *.lo *.so

http://git-wip-us.apache.org/repos/asf/trafficserver/blob/e8b899b0/plugins/experimental/ats_speed/gzip/README
----------------------------------------------------------------------
diff --git a/plugins/experimental/ats_speed/gzip/README b/plugins/experimental/ats_speed/gzip/README
deleted file mode 100644
index 2e74681..0000000
--- a/plugins/experimental/ats_speed/gzip/README
+++ /dev/null
@@ -1,4 +0,0 @@
-This gzip is not compiled, but only here to be able to diff later
-with the official gzip plugin. It is very slightly modified no 
-be able to disable caching of its compressed output through a 
-response header
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/trafficserver/blob/e8b899b0/plugins/experimental/ats_speed/gzip/configuration.cc
----------------------------------------------------------------------
diff --git a/plugins/experimental/ats_speed/gzip/configuration.cc b/plugins/experimental/ats_speed/gzip/configuration.cc
deleted file mode 100644
index b1c499d..0000000
--- a/plugins/experimental/ats_speed/gzip/configuration.cc
+++ /dev/null
@@ -1,264 +0,0 @@
-/** @file
-
-  Transforms content using gzip or deflate
-
-  @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 "configuration.h"
-#include <fstream>
-#include <algorithm>
-#include <vector>
-#include <fnmatch.h>
-
-namespace Gzip {
-  using namespace std;
-
-  void ltrim_if(string& s, int (* fp) (int)) {
-    for (size_t i = 0; i < s.size();) {
-      if (fp(s[i])) {
-        s.erase(i,1);
-      } else  {
-        break;
-      }
-    }
-  }
-
-  void rtrim_if(string& s, int (* fp) (int)) {
-    for (ssize_t i = (ssize_t)s.size() - 1; i >= 0; i--) {
-      if (fp(s[i])) {
-        s.erase(i,1);
-      } else  {
-        break;
-      }
-    }
-  }
-
-  void trim_if(string& s, int (* fp) (int)) {
-    ltrim_if(s, fp);
-    rtrim_if(s, fp);
-  }
-
-  vector<string> tokenize(const string &s, int (* fp) (int)) {
-    vector<string> r;
-    string tmp;
-
-    for (size_t i = 0; i < s.size(); i++) {
-      if ( fp(s[i]) ) {
-        if ( tmp.size()  ) {
-          r.push_back(tmp);
-          tmp = "";
-        }
-      } else {
-          tmp += s[i];
-      }
-    }
-
-    if ( tmp.size()  ) {
-      r.push_back(tmp);
-    }
-
-    return r;
-  }
-
-  enum ParserState {
-    kParseStart,
-    kParseCompressibleContentType,
-    kParseRemoveAcceptEncoding,
-    kParseEnable,
-    kParseCache,
-    kParseDisallow,
-  };
-
-  void Configuration::AddHostConfiguration(HostConfiguration * hc){
-    host_configurations_.push_back(hc);
-  }
-
-  void HostConfiguration::add_disallow(const std::string & disallow) {
-    disallows_.push_back(disallow);
-  }
-
-  void HostConfiguration::add_compressible_content_type(const std::string & content_type) {
-    compressible_content_types_.push_back(content_type);
-  }
-
-  HostConfiguration * Configuration::Find(const char * host, int host_length) {
-    HostConfiguration * host_configuration = host_configurations_[0];
-
-    std::string shost(host, host_length);
-
-    for (size_t i = 1; i < host_configurations_.size(); i++ ) {
-      if (host_configurations_[i]->host() == shost){
-        host_configuration = host_configurations_[i];
-        break;
-      }
-    }
-
-    return host_configuration;
-  }
-
-  bool HostConfiguration::IsUrlAllowed(const char * url, int url_len) {
-    string surl(url, url_len);
-
-    for (size_t i = 0; i < disallows_.size(); i++) {
-      if ( fnmatch (disallows_[i].c_str(), surl.c_str(), 0) == 0 ) {
-        info("url [%s] disabled for compression, matched on pattern [%s]",
-            surl.c_str(), disallows_[i].c_str());
-        return false;
-      }
-    }
-
-    return true;
-  }
-
-  bool HostConfiguration::ContentTypeIsCompressible(const char * content_type, int content_type_length) {
-    string scontent_type(content_type, content_type_length);
-    bool is_match = false;
-    
-    for (size_t i = 0; i < compressible_content_types_.size(); i++) {
-      const char* match_string = compressible_content_types_[i].c_str();
-      bool exclude = match_string[0] == '!';
-      if (exclude) {
-        match_string++;//skip '!'
-      }
-      if ( fnmatch (match_string, scontent_type.c_str(), 0) == 0 ) {
-        info("compressible content type [%s], matched on pattern [%s]",
-            scontent_type.c_str(), compressible_content_types_[i].c_str());
-        is_match = !exclude;
-      }
-    }
-
-    return is_match;
-  }
-
-  Configuration * Configuration::Parse(const char * path ) {
-    string pathstring(path);
-
-    // If we have a path and it's not an absolute path, make it relative to the
-    // configuration directory.
-    if (!pathstring.empty() && pathstring[0] != '/') {
-      pathstring.assign(TSConfigDirGet());
-      pathstring.append("/");
-      pathstring.append(path);
-    }
-
-    trim_if(pathstring, isspace);
-
-    Configuration * c = new Configuration();
-    HostConfiguration * current_host_configuration = new HostConfiguration("");
-    c->AddHostConfiguration(current_host_configuration);
-    current_host_configuration->add_compressible_content_type("text/*");
-    current_host_configuration->add_compressible_content_type("application/xml*");
-    current_host_configuration->add_compressible_content_type("*javascript*");
-    current_host_configuration->add_compressible_content_type("image/svg+xml");
-
-    
-    if (pathstring.empty())  {
-      return c;
-    }
-
-    path = pathstring.c_str();
-    info("Parsing file \"%s\"", path);
-    std::ifstream f;
-
-    size_t lineno = 0;
-
-    f.open(path, std::ios::in);
-
-    if (!f.is_open()) {
-      warning("could not open file [%s], skip",path);
-      return c;
-    }
-
-    enum ParserState state = kParseStart;
-
-    while (!f.eof()) {
-      std::string line;
-      getline(f, line);
-      ++lineno;
-
-      trim_if(line, isspace);
-      if (line.size() == 0) {
-        continue;
-      }
-
-      vector<string> v = tokenize( line, isspace );
-
-      for(size_t i = 0; i < v.size(); i++ ) {
-        string token = v[i];
-        trim_if(token, isspace);
-
-        //should not happen
-        if (!token.size()) continue;
-
-        //once a comment is encountered, we are done processing the line
-        if (token[0] == '#') break;
-
-        switch(state) {
-        case kParseStart:
-          if ( (token[0] == '[') && (token[token.size()-1] == ']')){
-            std::string current_host = token.substr(1,token.size()-2);
-            current_host_configuration = new HostConfiguration(current_host);
-            c->AddHostConfiguration(current_host_configuration);
-          } else if (token == "compressible-content-type" ) {
-            state = kParseCompressibleContentType;
-          } else if (token == "remove-accept-encoding" ) {
-            state = kParseRemoveAcceptEncoding;
-          } else if (token == "enabled" ) {
-            state = kParseEnable;
-          } else if (token == "cache" ) {
-            state = kParseCache;
-          } else if (token == "disallow" ) {
-            state = kParseDisallow;
-          }
-          else {
-            warning("failed to interpret \"%s\" at line %zu", token.c_str(), lineno);
-          }
-          break;
-        case kParseCompressibleContentType:
-          current_host_configuration->add_compressible_content_type(token);
-          state = kParseStart;
-          break;
-        case kParseRemoveAcceptEncoding:
-          current_host_configuration->set_remove_accept_encoding(token == "true");
-          state = kParseStart;
-          break;
-        case kParseEnable:
-          current_host_configuration->set_enabled(token == "true");
-          state = kParseStart;
-          break;
-        case kParseCache:
-          current_host_configuration->set_cache(token == "true");
-          state = kParseStart;
-          break;
-        case kParseDisallow:
-          current_host_configuration->add_disallow(token);
-          state = kParseStart;
-          break;
-        }
-      }
-    }
-
-    if (state != kParseStart) {
-      warning("the parser state indicates that data was expected when it reached the end of the file (%d)", state);
-    }
-
-    return c;
-  } //Configuration::Parse
-} //namespace

http://git-wip-us.apache.org/repos/asf/trafficserver/blob/e8b899b0/plugins/experimental/ats_speed/gzip/configuration.h
----------------------------------------------------------------------
diff --git a/plugins/experimental/ats_speed/gzip/configuration.h b/plugins/experimental/ats_speed/gzip/configuration.h
deleted file mode 100644
index b38cb64..0000000
--- a/plugins/experimental/ats_speed/gzip/configuration.h
+++ /dev/null
@@ -1,84 +0,0 @@
-/** @file
-
-  Transforms content using gzip or deflate
-
-  @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 GZIP_CONFIGURATION_H_
-#define GZIP_CONFIGURATION_H_
-
-#include <string>
-#include <vector>
-#include "debug_macros.h"
-
-namespace Gzip  { 
-  class HostConfiguration {
-  public: //todo -> only configuration should be able to construct hostconfig
-    explicit HostConfiguration(const std::string & host)
-      : host_(host)
-      , enabled_(true)
-      , cache_(true)
-      , remove_accept_encoding_(false)
-    {}
-
-    inline bool enabled() { return enabled_; }
-    inline void set_enabled(bool x) { enabled_ = x; } 
-    inline bool cache() { return cache_; }
-    inline void set_cache(bool x) { cache_ = x; } 
-    inline bool remove_accept_encoding() { return remove_accept_encoding_; }
-    inline void set_remove_accept_encoding(bool x) { remove_accept_encoding_ = x; } 
-    inline std::string host() { return host_; }
-    void add_disallow(const std::string & disallow);
-    void add_compressible_content_type(const std::string & content_type);
-    bool IsUrlAllowed(const char * url, int url_len);
-    bool ContentTypeIsCompressible(const char * content_type, int content_type_length);
-
-  private:
-    std::string host_;
-    bool enabled_;
-    bool cache_;
-    bool remove_accept_encoding_;
-    std::vector<std::string> compressible_content_types_;
-    std::vector<std::string> disallows_;
-    DISALLOW_COPY_AND_ASSIGN(HostConfiguration);
-  };//class HostConfiguration
-
-  class Configuration {
-    friend class HostConfiguration;
-  public:
-    static Configuration * Parse(const char * path);
-    HostConfiguration * Find(const char * host, int host_length); 
-    inline HostConfiguration * GlobalConfiguration() {
-      return host_configurations_[0];
-    }
-
-  private:
-    explicit Configuration()  {}
-    void AddHostConfiguration(HostConfiguration * hc);
-
-    std::vector<HostConfiguration *> host_configurations_;
-    //todo: destructor. delete owned host configurations
-    DISALLOW_COPY_AND_ASSIGN(Configuration);
-  }; //class Configuration
-
-}//namespace
-
-#endif

http://git-wip-us.apache.org/repos/asf/trafficserver/blob/e8b899b0/plugins/experimental/ats_speed/gzip/debug_macros.h
----------------------------------------------------------------------
diff --git a/plugins/experimental/ats_speed/gzip/debug_macros.h b/plugins/experimental/ats_speed/gzip/debug_macros.h
deleted file mode 100644
index 151de31..0000000
--- a/plugins/experimental/ats_speed/gzip/debug_macros.h
+++ /dev/null
@@ -1,59 +0,0 @@
-/** @file
-
-  Transforms content using gzip or deflate
-
-  @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 _DBG_MACROS_H
-#define _DBG_MACROS_H
-
-#include <ts/ts.h>
-
-#define TAG "gzip"
-
-#define debug(fmt, args...) do {                                    \
-  TSDebug(TAG, "DEBUG: [%s:%d] [%s] " fmt, __FILE__, __LINE__, __FUNCTION__ , ##args ); \
-  } while (0)
-
-#define info(fmt, args...) do {                                    \
-  TSDebug(TAG, "INFO: " fmt, ##args ); \
-  } while (0)
-
-#define warning(fmt, args...) do {                                    \
-  TSDebug(TAG, "WARNING: " fmt, ##args ); \
-} while (0)
-
-#define error(fmt, args...) do {                                    \
-  TSError("[%s:%d] [%s] ERROR: " fmt, __FILE__, __LINE__, __FUNCTION__ , ##args ); \
-  TSDebug(TAG, "[%s:%d] [%s] ERROR: " fmt, __FILE__, __LINE__, __FUNCTION__ , ##args ); \
-} while (0)
-
-#define fatal(fmt, args...) do {                                    \
-  TSError("[%s:%d] [%s] ERROR: " fmt, __FILE__, __LINE__, __FUNCTION__ , ##args ); \
-  TSDebug(TAG, "[%s:%d] [%s] ERROR: " fmt, __FILE__, __LINE__, __FUNCTION__ , ##args ); \
-  exit(-1); \
-} while (0)
-
-//FIXME: this one doesn't deserve to be here
-#define DISALLOW_COPY_AND_ASSIGN(TypeName) \
-  TypeName(const TypeName&);               \
-  void operator=(const TypeName&)
-
-#endif //_DBG_MACROS_H


[6/6] git commit: ats_pagespeed: rename ats_speed -> ats_pagespeed

Posted by am...@apache.org.
ats_pagespeed: rename ats_speed -> ats_pagespeed

Fixes TS-3005


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

Branch: refs/heads/5.1.x
Commit: e8b899b0fb847ca81eed290fa9c34f95ca6255eb
Parents: afa93fa
Author: Otto van der Schaaf <os...@we-amp.com>
Authored: Wed Aug 20 22:52:56 2014 +0200
Committer: Alan M. Carroll <am...@network-geographics.com>
Committed: Thu Aug 21 09:53:32 2014 -0500

----------------------------------------------------------------------
 plugins/experimental/ats_pagespeed/.gitignore   |   15 +
 plugins/experimental/ats_pagespeed/Makefile     |   83 ++
 .../ats_pagespeed/Makefile.psol_source          |   49 +
 plugins/experimental/ats_pagespeed/README.md    |   52 +
 .../ats_pagespeed/ats_base_fetch.cc             |  142 +++
 .../experimental/ats_pagespeed/ats_base_fetch.h |   88 ++
 .../ats_pagespeed/ats_beacon_intercept.cc       |  364 ++++++
 .../ats_pagespeed/ats_beacon_intercept.h        |   31 +
 .../experimental/ats_pagespeed/ats_config.cc    |  204 ++++
 plugins/experimental/ats_pagespeed/ats_config.h |   90 ++
 .../ats_pagespeed/ats_header_utils.cc           |   96 ++
 .../ats_pagespeed/ats_header_utils.h            |   41 +
 .../ats_pagespeed/ats_log_message_handler.cc    |  101 ++
 .../ats_pagespeed/ats_log_message_handler.h     |   36 +
 .../ats_pagespeed/ats_message_handler.cc        |  114 ++
 .../ats_pagespeed/ats_message_handler.h         |   75 ++
 .../experimental/ats_pagespeed/ats_pagespeed.cc | 1093 ++++++++++++++++++
 .../experimental/ats_pagespeed/ats_pagespeed.h  |  102 ++
 .../ats_pagespeed/ats_process_context.cc        |   86 ++
 .../ats_pagespeed/ats_process_context.h         |   58 +
 .../ats_pagespeed/ats_resource_intercept.cc     |  363 ++++++
 .../ats_pagespeed/ats_resource_intercept.h      |   29 +
 .../ats_pagespeed/ats_rewrite_driver_factory.cc |  196 ++++
 .../ats_pagespeed/ats_rewrite_driver_factory.h  |  113 ++
 .../ats_pagespeed/ats_rewrite_options.cc        |  263 +++++
 .../ats_pagespeed/ats_rewrite_options.h         |  103 ++
 .../ats_pagespeed/ats_server_context.cc         |   46 +
 .../ats_pagespeed/ats_server_context.h          |   56 +
 .../ats_pagespeed/ats_thread_system.h           |   50 +
 .../experimental/ats_pagespeed/gzip/Makefile    |   24 +
 plugins/experimental/ats_pagespeed/gzip/README  |    4 +
 .../ats_pagespeed/gzip/configuration.cc         |  264 +++++
 .../ats_pagespeed/gzip/configuration.h          |   84 ++
 .../ats_pagespeed/gzip/debug_macros.h           |   59 +
 plugins/experimental/ats_pagespeed/gzip/gzip.cc |  826 +++++++++++++
 .../experimental/ats_pagespeed/gzip/gzip.config |    6 +
 plugins/experimental/ats_pagespeed/gzip/misc.cc |  197 ++++
 plugins/experimental/ats_pagespeed/gzip/misc.h  |   84 ++
 .../ats_pagespeed/scripts/prepare_psol.sh       |   93 ++
 plugins/experimental/ats_speed/.gitignore       |   15 -
 plugins/experimental/ats_speed/Makefile         |   83 --
 .../experimental/ats_speed/Makefile.psol_source |   49 -
 plugins/experimental/ats_speed/README.md        |   52 -
 .../experimental/ats_speed/ats_base_fetch.cc    |  142 ---
 plugins/experimental/ats_speed/ats_base_fetch.h |   88 --
 .../ats_speed/ats_beacon_intercept.cc           |  364 ------
 .../ats_speed/ats_beacon_intercept.h            |   31 -
 plugins/experimental/ats_speed/ats_config.cc    |  204 ----
 plugins/experimental/ats_speed/ats_config.h     |   90 --
 .../experimental/ats_speed/ats_header_utils.cc  |   96 --
 .../experimental/ats_speed/ats_header_utils.h   |   41 -
 .../ats_speed/ats_log_message_handler.cc        |  101 --
 .../ats_speed/ats_log_message_handler.h         |   36 -
 .../ats_speed/ats_message_handler.cc            |  114 --
 .../ats_speed/ats_message_handler.h             |   75 --
 .../ats_speed/ats_process_context.cc            |   86 --
 .../ats_speed/ats_process_context.h             |   58 -
 .../ats_speed/ats_resource_intercept.cc         |  363 ------
 .../ats_speed/ats_resource_intercept.h          |   29 -
 .../ats_speed/ats_rewrite_driver_factory.cc     |  196 ----
 .../ats_speed/ats_rewrite_driver_factory.h      |  113 --
 .../ats_speed/ats_rewrite_options.cc            |  263 -----
 .../ats_speed/ats_rewrite_options.h             |  103 --
 .../ats_speed/ats_server_context.cc             |   46 -
 .../experimental/ats_speed/ats_server_context.h |   56 -
 plugins/experimental/ats_speed/ats_speed.cc     | 1093 ------------------
 plugins/experimental/ats_speed/ats_speed.h      |  102 --
 .../experimental/ats_speed/ats_thread_system.h  |   50 -
 plugins/experimental/ats_speed/gzip/Makefile    |   24 -
 plugins/experimental/ats_speed/gzip/README      |    4 -
 .../ats_speed/gzip/configuration.cc             |  264 -----
 .../experimental/ats_speed/gzip/configuration.h |   84 --
 .../experimental/ats_speed/gzip/debug_macros.h  |   59 -
 plugins/experimental/ats_speed/gzip/gzip.cc     |  826 -------------
 plugins/experimental/ats_speed/gzip/gzip.config |    6 -
 plugins/experimental/ats_speed/gzip/misc.cc     |  197 ----
 plugins/experimental/ats_speed/gzip/misc.h      |   84 --
 .../ats_speed/scripts/prepare_psol.sh           |   93 --
 78 files changed, 5780 insertions(+), 5780 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/trafficserver/blob/e8b899b0/plugins/experimental/ats_pagespeed/.gitignore
----------------------------------------------------------------------
diff --git a/plugins/experimental/ats_pagespeed/.gitignore b/plugins/experimental/ats_pagespeed/.gitignore
new file mode 100644
index 0000000..a12b1d2
--- /dev/null
+++ b/plugins/experimental/ats_pagespeed/.gitignore
@@ -0,0 +1,15 @@
+# Compiled Object files
+*.slo
+*.lo
+*.o
+
+# Compiled Dynamic libraries
+*.so
+*.dylib
+
+# Compiled Static libraries
+*.lai
+*.la
+*.a
+*.gz
+*~
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/trafficserver/blob/e8b899b0/plugins/experimental/ats_pagespeed/Makefile
----------------------------------------------------------------------
diff --git a/plugins/experimental/ats_pagespeed/Makefile b/plugins/experimental/ats_pagespeed/Makefile
new file mode 100644
index 0000000..9177b44
--- /dev/null
+++ b/plugins/experimental/ats_pagespeed/Makefile
@@ -0,0 +1,83 @@
+#  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.
+
+SHELL := /bin/bash
+TSXS?=tsxs
+# Specify BUILDTYPE=Debug for a debug build
+BUILDTYPE?=Release
+MOD_PAGESPEED_DIR=$(shell pwd)/psol/include/
+PAGESPEED_OUT=$(shell pwd)/psol/lib/$(BUILDTYPE)/linux/x64/
+
+
+os_name=unknown_os
+arch_name=ia32
+uname_os=$(shell uname)
+uname_arch=$(shell uname -m)
+
+ifeq ($(uname_os),Linux)
+  os_name=linux
+endif
+
+ifeq ($(uname_arch), x86_64)
+  arch_name=x64
+endif
+ifeq ($(uname_arch), amd64)
+  arch_name=x64
+endif
+
+INC =-I$(MOD_PAGESPEED_DIR)\
+ -I$(MOD_PAGESPEED_DIR)third_party/chromium/src/\
+ -I$(MOD_PAGESPEED_DIR)third_party/google-sparsehash/src\
+ -I$(MOD_PAGESPEED_DIR)third_party/google-sparsehash/gen/arch/$(os_name)/$(arch_name)/include\
+ -I$(MOD_PAGESPEED_DIR)third_party/protobuf/src\
+ -I$(MOD_PAGESPEED_DIR)third_party/re2/src\
+ -I$(MOD_PAGESPEED_DIR)third_party/out/$(BUILDTYPE)/obj/gen\
+ -I$(MOD_PAGESPEED_DIR)third_party/apr/src/include/\
+ -I$(MOD_PAGESPEED_DIR)third_party/aprutil/src/include/\
+ -I$(MOD_PAGESPEED_DIR)third_party/apr/gen/arch/$(os_name)/$(arch_name)/include/\
+ -I$(MOD_PAGESPEED_DIR)third_party/aprutil/gen/arch/$(os_name)/$(arch_name)/include/\
+ -I$(MOD_PAGESPEED_DIR)out/$(BUILDTYPE)/obj/gen\
+ -I$(MOD_PAGESPEED_DIR)out/$(BUILDTYPE)/obj/gen/protoc_out/instaweb
+
+PSOL_LIBS = $(PAGESPEED_OUT)pagespeed_automatic.a 
+#PSOL_LIBS = $(PAGESPEED_OUT)pagespeed_automatic.a $(PAGESPEED_OUT)libserf.a $(PAGESPEED_OUT)libaprutil.a $(PAGESPEED_OUT)libapr.a
+
+%.so: psol %.cc
+# https://github.com/pagespeed/ngx_pagespeed/issues/433: it would be nice to have -Wall -Werror, only suppressing when needed.
+	g++ $(INC) -shared -o ats_pagespeed.so -g -pipe -O3 -fpic *.cc -lstdc++ -lstdc++  -lpthread $(PSOL_LIBS) -lrt
+
+all: psol gzip/gzip.so ats_pagespeed.so
+
+1.8.31.4.tar.gz:
+	wget --no-check-certificate https://dl.google.com/dl/page-speed/psol/1.8.31.4.tar.gz
+
+psol/: 1.8.31.4.tar.gz
+	tar -xzvf 1.8.31.4.tar.gz
+
+gzip/gzip.so:
+	cd gzip && make
+
+install: all
+	$(TSXS) -i -o ats_pagespeed.so
+	cd gzip && make install
+
+cleanpsol:
+	rm -rf psol/
+	rm *.gz
+
+clean:
+	rm -f *.lo *.so *.o
+	rm -f gzip/*.lo gzip/*.so gzip/*.o

http://git-wip-us.apache.org/repos/asf/trafficserver/blob/e8b899b0/plugins/experimental/ats_pagespeed/Makefile.psol_source
----------------------------------------------------------------------
diff --git a/plugins/experimental/ats_pagespeed/Makefile.psol_source b/plugins/experimental/ats_pagespeed/Makefile.psol_source
new file mode 100755
index 0000000..f4c35723
--- /dev/null
+++ b/plugins/experimental/ats_pagespeed/Makefile.psol_source
@@ -0,0 +1,49 @@
+#  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.
+
+TSXS?=tsxs
+BUILDTYPE=Release
+MOD_PAGESPEED_DIR=$(HOME)/code/google/mod_pagespeed/src/
+PAGESPEED_OUT=$(MOD_PAGESPEED_DIR)out/$(BUILDTYPE)/
+
+INC =-I$(MOD_PAGESPEED_DIR)\
+ -I$(MOD_PAGESPEED_DIR)third_party/chromium/src/\
+ -I$(MOD_PAGESPEED_DIR)third_party/google-sparsehash/src\
+ -I$(MOD_PAGESPEED_DIR)third_party/google-sparsehash/gen/arch/linux/x64/include\
+ -I$(MOD_PAGESPEED_DIR)third_party/protobuf/src\
+ -I$(MOD_PAGESPEED_DIR)third_party/re2/src\
+ -I$(MOD_PAGESPEED_DIR)third_party/out/$(BUILDTYPE)/obj/gen\
+ -I$(MOD_PAGESPEED_DIR)third_party/apr/src/include/\
+ -I$(MOD_PAGESPEED_DIR)third_party/aprutil/src/include/\
+ -I$(MOD_PAGESPEED_DIR)third_party/apr/gen/arch/linux/x64/include/\
+ -I$(MOD_PAGESPEED_DIR)third_party/aprutil/gen/arch/linux/x64/include/\
+ -I$(PAGESPEED_OUT)obj/gen/\
+ -I$(PAGESPEED_OUT)obj/gen/protoc_out/instaweb/
+
+PSOL_LIBS = $(MOD_PAGESPEED_DIR)net/instaweb/automatic/pagespeed_automatic.a
+
+%.so: %.cc
+	g++ $(INC) -shared -o ats_pagespeed.so -g -pipe -Wall -Werror -O3 -fpic *.cc -lstdc++  -lpthread -lrt $(PSOL_LIBS)
+
+all: gzip/gzip.so ats_pagespeed.so
+
+install: all
+	$(TSXS) -i -o ats_pagespeed.so 
+	cp gzip/gzip.so ./
+	$(TSXS) -i -o zip.so 
+
+clean:
+	rm -f *.lo *.so *.o

http://git-wip-us.apache.org/repos/asf/trafficserver/blob/e8b899b0/plugins/experimental/ats_pagespeed/README.md
----------------------------------------------------------------------
diff --git a/plugins/experimental/ats_pagespeed/README.md b/plugins/experimental/ats_pagespeed/README.md
new file mode 100644
index 0000000..6c4ff15
--- /dev/null
+++ b/plugins/experimental/ats_pagespeed/README.md
@@ -0,0 +1,52 @@
+![ScreenShot](http://www.atsspeed.com/images/xATSSPEED_logo_plusshout_728x91.png.pagespeed.ic.8mRpu2PXS0.png
+)
+
+Apache Traffic Server web content optimization plugin powered by Google PageSpeed
+
+http://www.atsspeed.com/
+
+To build, a simple 'make' should work. Use 'sudo make install' to install.
+Optionally, patching ATS with ethread.patch helps with eliminating latency that 
+sometimes gets induced when synchronising ATS's and PSOL's thread pools.
+
+After that, update ATS's plugin.config with:
+```
+ats_pagespeed.so                                                                                 
+gzip.so /usr/local/etc/trafficserver/gzip.config  
+````
+gzip.so also is build with ats_pagespeed, as it currently is a slightly
+modified version of the official one from the ATS repository.
+
+There are some hard-coded things in the plugin, these directories should exist:
+- /tmp/ps_log/ to exist
+- /tmp/ats_ps/ to exist
+
+Configuration files go into `/usr/local/etc/trafficserver/psol.`
+That folder is monitored, and changes to files in there are picked
+up immediately. A sample configuration:
+
+```
+# [host]
+[192.168.185.185]
+# Force traffic server to cache all origin responses
+override_expiry
+pagespeed FlushHtml on
+pagespeed RewriteLevel CoreFilters
+pagespeed EnableFilters rewrite_domains,trim_urls
+pagespeed MapRewriteDomain http://192.168.185.185 http://www.foo.com
+pagespeed MapOriginDomain http://192.168.185.185 http://www.foo.com
+pagespeed EnableFilters prioritize_critical_css,move_css_to_head,move_css_above_scripts
+pagespeed EnableFilters fallback_rewrite_css_urls,insert_img_dimensions,lazyload_images,local_storage_cache
+pagespeed EnableFilters prioritize_critical_css,rewrite_css
+pagespeed EnableFilters combine_javascript,combine_css
+```
+
+It also expects this in records.config from ATS to function:
+`CONFIG proxy.config.url_remap.pristine_host_hdr INT 0`
+
+You can view debug output of the plugin using `traffic_server -T ".*speed.*"`
+
+The current state compiles against PSOL 1.7.30.4-beta.
+Please note the this plugin will generate asserts when build against
+the debug version of mps (option->Merge from a different thread).
+

http://git-wip-us.apache.org/repos/asf/trafficserver/blob/e8b899b0/plugins/experimental/ats_pagespeed/ats_base_fetch.cc
----------------------------------------------------------------------
diff --git a/plugins/experimental/ats_pagespeed/ats_base_fetch.cc b/plugins/experimental/ats_pagespeed/ats_base_fetch.cc
new file mode 100644
index 0000000..769e79b
--- /dev/null
+++ b/plugins/experimental/ats_pagespeed/ats_base_fetch.cc
@@ -0,0 +1,142 @@
+/** @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.
+*/
+
+#include "ats_base_fetch.h"
+
+#include <ts/ts.h>
+
+#include "ats_server_context.h"
+
+#include "net/instaweb/util/public/string_util.h"
+#include "net/instaweb/util/public/string_writer.h"
+#include "net/instaweb/util/public/google_message_handler.h"
+
+
+using namespace net_instaweb;
+
+// TODO(oschaaf): rename is_resource_fetch -> write_raw_response_headers
+AtsBaseFetch::AtsBaseFetch(AtsServerContext* server_context,
+                           const net_instaweb::RequestContextPtr& request_ctx,
+                           TSVIO downstream_vio, TSIOBuffer downstream_buffer, bool is_resource_fetch) :
+  AsyncFetch(request_ctx),
+  server_context_(server_context),
+  done_called_(false),
+  last_buf_sent_(false),
+  references_(2),
+  downstream_vio_(downstream_vio),
+  downstream_buffer_(downstream_buffer),
+  is_resource_fetch_(is_resource_fetch),
+  downstream_length_(0),
+  txn_mutex_(TSVIOMutexGet(downstream_vio)) {
+  buffer_.reserve(1024 * 32);
+}
+
+AtsBaseFetch::~AtsBaseFetch() {
+  CHECK(references_ == 0);
+}
+
+// Should be called from the event loop,
+// and thus with the txn mutex held by ATS
+void AtsBaseFetch::Release() {
+  DecrefAndDeleteIfUnreferenced();
+}
+
+void AtsBaseFetch::Lock(){
+  TSMutexLock(txn_mutex_);
+}
+
+void AtsBaseFetch::Unlock() {
+  TSMutexUnlock(txn_mutex_);
+}
+
+bool AtsBaseFetch::HandleWrite(const StringPiece& sp, net_instaweb::MessageHandler* handler) {
+  ForwardData(sp, false, false);
+  return true;
+}
+
+bool AtsBaseFetch::HandleFlush( net_instaweb::MessageHandler* handler ) {
+  ForwardData("", true, false);
+  return true;
+}
+
+void AtsBaseFetch::HandleHeadersComplete() {
+  // oschaaf: ATS will currently send its response headers
+  // earlier than this will fire. So this has become a no-op.
+  // This implies that we can't support convert_meta_tags
+  TSDebug("ats-speed", "HeadersComplete()!");
+  // For resource fetches, we need to output the headers in raw HTTP format.
+  if (is_resource_fetch_) {
+    GoogleMessageHandler mh;
+    GoogleString s;
+    StringWriter string_writer(&s);
+    response_headers()->Add("Connection", "Close");
+    response_headers()->WriteAsHttp(&string_writer, &mh);
+    ForwardData(StringPiece(s.data(),s.size()), true, false);
+  }
+}
+
+void AtsBaseFetch::ForwardData(const StringPiece& sp, bool reenable, bool last) {
+  TSIOBufferBlock downstream_blkp;
+  char *downstream_buffer;
+  int64_t downstream_length;
+  int64_t to_write = sp.size();
+
+  Lock();
+  if (references_ == 2) {
+    while (to_write > 0) {
+      downstream_blkp = TSIOBufferStart(downstream_buffer_);
+      downstream_buffer = TSIOBufferBlockWriteStart(downstream_blkp, &downstream_length);
+      int64_t bytes_written = to_write > downstream_length ? downstream_length : to_write;
+      memcpy(downstream_buffer, sp.data() + (sp.size() - to_write), bytes_written);
+      to_write -= bytes_written;
+      downstream_length_ += bytes_written;
+      TSIOBufferProduce(downstream_buffer_, bytes_written);
+    }
+    CHECK(to_write == 0) << "to_write failure";
+    if (last) {
+      TSVIONBytesSet(downstream_vio_, downstream_length_);
+    }
+    if (reenable) { 
+      TSVIOReenable(downstream_vio_);
+    }
+  }
+  Unlock();
+}
+
+void AtsBaseFetch::HandleDone(bool success) {
+  CHECK(!done_called_);
+  CHECK(downstream_vio_);
+  TSDebug("ats-speed", "Done()!");
+
+  Lock();
+  done_called_ = true;
+  ForwardData("", true, true);
+  DecrefAndDeleteIfUnreferenced();
+  Unlock();
+}
+
+void AtsBaseFetch::DecrefAndDeleteIfUnreferenced() {
+  if (__sync_add_and_fetch(&references_, -1) == 0) {
+    delete this;
+  }
+}

http://git-wip-us.apache.org/repos/asf/trafficserver/blob/e8b899b0/plugins/experimental/ats_pagespeed/ats_base_fetch.h
----------------------------------------------------------------------
diff --git a/plugins/experimental/ats_pagespeed/ats_base_fetch.h b/plugins/experimental/ats_pagespeed/ats_base_fetch.h
new file mode 100644
index 0000000..63b952f
--- /dev/null
+++ b/plugins/experimental/ats_pagespeed/ats_base_fetch.h
@@ -0,0 +1,88 @@
+/** @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.
+*/
+
+#ifndef ATS_BASE_FETCH_H_
+#define ATS_BASE_FETCH_H_
+
+#include <string>
+
+#include <ts/ts.h>
+
+#include "ats_pagespeed.h"
+
+#include "net/instaweb/http/public/async_fetch.h"
+#include "net/instaweb/http/public/headers.h"
+#include "net/instaweb/util/public/string.h"
+
+
+namespace net_instaweb {
+
+class AtsServerContext;
+class AbstractMutex;
+
+class AtsBaseFetch : public net_instaweb::AsyncFetch {
+
+public:
+  // TODO(oschaaf): change this to take the downstream buffer and vio
+  // instead of AtsData*. Also, make the bytes send a property
+  // of the fetch itself instead of tracking it on data.
+  // Doing so, would allow us to share this with the server intercept
+  // code for resources.
+  AtsBaseFetch(AtsServerContext* server_context,
+               const net_instaweb::RequestContextPtr& request_ctx,
+               TSVIO downstream_vio,
+               TSIOBuffer downstream_buffer,
+               bool is_resource_fetch);
+  
+  virtual ~AtsBaseFetch();
+  void Release();
+private:
+  virtual bool HandleWrite(const StringPiece& sp, net_instaweb::MessageHandler* handler);
+  virtual bool HandleFlush( net_instaweb::MessageHandler* handler);
+  virtual void HandleHeadersComplete();
+  virtual void HandleDone(bool success);
+  void Lock();
+  void Unlock();
+  void DecrefAndDeleteIfUnreferenced();
+  void ForwardData(const StringPiece& sp, bool reenable, bool last);
+  GoogleString buffer_;
+  AtsServerContext* server_context_;
+  bool done_called_;
+  bool last_buf_sent_;
+
+  // How many active references there are to this fetch. Starts at two,
+  // decremented once when Done() is called and once when Release() is called.
+  int references_;
+  TSVIO downstream_vio_;
+  TSIOBuffer downstream_buffer_;
+  bool is_resource_fetch_;
+  int64_t downstream_length_;
+
+  // We don't own this mutex
+  TSMutex txn_mutex_;
+};
+
+} /* ats_pagespeed */
+
+
+#endif /* ATS_BASE_FETCH_H_ */

http://git-wip-us.apache.org/repos/asf/trafficserver/blob/e8b899b0/plugins/experimental/ats_pagespeed/ats_beacon_intercept.cc
----------------------------------------------------------------------
diff --git a/plugins/experimental/ats_pagespeed/ats_beacon_intercept.cc b/plugins/experimental/ats_pagespeed/ats_beacon_intercept.cc
new file mode 100644
index 0000000..88cf016
--- /dev/null
+++ b/plugins/experimental/ats_pagespeed/ats_beacon_intercept.cc
@@ -0,0 +1,364 @@
+/** @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.
+*/
+
+#include "ats_beacon_intercept.h"
+#include "ats_pagespeed.h"
+#include "ats_server_context.h"
+
+#include "net/instaweb/system/public/system_request_context.h"
+
+#include <string>
+#include <limits.h>
+#include <strings.h>
+#include <stdio.h>
+
+using std::string;
+using namespace net_instaweb;
+
+#define DEBUG_TAG "ats_pagespeed_beacon"
+
+struct InterceptCtx {
+  TSVConn net_vc;
+  TSCont contp;
+
+  struct IoHandle {
+    TSVIO vio;
+    TSIOBuffer buffer;
+    TSIOBufferReader reader;
+    IoHandle()
+      : vio(0), buffer(0), reader(0) { };
+    ~IoHandle() {
+      if (reader) {
+        TSIOBufferReaderFree(reader);
+      }
+      if (buffer) {
+        TSIOBufferDestroy(buffer);
+      }
+    };
+  };
+
+  IoHandle input;
+  IoHandle output;
+
+  TSHttpParser http_parser;
+  string body;
+  int req_content_len;
+  TSMBuffer req_hdr_bufp;
+  TSMLoc req_hdr_loc;
+  bool req_hdr_parsed;
+  bool initialized;
+  TransformCtx* request_context;
+  InterceptCtx(TSCont cont) 
+    : net_vc(0), contp(cont), input(), output(), body(""), req_content_len(0), req_hdr_bufp(0), req_hdr_loc(0),
+      req_hdr_parsed(false), initialized(false) {
+    http_parser = TSHttpParserCreate();
+  }
+
+  bool init(TSVConn vconn);
+
+  void setupWrite();
+
+  ~InterceptCtx() {
+    TSDebug(DEBUG_TAG, "[%s] Destroying continuation data", __FUNCTION__);
+    TSHttpParserDestroy(http_parser); 
+    if (req_hdr_loc) {
+      TSHandleMLocRelease(req_hdr_bufp, TS_NULL_MLOC, req_hdr_loc);
+    }
+    if (req_hdr_bufp) {
+      TSMBufferDestroy(req_hdr_bufp);
+    }
+    if (request_context) {
+      ats_ctx_destroy(request_context);
+      request_context = NULL;
+    }
+  };
+};
+
+bool
+InterceptCtx::init(TSVConn vconn)
+{
+  if (initialized) {
+    TSError("[%s] InterceptCtx already initialized!", __FUNCTION__);
+    return false;
+  }
+  
+  net_vc = vconn;
+
+  input.buffer = TSIOBufferCreate();
+  input.reader = TSIOBufferReaderAlloc(input.buffer);
+  input.vio = TSVConnRead(net_vc, contp, input.buffer, INT_MAX);
+
+  req_hdr_bufp = TSMBufferCreate();
+  req_hdr_loc = TSHttpHdrCreate(req_hdr_bufp);
+  TSHttpHdrTypeSet(req_hdr_bufp, req_hdr_loc, TS_HTTP_TYPE_REQUEST);
+
+  initialized = true;
+  TSDebug(DEBUG_TAG, "[%s] InterceptCtx initialized!", __FUNCTION__);
+  return true;
+}
+
+void
+InterceptCtx::setupWrite() {
+  TSAssert(output.buffer == 0);
+  output.buffer = TSIOBufferCreate();
+  output.reader = TSIOBufferReaderAlloc(output.buffer);
+  output.vio = TSVConnWrite(net_vc, contp, output.reader, INT_MAX);
+}
+
+// Parses out query params from the request.
+void ps_query_params_handler(StringPiece unparsed_uri, StringPiece* data) {
+  stringpiece_ssize_type question_mark_index = unparsed_uri.find("?");
+  if (question_mark_index == StringPiece::npos) {
+    *data = "";
+  } else {
+    *data = unparsed_uri.substr(
+        question_mark_index+1, unparsed_uri.size() - (question_mark_index+1));
+  }
+}
+
+static bool
+handleRead(InterceptCtx *cont_data, bool &read_complete) {
+  int avail = TSIOBufferReaderAvail(cont_data->input.reader);
+  if (avail == TS_ERROR) {
+    TSError("[%s] Error while getting number of bytes available", __FUNCTION__);
+    return false;
+  }
+  
+  TSDebug(DEBUG_TAG, "[%s] Parsed header, avail: %d", __FUNCTION__, avail);
+
+  int consumed = 0;
+  if (avail > 0) {
+    int64_t data_len;
+    const char *data;
+    TSIOBufferBlock block = TSIOBufferReaderStart(cont_data->input.reader);
+    while (block != NULL) {
+      data = TSIOBufferBlockReadStart(block, cont_data->input.reader, &data_len);
+      if (!cont_data->req_hdr_parsed) {
+        const char *endptr = data + data_len;
+        if (TSHttpHdrParseReq(cont_data->http_parser, cont_data->req_hdr_bufp, cont_data->req_hdr_loc,
+                               &data, endptr) == TS_PARSE_DONE) {
+          TSDebug(DEBUG_TAG, "[%s] Parsed header", __FUNCTION__);
+          TSMLoc content_len_loc = TSMimeHdrFieldFind(cont_data->req_hdr_bufp, cont_data->req_hdr_loc,
+                                                        TS_MIME_FIELD_CONTENT_LENGTH, -1);
+          
+          /*if (!content_len_loc) {
+            TSError("[%s] Error while searching content length header [%s]",
+                     __FUNCTION__, TS_MIME_FIELD_CONTENT_LENGTH);
+            return false;
+          }
+          if (!content_len_loc) {
+            TSError("[%s] request doesn't contain content length header [%s]",
+                     __FUNCTION__, TS_MIME_FIELD_CONTENT_TYPE);
+            return false;
+            }*/
+          if (!content_len_loc) {
+            cont_data->req_content_len = 0;
+          } else {
+            cont_data->req_content_len = TSMimeHdrFieldValueIntGet(cont_data->req_hdr_bufp, cont_data->req_hdr_loc,
+                                         content_len_loc, 0);
+            TSHandleMLocRelease(cont_data->req_hdr_bufp, cont_data->req_hdr_loc, content_len_loc);
+          }
+          TSDebug(DEBUG_TAG, "[%s] Got content length as %d", __FUNCTION__, cont_data->req_content_len);
+          if (cont_data->req_content_len < 0) {
+            TSError("[%s] Invalid content length [%d]", __FUNCTION__, cont_data->req_content_len);
+            return false;
+          }
+          if (endptr - data) {
+            TSDebug(DEBUG_TAG, "[%s] Appending %ld bytes to body", __FUNCTION__, static_cast<long int>(endptr - data));
+            cont_data->body.append(data, endptr - data);
+          }
+          cont_data->req_hdr_parsed = true;
+        }
+      } else {
+        //TSDebug(DEBUG_TAG, "[%s] Appending %" PRId64" bytes to body", __FUNCTION__, data_len);
+        cont_data->body.append(data, data_len);
+      }
+      consumed += data_len;
+      block = TSIOBufferBlockNext(block);
+    }
+  }
+  
+  TSIOBufferReaderConsume(cont_data->input.reader, consumed);
+
+  TSDebug(DEBUG_TAG, "[%s] Consumed %d bytes from input vio, avail: %d", __FUNCTION__, consumed, avail);
+  
+  // Modify the input VIO to reflect how much data we've completed.
+  TSVIONDoneSet(cont_data->input.vio, TSVIONDoneGet(cont_data->input.vio) + consumed);
+
+  if (static_cast<int>(cont_data->body.size()) == cont_data->req_content_len) {
+    TSDebug(DEBUG_TAG, "[%s] Completely read body of size %d", __FUNCTION__, cont_data->req_content_len);
+    read_complete = true;
+  } else {
+    read_complete = false;
+    TSDebug(DEBUG_TAG, "[%s] Reenabling input vio as %ld bytes still need to be read",
+             __FUNCTION__, static_cast<long int>(cont_data->req_content_len - cont_data->body.size()));
+    TSVIOReenable(cont_data->input.vio);
+  }
+  return true;
+}
+
+static bool
+processRequest(InterceptCtx *cont_data) {
+  // OS: Looks like on 5.x we sometimes receive read complete / EOS events twice,
+  // which needs looking into. Probably this intercept is doing something it shouldn't
+  if (cont_data->output.buffer) { 
+    TSDebug("ats_pagespeed", "Received read complete / EOS twice?!");
+    return true;
+  }
+  string reply_header("HTTP/1.1 204 No Content\r\n");
+  int body_size = static_cast<int>(cont_data->body.size());
+  if (cont_data->req_content_len != body_size) {
+    TSError("[%s] Read only %d bytes of body; expecting %d bytes", __FUNCTION__, body_size,
+             cont_data->req_content_len);
+  }
+
+  char buf[64];
+  //snprintf(buf, 64, "%s: %d\r\n\r\n", TS_MIME_FIELD_CONTENT_LENGTH, body_size);
+  snprintf(buf, 64, "%s: %d\r\n\r\n", TS_MIME_FIELD_CONTENT_LENGTH, 0);
+  reply_header.append(buf);
+  reply_header.append("Cache-Control: max-age=0, no-cache");
+  //TSError("[%s] reply header: \n%s", __FUNCTION__, reply_header.data());
+
+  StringPiece query_param_beacon_data;
+  ps_query_params_handler(cont_data->request_context->url_string->c_str(), &query_param_beacon_data);
+  
+  GoogleString beacon_data = net_instaweb::StrCat(
+      query_param_beacon_data, "&", cont_data->body);
+  ServerContext* server_context = cont_data->request_context->server_context;
+  
+  SystemRequestContext* system_request_context = 
+      new SystemRequestContext(server_context->thread_system()->NewMutex(),
+                               server_context->timer(),
+			       // TODO(oschaaf): determine these for real.
+			       "www.foo.com",
+                               80,
+                               "127.0.0.1");
+  
+  if (!server_context->HandleBeacon(
+          beacon_data,
+            cont_data->request_context->user_agent->c_str(),
+          net_instaweb::RequestContextPtr(system_request_context))) {
+    TSError("Beacon handling failure!");
+  } else {
+    TSDebug(DEBUG_TAG,  "Beacon post data processed OK: [%s]", beacon_data.c_str());
+  }
+  
+  cont_data->setupWrite();
+  if (TSIOBufferWrite(cont_data->output.buffer, reply_header.data(), reply_header.size()) == TS_ERROR) {
+    TSError("[%s] Error while writing reply header", __FUNCTION__);
+    return false;
+  }
+  /*
+  if (TSIOBufferWrite(cont_data->output.buffer, cont_data->body.data(), body_size) == TS_ERROR) {
+    TSError("[%s] Error while writing content", __FUNCTION__);
+    return false;
+    }*/
+  int total_bytes_written = reply_header.size() + body_size;
+  TSDebug(DEBUG_TAG, "[%s] Wrote reply of size %d", __FUNCTION__, total_bytes_written);
+  TSVIONBytesSet(cont_data->output.vio, total_bytes_written);
+  
+  TSVIOReenable(cont_data->output.vio);
+  return true;
+}
+
+static int
+txn_intercept(TSCont contp, TSEvent event, void *edata) {
+    TSDebug(DEBUG_TAG, "[%s] Received event: %d", __FUNCTION__, (int)event);
+
+  InterceptCtx *cont_data = static_cast<InterceptCtx *>(TSContDataGet(contp));
+  bool read_complete = false;
+  bool shutdown = false;
+  switch (event) {
+  case TS_EVENT_NET_ACCEPT:
+    TSDebug(DEBUG_TAG, "[%s] Received net accept event", __FUNCTION__);
+    TSAssert(cont_data->initialized == false);
+    if (!cont_data->init(static_cast<TSVConn>(edata))) {
+      TSError("[%s] Could not initialize continuation data!", __FUNCTION__);
+      return 1;
+    }
+    break;
+  case TS_EVENT_VCONN_READ_READY:
+    TSDebug(DEBUG_TAG, "[%s] Received read ready event", __FUNCTION__);
+    if (!handleRead(cont_data, read_complete)) {
+      TSError("[%s] Error while reading from input vio", __FUNCTION__);
+      //return 0;
+      read_complete = true;
+    }
+    break;
+  case TS_EVENT_VCONN_READ_COMPLETE:
+  case TS_EVENT_VCONN_EOS:
+    // intentional fall-through
+    TSDebug(DEBUG_TAG, "[%s] Received read complete/eos event %d", __FUNCTION__, event);
+    read_complete = true;
+    break;
+  case TS_EVENT_VCONN_WRITE_READY:
+    TSDebug(DEBUG_TAG, "[%s] Received write ready event", __FUNCTION__);
+    break;
+  case TS_EVENT_VCONN_WRITE_COMPLETE:
+    TSDebug(DEBUG_TAG, "[%s] Received write complete event", __FUNCTION__);
+    shutdown = true;
+    break;
+  case TS_EVENT_ERROR:
+    // todo: do some error handling here
+    TSDebug(DEBUG_TAG, "[%s] Received error event; going to shutdown, event: %d", __FUNCTION__, event);    
+    TSError("[%s] Received error event; going to shutdown, event: %d", __FUNCTION__, event);
+    shutdown = true;
+    break;
+  default:
+    break;
+  }
+
+  if (read_complete) {
+    if (!processRequest(cont_data)) {
+      TSError("[%s] Failed to process process", __FUNCTION__);
+    } else {
+      TSDebug(DEBUG_TAG, "[%s] Processed request successfully", __FUNCTION__);
+    }
+  }
+
+  if (shutdown) {
+    TSDebug(DEBUG_TAG, "[%s] Completed request processing. Shutting down...", __FUNCTION__);
+    if (cont_data->net_vc) {
+      TSVConnClose(cont_data->net_vc);
+    }
+    delete cont_data;
+    TSContDestroy(contp);
+  } 
+
+  return 1;
+}
+
+bool
+hook_beacon_intercept(TSHttpTxn txnp) {
+  TSCont contp = TSContCreate(txn_intercept, TSMutexCreate());
+  if (!contp) {
+    TSError("[%s] Could not create intercept request", __FUNCTION__);
+    return false;
+  }
+  InterceptCtx *cont_data = new InterceptCtx(contp);
+  cont_data->request_context = get_transaction_context(txnp);
+  TSContDataSet(contp, cont_data);
+  TSHttpTxnIntercept(contp, txnp);
+  TSDebug(DEBUG_TAG, "[%s] Setup server intercept successfully", __FUNCTION__);
+  return true;
+}

http://git-wip-us.apache.org/repos/asf/trafficserver/blob/e8b899b0/plugins/experimental/ats_pagespeed/ats_beacon_intercept.h
----------------------------------------------------------------------
diff --git a/plugins/experimental/ats_pagespeed/ats_beacon_intercept.h b/plugins/experimental/ats_pagespeed/ats_beacon_intercept.h
new file mode 100644
index 0000000..d53d81c
--- /dev/null
+++ b/plugins/experimental/ats_pagespeed/ats_beacon_intercept.h
@@ -0,0 +1,31 @@
+/** @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.
+*/
+
+#ifndef _ATS_BEACON_INTERCEPT_H
+#define _ATS_BEACON_INTERCEPT_H
+
+#include "ts/ts.h"
+
+bool hook_beacon_intercept(TSHttpTxn txnp);
+
+#endif

http://git-wip-us.apache.org/repos/asf/trafficserver/blob/e8b899b0/plugins/experimental/ats_pagespeed/ats_config.cc
----------------------------------------------------------------------
diff --git a/plugins/experimental/ats_pagespeed/ats_config.cc b/plugins/experimental/ats_pagespeed/ats_config.cc
new file mode 100644
index 0000000..e0adf42
--- /dev/null
+++ b/plugins/experimental/ats_pagespeed/ats_config.cc
@@ -0,0 +1,204 @@
+/** @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.
+*/
+
+#include "ats_config.h"
+
+#include <ts/ts.h>
+#include <fstream>
+
+#include "net/instaweb/util/public/string_util.h"
+
+#include "ats_message_handler.h"
+#include "ats_rewrite_options.h"
+
+namespace net_instaweb {
+
+using namespace std;
+
+
+
+void ltrim_if(string& s, int (* fp) (int)) {
+  for (size_t i = 0; i < s.size();) {
+    if (fp(s[i])) {
+      s.erase(i,1);
+    } else  {
+      break;
+    }
+  }
+}
+
+void rtrim_if(string& s, int (* fp) (int)) {
+  for (ssize_t i = (ssize_t)s.size() - 1; i >= 0; i--) {
+    if (fp(s[i])) {
+      s.erase(i,1);
+    } else  {
+      break;
+    }
+  }
+}
+
+void trim_if(string& s, int (* fp) (int)) {
+  ltrim_if(s, fp);
+  rtrim_if(s, fp);
+}
+
+vector<string> tokenize(const string &s, int (* fp) (int)) {
+  vector<string> r;
+  string tmp;
+
+  for (size_t i = 0; i < s.size(); i++) {
+    if ( fp(s[i]) ) {
+      if ( tmp.size()  ) {
+        r.push_back(tmp);
+        tmp = "";
+      }
+    } else {
+      tmp += s[i];
+    }
+  }
+
+  if ( tmp.size()  ) {
+    r.push_back(tmp);
+  }
+
+  return r;
+}
+
+AtsConfig::AtsConfig(AtsThreadSystem* thread_system)
+      : thread_system_(thread_system) {
+  AddHostConfig(new AtsHostConfig(GoogleString("(XXXXXX)"), new AtsRewriteOptions(thread_system_)));
+}
+
+AtsConfig::~AtsConfig() {
+  for (size_t i = 0; i < host_configurations_.size(); i++) {
+    delete host_configurations_[i];
+    host_configurations_.clear();
+  }
+}
+
+void AtsConfig::AddHostConfig(AtsHostConfig* hc){
+  host_configurations_.push_back(hc);
+}
+
+AtsHostConfig::~AtsHostConfig() {
+  if (options_ != NULL) {
+    delete options_;
+    options_ = NULL;
+  }
+}
+
+AtsHostConfig * AtsConfig::Find(const char * host, int host_length) {
+  AtsHostConfig * host_configuration = host_configurations_[0];
+
+  std::string shost(host, host_length);
+
+  for (size_t i = 1; i < host_configurations_.size(); i++ ) {
+    if (host_configurations_[i]->host() == shost){
+      host_configuration = host_configurations_[i];
+      break;
+    }
+  }
+
+  return host_configuration;
+}
+
+bool AtsConfig::Parse(const char * path ) {
+  string pathstring(path);
+
+  // If we have a path and it's not an absolute path, make it relative to the
+  // configuration directory.
+  if (!pathstring.empty() && pathstring[0] != '/') {
+    pathstring.assign(TSConfigDirGet());
+    pathstring.append("/");
+    pathstring.append(path);
+  }
+
+  trim_if(pathstring, isspace);
+
+  AtsHostConfig* current_host_configuration = host_configurations_[0];
+
+  if (pathstring.empty())  {
+    TSError("Empty path passed in AtsConfig::Parse");
+    return false;
+  }
+
+  path = pathstring.c_str();
+  std::ifstream f;
+
+  size_t lineno = 0;
+
+  f.open(path, std::ios::in);
+
+  if (!f.is_open()) {
+    TSError("could not open file [%s], skip",path);
+    return false;
+  }
+
+
+  while (!f.eof()) {
+    std::string line;
+    getline(f, line);
+    ++lineno;
+
+    trim_if(line, isspace);
+    if (line.size() == 0) {
+      continue;
+    }
+    if (line[0] == '#') {
+      continue;
+    }
+    
+    vector<string> v = tokenize( line, isspace );
+    if (v.size() == 0)
+      continue;
+    GoogleString msg;
+    AtsMessageHandler handler(thread_system_->NewMutex());
+    if (v.size() == 1) {
+      string token = v[0];
+      if ((token[0] == '[') && (token[token.size()-1] == ']')) {
+        GoogleString current_host = token.substr(1, token.size() - 2);
+        current_host_configuration = new AtsHostConfig(current_host, new AtsRewriteOptions(thread_system_));
+        AddHostConfig(current_host_configuration);
+      } else if (StringCaseEqual(token,"override_expiry")) {
+        current_host_configuration->set_override_expiry(true);
+      } else {
+        msg = "unknown single token on a line";
+      }
+    } else {
+      global_settings settings;
+      v.erase (v.begin());
+      const char* err = current_host_configuration->options()->ParseAndSetOptions(v, &handler, settings);
+      if (err) {
+        msg.append(err);
+      }
+    }
+    if (msg.size() > 0) {
+      TSDebug("ats-speed", "Error parsing line [%s]: [%s]", line.c_str(), msg.c_str());
+    }
+  }
+
+  return true;
+}
+
+
+} //  namespace net_instaweb

http://git-wip-us.apache.org/repos/asf/trafficserver/blob/e8b899b0/plugins/experimental/ats_pagespeed/ats_config.h
----------------------------------------------------------------------
diff --git a/plugins/experimental/ats_pagespeed/ats_config.h b/plugins/experimental/ats_pagespeed/ats_config.h
new file mode 100644
index 0000000..d3b0e40
--- /dev/null
+++ b/plugins/experimental/ats_pagespeed/ats_config.h
@@ -0,0 +1,90 @@
+/** @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.
+*/
+
+#ifndef ATS_CONFIG_H_
+#define ATS_CONFIG_H_
+
+#include <string>
+#include <vector>
+
+#include <ts/ts.h>
+
+#include "ats_thread_system.h"
+
+#include "net/instaweb/util/public/string.h"
+#include "net/instaweb/util/public/string_util.h"
+
+
+namespace net_instaweb {
+
+class AtsRewriteOptions;
+
+class AtsHostConfig {
+public:
+  explicit AtsHostConfig(const GoogleString & host, AtsRewriteOptions* options)
+      : host_(host)
+      , options_(options)
+  {
+  }
+  virtual ~AtsHostConfig();
+
+  inline GoogleString host() { return host_; }
+  inline AtsRewriteOptions* options() { return options_; }
+  inline bool override_expiry() { return override_expiry_; }
+  inline void set_override_expiry(bool x) { override_expiry_ = x; }
+private:
+  GoogleString host_;
+  AtsRewriteOptions* options_;
+  bool override_expiry_;
+  DISALLOW_COPY_AND_ASSIGN(AtsHostConfig);
+}; // class AtsHostConfig
+
+class AtsConfig {
+  friend class AtsHostConfig;
+public:
+  explicit AtsConfig(AtsThreadSystem* thread_system);
+  virtual ~AtsConfig();
+  
+  // TODO(oschaaf): destructor??
+  bool Parse(const char * path);
+  AtsHostConfig * Find(const char * host, int host_length);
+  inline AtsHostConfig * GlobalConfiguration() {
+    return host_configurations_[0];
+  }
+  AtsThreadSystem* thread_system() {
+    return thread_system_;
+  }
+
+private:
+  void AddHostConfig(AtsHostConfig* hc);
+
+  std::vector<AtsHostConfig *> host_configurations_;
+  AtsThreadSystem* thread_system_;
+  //todo: destructor. delete owned host configurations
+  DISALLOW_COPY_AND_ASSIGN(AtsConfig);
+}; // class Configuration
+
+
+}  // namespace net_instaweb
+
+#endif  // ATS_CONFIG_H

http://git-wip-us.apache.org/repos/asf/trafficserver/blob/e8b899b0/plugins/experimental/ats_pagespeed/ats_header_utils.cc
----------------------------------------------------------------------
diff --git a/plugins/experimental/ats_pagespeed/ats_header_utils.cc b/plugins/experimental/ats_pagespeed/ats_header_utils.cc
new file mode 100644
index 0000000..a61c784
--- /dev/null
+++ b/plugins/experimental/ats_pagespeed/ats_header_utils.cc
@@ -0,0 +1,96 @@
+/** @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.
+*/
+
+#include "ats_header_utils.h"
+
+GoogleString get_header(TSMBuffer bufp, TSMLoc hdr_loc, const char * header_name)
+{
+  const char * val = NULL;
+  int val_len;
+  TSMLoc field_loc = TSMimeHdrFieldFind( bufp, hdr_loc, header_name, -1);
+
+  if (field_loc) {
+    val = TSMimeHdrFieldValueStringGet (bufp, hdr_loc, field_loc, 0, &val_len);
+    TSHandleMLocRelease(bufp,hdr_loc,field_loc);
+    return GoogleString(val,val_len);
+  }
+
+  return GoogleString("");
+}
+
+void unset_header(TSMBuffer bufp, TSMLoc hdr_loc, const char * header_name)
+{
+  TSMLoc field_loc = TSMimeHdrFieldFind( bufp, hdr_loc, header_name, -1);
+
+  if (field_loc) {
+    TSMimeHdrFieldDestroy(bufp, hdr_loc, field_loc);
+    TSHandleMLocRelease(bufp, hdr_loc, field_loc);
+  }
+}
+
+void hide_accept_encoding(TSMBuffer reqp, TSMLoc hdr_loc, const char * hidden_header_name)
+{
+  TSMLoc field = TSMimeHdrFieldFind(reqp, hdr_loc, TS_MIME_FIELD_ACCEPT_ENCODING, TS_MIME_LEN_ACCEPT_ENCODING);
+  while (field) {
+    TSMLoc tmp;
+    tmp = TSMimeHdrFieldNextDup(reqp, hdr_loc, field);
+    TSMimeHdrFieldNameSet(reqp, hdr_loc, field, hidden_header_name, -1);
+    TSHandleMLocRelease(reqp, hdr_loc, field);
+    field = tmp;
+  }
+}
+
+void restore_accept_encoding(TSMBuffer reqp, TSMLoc hdr_loc, const char * hidden_header_name)
+{
+  TSMLoc field = TSMimeHdrFieldFind(reqp, hdr_loc, hidden_header_name, -1);
+
+  while (field) {
+    TSMLoc tmp;
+    tmp = TSMimeHdrFieldNextDup(reqp, hdr_loc, field);
+    TSMimeHdrFieldNameSet(reqp, hdr_loc, field, TS_MIME_FIELD_ACCEPT_ENCODING, TS_MIME_LEN_ACCEPT_ENCODING);
+    TSHandleMLocRelease(reqp, hdr_loc, field);
+    field = tmp;
+  }
+}
+
+void set_header(TSMBuffer bufp, TSMLoc hdr_loc, const char * header_name, const char * header_value)
+{
+  TSMLoc field_loc = TSMimeHdrFieldFind( bufp, hdr_loc, header_name, -1);
+
+  if (field_loc) {
+    TSMimeHdrFieldValueStringSet(bufp, hdr_loc, field_loc, -1, header_value, -1);
+  } else {    
+    if ( TSMimeHdrFieldCreate(bufp, hdr_loc, &field_loc) == TS_SUCCESS ) {
+      TSMimeHdrFieldNameSet(bufp, hdr_loc, field_loc, header_name, -1);
+      TSMimeHdrFieldAppend(bufp, hdr_loc, field_loc);
+      TSMimeHdrFieldValueStringSet(bufp,hdr_loc,field_loc,-1,header_value,-1);
+    } else {
+      TSError("field creation error for field [%s]", header_name);
+      return;
+    }
+  }
+
+  if (field_loc) {
+    TSHandleMLocRelease(bufp,hdr_loc,field_loc);
+  }
+}

http://git-wip-us.apache.org/repos/asf/trafficserver/blob/e8b899b0/plugins/experimental/ats_pagespeed/ats_header_utils.h
----------------------------------------------------------------------
diff --git a/plugins/experimental/ats_pagespeed/ats_header_utils.h b/plugins/experimental/ats_pagespeed/ats_header_utils.h
new file mode 100644
index 0000000..1d6c567
--- /dev/null
+++ b/plugins/experimental/ats_pagespeed/ats_header_utils.h
@@ -0,0 +1,41 @@
+/** @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.
+*/
+
+#ifndef ATS_HEADER_UTILS_H
+#define ATS_HEADER_UTILS_H
+
+#include <string>
+
+#include <ts/ts.h>
+
+#include "net/instaweb/util/public/string.h"
+#include "net/instaweb/util/public/string_util.h"
+
+
+GoogleString get_header(TSMBuffer bufp, TSMLoc hdr_loc, const char * header_name);
+void unset_header(TSMBuffer bufp, TSMLoc hdr_loc, const char * header_name);
+void hide_accept_encoding(TSMBuffer reqp, TSMLoc hdr_loc, const char * hidden_header_name);
+void restore_accept_encoding(TSMBuffer reqp, TSMLoc hdr_loc, const char * hidden_header_name);
+void set_header(TSMBuffer bufp, TSMLoc hdr_loc, const char * header_name, const char * header_value);
+
+#endif //  ATS_HEADER_UTILS_H

http://git-wip-us.apache.org/repos/asf/trafficserver/blob/e8b899b0/plugins/experimental/ats_pagespeed/ats_log_message_handler.cc
----------------------------------------------------------------------
diff --git a/plugins/experimental/ats_pagespeed/ats_log_message_handler.cc b/plugins/experimental/ats_pagespeed/ats_log_message_handler.cc
new file mode 100644
index 0000000..f41b9cc
--- /dev/null
+++ b/plugins/experimental/ats_pagespeed/ats_log_message_handler.cc
@@ -0,0 +1,101 @@
+/** @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.
+*/
+
+#include "ats_log_message_handler.h"
+
+#include <ts/ts.h>
+
+#include <unistd.h>
+
+#include <limits>
+#include <string>
+
+#include "base/debug/debugger.h"
+#include "base/debug/stack_trace.h"
+#include "base/logging.h"
+#include "net/instaweb/public/version.h"
+#include "net/instaweb/util/public/string_util.h"
+
+// Make sure we don't attempt to use LOG macros here, since doing so
+// would cause us to go into an infinite log loop.
+#undef LOG
+#define LOG USING_LOG_HERE_WOULD_CAUSE_INFINITE_RECURSION
+
+namespace {
+
+bool LogMessageHandler(int severity, const char* file, int line,
+                       size_t message_start, const GoogleString& str) {
+  GoogleString message = str;
+  if (severity == logging::LOG_FATAL) {
+    if (base::debug::BeingDebugged()) {
+      base::debug::BreakDebugger();
+    } else {
+      base::debug::StackTrace trace;
+      std::ostringstream stream;
+      trace.OutputToStream(&stream);
+      message.append(stream.str());
+    }
+  }
+
+  // Trim the newline off the end of the message string.
+  size_t last_msg_character_index = message.length() - 1;
+  if (message[last_msg_character_index] == '\n') {
+    message.resize(last_msg_character_index);
+  }
+
+  TSDebug("ats-speed-vlog", "[%s] %s",
+                net_instaweb::kModPagespeedVersion,
+                message.c_str());
+
+  if (severity == logging::LOG_FATAL) {
+    // Crash the process to generate a dump.
+    base::debug::BreakDebugger();
+  }
+
+  return true;
+}
+
+}  // namespace
+
+
+namespace net_instaweb {
+
+namespace log_message_handler {
+
+
+const int kDebugLogLevel = -2;
+
+void Install() {
+  logging::SetLogMessageHandler(&LogMessageHandler);
+
+  // All VLOG(2) and higher will be displayed as DEBUG logs if the nginx log
+  // level is DEBUG.
+  // TODO(oschaaf): from config
+  //if (log->log_level >= NGX_LOG_DEBUG) {
+    logging::SetMinLogLevel(-2);
+  //}
+}
+
+}  // namespace log_message_handler
+
+}  // namespace net_instaweb

http://git-wip-us.apache.org/repos/asf/trafficserver/blob/e8b899b0/plugins/experimental/ats_pagespeed/ats_log_message_handler.h
----------------------------------------------------------------------
diff --git a/plugins/experimental/ats_pagespeed/ats_log_message_handler.h b/plugins/experimental/ats_pagespeed/ats_log_message_handler.h
new file mode 100644
index 0000000..bf57634
--- /dev/null
+++ b/plugins/experimental/ats_pagespeed/ats_log_message_handler.h
@@ -0,0 +1,36 @@
+/** @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.
+*/
+
+#ifndef ATS_LOG_MESSAGE_HANDLER_H_
+#define ATS_LOG_MESSAGE_HANDLER_H_
+
+
+namespace net_instaweb {
+
+  namespace log_message_handler {
+    void Install();
+  }  // namespace log_message_handler
+
+}  // namespace net_instaweb
+
+#endif  // ATS_LOG_MESSAGE_HANDLER_H_

http://git-wip-us.apache.org/repos/asf/trafficserver/blob/e8b899b0/plugins/experimental/ats_pagespeed/ats_message_handler.cc
----------------------------------------------------------------------
diff --git a/plugins/experimental/ats_pagespeed/ats_message_handler.cc b/plugins/experimental/ats_pagespeed/ats_message_handler.cc
new file mode 100644
index 0000000..370f317
--- /dev/null
+++ b/plugins/experimental/ats_pagespeed/ats_message_handler.cc
@@ -0,0 +1,114 @@
+/** @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.
+*/
+
+#include "ats_message_handler.h"
+
+#include <signal.h>
+#include <unistd.h>
+
+#include "net/instaweb/util/public/abstract_mutex.h"
+#include "net/instaweb/util/public/debug.h"
+#include "net/instaweb/util/public/shared_circular_buffer.h"
+#include "net/instaweb/util/public/string_util.h"
+#include "net/instaweb/public/version.h"
+#include "pagespeed/kernel/base/posix_timer.h"
+#include "pagespeed/kernel/base/time_util.h"
+   
+
+namespace {
+
+// This will be prefixed to every logged message.
+const char kModuleName[] = "ats_pagespeed";
+
+}  // namespace
+
+namespace net_instaweb {
+
+AtsMessageHandler::AtsMessageHandler(AbstractMutex* mutex)
+    : mutex_(mutex),
+      buffer_(NULL) {
+  SetPidString(static_cast<int64>(getpid()));
+}
+
+
+bool AtsMessageHandler::Dump(Writer* writer) {
+  // Can't dump before SharedCircularBuffer is set up.
+  if (buffer_ == NULL) {
+    return false;
+  }
+  return buffer_->Dump(writer, &handler_);
+}
+
+void AtsMessageHandler::set_buffer(SharedCircularBuffer* buff) {
+  ScopedMutex lock(mutex_.get());
+  buffer_ = buff;
+}
+
+void AtsMessageHandler::MessageVImpl(MessageType type, const char* msg,
+                                     va_list args) {
+  GoogleString formatted_message = Format(msg, args);
+  
+  TSDebug("ats-speed", "[%s %s] %s", kModuleName, kModPagespeedVersion,
+          formatted_message.c_str());
+ 
+  // Prepare a log message for the SharedCircularBuffer only.
+  // Prepend time and severity to message.
+  // Format is [time] [severity] [pid] message.
+  GoogleString message;
+  GoogleString time;
+  PosixTimer timer;
+  if (!ConvertTimeToString(timer.NowMs(), &time)) {
+    time = "?";
+  }
+  
+  StrAppend(&message, "[", time, "] ",
+            "[", MessageTypeToString(type), "] ");
+  StrAppend(&message, pid_string_, " ", formatted_message, "\n");
+  {
+    ScopedMutex lock(mutex_.get());
+    if (buffer_ != NULL) {
+      buffer_->Write(message);
+    }
+  }
+}
+
+void AtsMessageHandler::FileMessageVImpl(MessageType type, const char* file,
+                                         int line, const char* msg,
+                                         va_list args) {
+  GoogleString formatted_message = Format(msg, args);
+  TSDebug("ats-speed", "[%s %s] %s:%d:%s",
+                kModuleName, kModPagespeedVersion, file, line,
+                formatted_message.c_str());
+}
+
+// TODO(sligocki): It'd be nice not to do so much string copying.
+GoogleString AtsMessageHandler::Format(const char* msg, va_list args) {
+  GoogleString buffer;
+
+  // Ignore the name of this routine: it formats with vsnprintf.
+  // See base/stringprintf.cc.
+  StringAppendV(&buffer, msg, args);
+  return buffer;
+}
+
+}  // namespace net_instaweb

http://git-wip-us.apache.org/repos/asf/trafficserver/blob/e8b899b0/plugins/experimental/ats_pagespeed/ats_message_handler.h
----------------------------------------------------------------------
diff --git a/plugins/experimental/ats_pagespeed/ats_message_handler.h b/plugins/experimental/ats_pagespeed/ats_message_handler.h
new file mode 100644
index 0000000..b8248cf
--- /dev/null
+++ b/plugins/experimental/ats_pagespeed/ats_message_handler.h
@@ -0,0 +1,75 @@
+/** @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.
+*/
+
+#ifndef NGX_MESSAGE_HANDLER_H_
+#define NGX_MESSAGE_HANDLER_H_
+
+#include <ts/ts.h>
+#include <cstdarg>
+
+#include "net/instaweb/util/public/basictypes.h"
+#include "net/instaweb/util/public/google_message_handler.h"
+#include "net/instaweb/util/public/message_handler.h"
+#include "net/instaweb/util/public/scoped_ptr.h"
+#include "net/instaweb/util/public/string.h"
+#include "net/instaweb/util/public/string_util.h"
+
+namespace net_instaweb {
+
+  class AbstractMutex;
+  class SharedCircularBuffer;
+  class Timer;
+  class Writer;
+
+  class AtsMessageHandler : public GoogleMessageHandler {
+ public:
+    explicit AtsMessageHandler(AbstractMutex* mutex);
+
+    void set_buffer(SharedCircularBuffer* buff);
+
+    void SetPidString(const int64 pid) {
+      pid_string_ = StrCat("[", Integer64ToString(pid), "]");
+    }
+    // Dump contents of SharedCircularBuffer.
+    bool Dump(Writer* writer);
+
+ protected:
+    virtual void MessageVImpl(MessageType type, const char* msg, va_list args);
+
+    virtual void FileMessageVImpl(MessageType type, const char* filename,
+                                  int line, const char* msg, va_list args);
+
+ private:
+    GoogleString Format(const char* msg, va_list args);
+
+    scoped_ptr<AbstractMutex> mutex_;
+    GoogleString pid_string_;
+    GoogleMessageHandler handler_;
+    SharedCircularBuffer* buffer_;
+
+    DISALLOW_COPY_AND_ASSIGN(AtsMessageHandler);
+  };
+
+}  // namespace net_instaweb
+
+#endif  // NGX_MESSAGE_HANDLER_H_


[5/6] ats_pagespeed: rename ats_speed -> ats_pagespeed

Posted by am...@apache.org.
http://git-wip-us.apache.org/repos/asf/trafficserver/blob/e8b899b0/plugins/experimental/ats_pagespeed/ats_pagespeed.cc
----------------------------------------------------------------------
diff --git a/plugins/experimental/ats_pagespeed/ats_pagespeed.cc b/plugins/experimental/ats_pagespeed/ats_pagespeed.cc
new file mode 100644
index 0000000..4f6cea5
--- /dev/null
+++ b/plugins/experimental/ats_pagespeed/ats_pagespeed.cc
@@ -0,0 +1,1093 @@
+/** @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.
+*/
+
+// TODO(oschaaf): remove what isn't used
+#ifndef __STDC_LIMIT_MACROS
+#define __STDC_LIMIT_MACROS
+#endif
+#include <stdlib.h>
+#include <errno.h>
+#include <stdio.h>
+#include <limits.h>
+#include <stdint.h>
+#include <sys/inotify.h>
+#include <unistd.h>
+
+#include <ts/ts.h>
+
+#include <vector>
+#include <set>
+
+
+#include "ats_pagespeed.h"
+
+#include "ats_config.h"
+#include "ats_header_utils.h"
+#include "ats_rewrite_options.h"
+#include "ats_log_message_handler.h"
+
+#include "base/logging.h"
+#include "net/instaweb/http/public/response_headers.h"
+#include "net/instaweb/util/public/string_util.h"
+
+#include "ats_base_fetch.h"
+#include "ats_resource_intercept.h"
+#include "ats_beacon_intercept.h"
+#include "ats_process_context.h"
+#include "ats_rewrite_driver_factory.h"
+#include "ats_rewrite_options.h"
+#include "ats_server_context.h"
+
+#include "net/instaweb/rewriter/public/rewrite_stats.h"
+#include "net/instaweb/system/public/in_place_resource_recorder.h"
+
+#include "net/instaweb/automatic/public/proxy_fetch.h"
+#include "net/instaweb/http/public/content_type.h"
+#include "net/instaweb/http/public/request_context.h"
+#include "net/instaweb/rewriter/public/experiment_matcher.h"
+#include "net/instaweb/rewriter/public/experiment_util.h"
+#include "net/instaweb/rewriter/public/process_context.h"
+#include "net/instaweb/rewriter/public/resource_fetch.h"
+#include "net/instaweb/rewriter/public/rewrite_driver.h"
+#include "net/instaweb/rewriter/public/rewrite_query.h"
+#include "net/instaweb/rewriter/public/static_asset_manager.h"
+#include "net/instaweb/public/global_constants.h"
+#include "net/instaweb/public/version.h"
+#include "net/instaweb/util/public/google_message_handler.h"
+#include "net/instaweb/util/public/google_url.h"
+#include "net/instaweb/util/public/gzip_inflater.h"
+#include "net/instaweb/util/public/query_params.h"
+#include "net/instaweb/util/public/statistics_logger.h"
+#include "net/instaweb/util/public/stdio_file_system.h"
+#include "net/instaweb/util/public/string.h"
+#include "net/instaweb/util/public/string_writer.h"
+#include "net/instaweb/util/public/time_util.h"
+#include "net/instaweb/util/stack_buffer.h"
+#include "net/instaweb/system/public/system_request_context.h"
+
+
+#include <dirent.h>
+
+using namespace net_instaweb;
+
+static AtsProcessContext* ats_process_context;
+static const char* DEBUG_TAG = "ats_pagespeed_transform";
+static int TXN_INDEX_ARG;
+static int TXN_INDEX_OWNED_ARG;
+static int TXN_INDEX_OWNED_ARG_SET;
+static int TXN_INDEX_OWNED_ARG_UNSET;
+TSMutex config_mutex = TSMutexCreate();
+AtsConfig* config = NULL;
+TransformCtx* get_transaction_context(TSHttpTxn txnp) {
+  return (TransformCtx *) TSHttpTxnArgGet(txnp, TXN_INDEX_ARG);
+}
+
+static TransformCtx *
+ats_ctx_alloc()
+{
+  TransformCtx *ctx;
+ 
+  ctx = (TransformCtx *) TSmalloc(sizeof(TransformCtx));
+  ctx->downstream_vio = NULL;
+  ctx->downstream_buffer = NULL;
+  ctx->downstream_length = 0;
+  ctx->state = transform_state_initialized;
+
+  ctx->base_fetch = NULL;
+  ctx->proxy_fetch = NULL;
+  
+  ctx->inflater = NULL;
+  ctx->url_string = NULL;
+  ctx->gurl = NULL;
+  ctx->write_pending = false;
+  ctx->fetch_done = false;
+  ctx->resource_request = false;
+  ctx->beacon_request = false;
+  ctx->transform_added = false;
+  ctx->mps_user_agent = false;
+  ctx->user_agent = NULL;
+  ctx->server_context = NULL;
+  ctx->html_rewrite = false;
+  ctx->request_method = NULL;
+  ctx->alive = 0xaaaa;
+  ctx->options = NULL;
+  ctx->to_host = NULL;
+  return ctx;
+}
+
+void
+ats_ctx_destroy(TransformCtx * ctx)
+{
+  TSReleaseAssert(ctx);
+  CHECK(ctx->alive == 0xaaaa) << "Already dead!";
+  ctx->alive = 0xbbbb;
+
+  if (ctx->base_fetch != NULL) {
+    ctx->base_fetch->Release();
+    ctx->base_fetch = NULL;
+  }
+
+  if (ctx->proxy_fetch != NULL) {
+    ctx->proxy_fetch->Done(false /* failure */);
+    ctx->proxy_fetch = NULL;
+  }
+
+  if (ctx->inflater != NULL) {
+    delete ctx->inflater;
+    ctx->inflater = NULL;
+  }
+
+  if (ctx->downstream_buffer) {
+    TSIOBufferDestroy(ctx->downstream_buffer);
+  }
+
+  if (ctx->url_string != NULL) {
+    delete ctx->url_string;
+    ctx->url_string = NULL;
+  }
+
+  if (ctx->gurl != NULL) {
+    delete ctx->gurl;
+    ctx->gurl = NULL;
+  }
+  if (ctx->user_agent != NULL) {
+    delete ctx->user_agent;
+    ctx->user_agent = NULL;
+  }
+  ctx->request_method = NULL;
+  if (ctx->options != NULL) {
+    delete ctx->options;
+    ctx->options = NULL;
+  }
+  if (ctx->to_host != NULL) {
+    delete ctx->to_host;
+    ctx->to_host = NULL;
+  }
+  TSfree(ctx);
+}
+
+RewriteOptions* ps_determine_request_options(
+    ServerContext* server_context,
+    RequestHeaders* request_headers,
+    ResponseHeaders* response_headers,
+    GoogleUrl* url) {
+  // Stripping ModPagespeed query params before the property cache lookup to
+  // make cache key consistent for both lookup and storing in cache.
+  //
+  // Sets option from request headers and url.
+  RewriteQuery rewrite_query;
+  if (!server_context->GetQueryOptions(url, request_headers,
+				       response_headers, &rewrite_query)) {
+    // Failed to parse query params or request headers.  Treat this as if there
+    // were no query params given.
+    TSError("ps_route rerquest: parsing headers or query params failed.");
+    return NULL;
+  }
+
+  // Will be NULL if there aren't any options set with query params or in
+  // headers.
+  return rewrite_query.ReleaseOptions();
+}
+
+bool ps_determine_options(ServerContext* server_context,
+  // Directory-specific options, usually null.  They've already been rebased off
+  // of the global options as part of the configuration process.
+                          RewriteOptions* directory_options,
+                          RequestHeaders* request_headers,
+                          ResponseHeaders* response_headers,
+                          RewriteOptions** options,
+                          GoogleUrl* url) {
+  // Global options for this server.  Never null.
+  RewriteOptions* global_options = server_context->global_options();
+
+  // Request-specific options, nearly always null.  If set they need to be
+  // rebased on the directory options or the global options.
+  RewriteOptions* request_options = ps_determine_request_options(
+      server_context, request_headers, response_headers, url);
+
+  // Because the caller takes ownership of any options we return, the only
+  // situation in which we can avoid allocating a new RewriteOptions is if the
+  // global options are ok as are.
+  if (directory_options == NULL && request_options == NULL &&
+      !global_options->running_experiment()) {
+    return true;
+  }
+
+  // Start with directory options if we have them, otherwise request options.
+  if (directory_options != NULL) {
+    //*options = directory_options->Clone();
+    // OS: HACK! TODO!
+    *options = global_options->Clone();
+    (*options)->Merge(*directory_options);
+  } else {
+    *options = global_options->Clone();
+  }
+
+  // Modify our options in response to request options or experiment settings,
+  // if we need to.  If there are request options then ignore the experiment
+  // because we don't want experiments to be contaminated with unexpected
+  // settings.
+  if (request_options != NULL) {
+    (*options)->Merge(*request_options);
+    delete request_options;
+  }
+  // TODO(oschaaf): experiments
+  /*else if ((*options)->running_experiment()) {
+    bool ok = ps_set_experiment_state_and_cookie(
+        r, request_headers, *options, url->Host());
+    if (!ok) {
+      delete *options;
+      *options = NULL;
+      return false;
+      }
+  }*/
+
+  return true;
+}
+
+void
+handle_send_response_headers(TSHttpTxn txnp) {
+  TransformCtx* ctx = get_transaction_context(txnp);
+  // TODO(oschaaf): Fix the response headers!!
+  bool is_owned = TSHttpTxnArgGet(txnp, TXN_INDEX_OWNED_ARG) == &TXN_INDEX_OWNED_ARG_SET;
+  if (!is_owned) {
+    return;
+  }
+  CHECK(ctx->alive == 0xaaaa) << "Already dead !";
+  if (ctx->html_rewrite) {
+    TSMBuffer bufp = NULL;
+    TSMLoc hdr_loc = NULL;
+    if (ctx->base_fetch == NULL) {
+      // TODO(oschaaf): figure out when this happens.
+      return;
+    }
+    
+    if (TSHttpTxnClientRespGet(txnp, &bufp, &hdr_loc) == TS_SUCCESS) {
+      ResponseHeaders* pagespeed_headers =
+          ctx->base_fetch->response_headers();
+      for (int i = 0 ; i < pagespeed_headers->NumAttributes() ; i++) {
+        const GoogleString& name_gs = pagespeed_headers->Name(i);
+        const GoogleString& value_gs = pagespeed_headers->Value(i);
+
+        // We should avoid touching these fields, as ATS will drop keepalive when we do.
+        if ( StringCaseEqual(name_gs, "Connection") || StringCaseEqual(name_gs, "Transfer-Encoding") ) {
+          continue;
+        }
+        
+        TSMLoc field_loc = TSMimeHdrFieldFind(bufp, hdr_loc, name_gs.data(), name_gs.size());
+        if (field_loc != NULL) {
+          TSMimeHdrFieldValuesClear(bufp, hdr_loc, field_loc);
+          TSMimeHdrFieldValueStringInsert(bufp, hdr_loc, field_loc, -1,
+                                          value_gs.data(), value_gs.size());
+        } else if (TSMimeHdrFieldCreate(bufp, hdr_loc, &field_loc) == TS_SUCCESS) {
+          if (TSMimeHdrFieldNameSet(bufp, hdr_loc, field_loc, name_gs.data(), name_gs.size()) == TS_SUCCESS) {
+            TSMimeHdrFieldValueStringInsert(bufp, hdr_loc, field_loc, -1,
+                                            value_gs.data(), value_gs.size());
+            TSMimeHdrFieldAppend(bufp, hdr_loc, field_loc);
+          } else {
+            CHECK(false) << "Field name set failure";
+          }
+          TSHandleMLocRelease(bufp, hdr_loc, field_loc);
+        } else {
+          CHECK(false) << "Field create failure";
+        }        
+      }
+      
+      TSHandleMLocRelease(bufp, TS_NULL_MLOC, hdr_loc);
+    } else  {
+      DCHECK(false) << "Could not get response headers?!";
+    }
+  }
+}
+
+static void
+copy_response_headers_to_psol(TSMBuffer bufp, TSMLoc hdr_loc, ResponseHeaders* psol_headers) {
+  int n_mime_headers = TSMimeHdrFieldsCount(bufp, hdr_loc);
+  TSMLoc field_loc;
+  const char *name, *value;
+  int name_len, value_len;
+  GoogleString header;
+  for (int i = 0; i < n_mime_headers; ++i) {
+    field_loc = TSMimeHdrFieldGet(bufp, hdr_loc, i);
+    if (!field_loc) {
+      TSDebug(DEBUG_TAG, "[%s] Error while obtaining header field #%d", __FUNCTION__, i);
+      continue;
+    }
+    name = TSMimeHdrFieldNameGet(bufp, hdr_loc, field_loc, &name_len);
+    StringPiece s_name(name, name_len);
+    int n_field_values = TSMimeHdrFieldValuesCount(bufp, hdr_loc, field_loc);
+    for (int j = 0; j < n_field_values; ++j) {
+      value = TSMimeHdrFieldValueStringGet(bufp, hdr_loc, field_loc, j, &value_len);
+      if ( NULL == value || !value_len ) {
+        TSDebug(DEBUG_TAG, "[%s] Error while getting value #%d of header [%.*s]",
+                __FUNCTION__, j, name_len, name);
+      } else {
+        StringPiece s_value(value, value_len);
+        psol_headers->Add(s_name, s_value);
+        //TSDebug(DEBUG_TAG, "Add response header [%.*s:%.*s]",name_len, name, value_len, value);
+      }
+    }
+    TSHandleMLocRelease(bufp, hdr_loc, field_loc);
+  }
+}
+
+void
+copy_request_headers_to_psol(TSMBuffer bufp, TSMLoc hdr_loc, RequestHeaders* psol_headers) {
+  int n_mime_headers = TSMimeHdrFieldsCount(bufp, hdr_loc);
+  TSMLoc field_loc;
+  const char *name, *value;
+  int name_len, value_len;
+  GoogleString header;
+  for (int i = 0; i < n_mime_headers; ++i) {
+    field_loc = TSMimeHdrFieldGet(bufp, hdr_loc, i);
+    if (!field_loc) {
+      TSDebug(DEBUG_TAG, "[%s] Error while obtaining header field #%d", __FUNCTION__, i);
+      continue;
+    }
+    name = TSMimeHdrFieldNameGet(bufp, hdr_loc, field_loc, &name_len);
+    StringPiece s_name(name, name_len);
+    int n_field_values = TSMimeHdrFieldValuesCount(bufp, hdr_loc, field_loc);
+    for (int j = 0; j < n_field_values; ++j) {
+      value = TSMimeHdrFieldValueStringGet(bufp, hdr_loc, field_loc, j, &value_len);
+      if ( NULL == value || !value_len ) {
+        TSDebug(DEBUG_TAG, "[%s] Error while getting value #%d of header [%.*s]",
+                __FUNCTION__, j, name_len, name);
+      } else {
+        StringPiece s_value(value, value_len);
+        psol_headers->Add(s_name, s_value);
+        //TSDebug(DEBUG_TAG, "Add request header [%.*s:%.*s]",name_len, name, value_len, value);
+      }
+    }
+    TSHandleMLocRelease(bufp, hdr_loc, field_loc);
+  }
+}
+
+// TODO(oschaaf): this is not sustainable when we get more
+// configuration options like this.
+bool get_override_expiry(const StringPiece& host) {
+  TSMutexLock(config_mutex);
+  AtsHostConfig* hc = config->Find(host.data(), host.size());
+  TSMutexUnlock(config_mutex);
+  return hc->override_expiry();
+}
+
+AtsRewriteOptions* get_host_options(const StringPiece& host) {
+  TSMutexLock(config_mutex);
+  AtsRewriteOptions* r = NULL;
+  AtsHostConfig* hc = config->Find(host.data(), host.size());
+  if (hc->options() != NULL) {
+    // We return a clone here to avoid having to thing about
+    // configuration reloads and outstanding options
+    r = hc->options()->Clone();
+  }
+  TSMutexUnlock(config_mutex);
+  return r;
+}
+
+std::string get_remapped_host(TSHttpTxn txn) {
+  TSMBuffer server_req_buf;
+  TSMLoc server_req_loc;
+  std::string to_host;
+  if (TSHttpTxnServerReqGet(txn, &server_req_buf, &server_req_loc) == TS_SUCCESS
+      || TSHttpTxnCachedReqGet(txn, &server_req_buf, &server_req_loc) == TS_SUCCESS) {
+    to_host = get_header(server_req_buf, server_req_loc, "Host");
+    TSHandleMLocRelease(server_req_buf, TS_NULL_MLOC, server_req_loc);
+  } else  {
+    fprintf(stderr, "@@@@@@@ FAILED \n");
+  }
+  return to_host;
+}
+
+static void
+ats_transform_init(TSCont contp, TransformCtx * ctx)
+{
+  //prepare the downstream for transforming
+  TSVConn downstream_conn;
+  TSMBuffer bufp;
+  TSMLoc hdr_loc;
+  TSMBuffer reqp;
+  TSMLoc req_hdr_loc;
+  ctx->state = transform_state_output;
+
+
+  // TODO: check cleanup flow
+  if (TSHttpTxnTransformRespGet(ctx->txn, &bufp, &hdr_loc) != TS_SUCCESS) {
+    TSError("Error TSHttpTxnTransformRespGet");
+    return;
+  }
+  if (TSHttpTxnClientReqGet(ctx->txn, &reqp, &req_hdr_loc) != TS_SUCCESS) {
+    TSError("Error TSHttpTxnClientReqGet");
+    return;
+  }
+  
+  AtsServerContext* server_context = ats_process_context->server_context();
+  if (server_context->IsPagespeedResource(*ctx->gurl)) {
+    CHECK(false) << "PageSpeed resource should not get here!";
+  }
+
+  downstream_conn = TSTransformOutputVConnGet(contp);
+  ctx->downstream_buffer = TSIOBufferCreate();
+  ctx->downstream_vio = TSVConnWrite(downstream_conn, contp, TSIOBufferReaderAlloc(ctx->downstream_buffer), INT64_MAX);
+
+  // TODO(oschaaf): fix host/ip(?)
+  SystemRequestContext* system_request_context = 
+    new SystemRequestContext(server_context->thread_system()->NewMutex(),
+			     server_context->timer(),
+			     "www.foo.com",
+			     80,
+			     "127.0.0.1");
+
+  ctx->base_fetch = new AtsBaseFetch(server_context, RequestContextPtr(system_request_context),
+                                      ctx->downstream_vio, ctx->downstream_buffer, false);
+
+  
+  RewriteOptions* options = NULL;
+  RequestHeaders* request_headers = new RequestHeaders();
+  ctx->base_fetch->SetRequestHeadersTakingOwnership(request_headers);
+  copy_request_headers_to_psol(reqp, req_hdr_loc, request_headers);
+ 
+  TSHttpStatus status = TSHttpHdrStatusGet(bufp, hdr_loc);
+  // TODO(oschaaf): http version
+  ctx->base_fetch->response_headers()->set_status_code(status);
+  copy_response_headers_to_psol(bufp, hdr_loc, ctx->base_fetch->response_headers());
+  ctx->base_fetch->response_headers()->ComputeCaching();
+  const char* host = ctx->gurl->HostAndPort().as_string().c_str();
+      //request_headers->Lookup1(HttpAttributes::kHost);
+  if (host != NULL && strlen(host) > 0) {
+    ctx->options = get_host_options(host);
+  }
+  bool ok = ps_determine_options(server_context,
+                                 ctx->options,
+                                 request_headers,
+                                 ctx->base_fetch->response_headers(),
+                                 &options,
+                                 ctx->gurl);
+
+  // Take ownership of custom_options.
+  scoped_ptr<RewriteOptions> custom_options(options);
+  
+  if (!ok) {
+    TSError("Failure while determining request options for psol");
+    options = server_context->global_options();
+  } else {
+    // ps_determine_options modified url, removing any ModPagespeedFoo=Bar query
+    // parameters.  Keep url_string in sync with url.
+    ctx->gurl->Spec().CopyToString(ctx->url_string);
+  }
+  
+  RewriteDriver* driver;
+  if (custom_options.get() == NULL) {
+    driver = server_context->NewRewriteDriver(ctx->base_fetch->request_context());
+  } else {
+    driver = server_context->NewCustomRewriteDriver(custom_options.release(), ctx->base_fetch->request_context());
+  }
+  
+  driver->SetUserAgent(ctx->user_agent->c_str());
+  driver->SetRequestHeaders(*request_headers);
+   
+  bool page_callback_added = false;
+  scoped_ptr<ProxyFetchPropertyCallbackCollector>
+      property_callback(
+          ProxyFetchFactory::InitiatePropertyCacheLookup(
+              false /*  is resource fetch?*/,
+              *ctx->gurl,
+              server_context,
+              options,
+              ctx->base_fetch,
+              false /* requires_blink_cohort (no longer unused) */,
+              &page_callback_added));
+  
+  ctx->proxy_fetch =
+    ats_process_context->proxy_fetch_factory()->CreateNewProxyFetch(
+								    *(ctx->url_string), ctx->base_fetch, driver,
+                                                                    property_callback.release(),
+								  NULL /* original_content_fetch */);
+
+  TSHandleMLocRelease(reqp, TS_NULL_MLOC, req_hdr_loc);
+  TSHandleMLocRelease(bufp, TS_NULL_MLOC, hdr_loc);
+}
+
+static void
+ats_transform_one(TransformCtx * ctx, TSIOBufferReader upstream_reader, int amount)
+{
+  TSIOBufferBlock downstream_blkp;
+  const char *upstream_buffer;
+  int64_t upstream_length;
+
+  while (amount > 0) {
+    downstream_blkp = TSIOBufferReaderStart(upstream_reader);
+    if (!downstream_blkp) {
+      TSError("couldn't get from IOBufferBlock");
+      return;
+    }
+
+    upstream_buffer = TSIOBufferBlockReadStart(downstream_blkp, upstream_reader, &upstream_length);
+    if (!upstream_buffer) {
+      TSError("couldn't get from TSIOBufferBlockReadStart");
+      return;
+    }
+
+    if (upstream_length > amount) {
+      upstream_length = amount;
+    }
+    
+    TSDebug("ats-speed", "transform!");
+    // TODO(oschaaf): use at least the message handler from the server conrtext here?
+    if (ctx->inflater == NULL) {
+      ctx->proxy_fetch->Write(StringPiece((char*)upstream_buffer, upstream_length), ats_process_context->message_handler());
+    } else {
+      char buf[net_instaweb::kStackBufferSize];
+      
+      ctx->inflater->SetInput((char*)upstream_buffer, upstream_length);
+      
+      while (ctx->inflater->HasUnconsumedInput()) {
+        int num_inflated_bytes = ctx->inflater->InflateBytes(
+            buf, net_instaweb::kStackBufferSize);
+        if (num_inflated_bytes < 0) {
+          TSError("Corrupted inflation");
+        } else if (num_inflated_bytes > 0) {
+          ctx->proxy_fetch->Write(StringPiece(buf, num_inflated_bytes),
+                                   ats_process_context->message_handler());
+        }
+      }
+    }
+    //ctx->proxy_fetch->Flush(NULL);
+    TSIOBufferReaderConsume(upstream_reader, upstream_length);
+    amount -= upstream_length;
+  }
+  // TODO(oschaaf): get the output from the base fetch, and send it downstream.
+  // This would require proper locking around the base fetch buffer
+  // We could also have a look at directly writing to the traffic server buffers
+}
+
+
+static void
+ats_transform_finish(TransformCtx * ctx)
+{
+  if (ctx->state == transform_state_output) {
+    ctx->state = transform_state_finished;
+    ctx->proxy_fetch->Done(true);
+    ctx->proxy_fetch = NULL;
+  }
+}
+
+static void
+ats_transform_do(TSCont contp)
+{
+  TSVIO upstream_vio;
+  TransformCtx *ctx;
+  int64_t upstream_todo;
+  int64_t upstream_avail;
+  int64_t downstream_bytes_written;
+
+  ctx = (TransformCtx*)TSContDataGet(contp);
+
+  if (ctx->state == transform_state_initialized) {
+    ats_transform_init(contp, ctx);
+  }
+
+  upstream_vio = TSVConnWriteVIOGet(contp);
+  downstream_bytes_written = ctx->downstream_length;
+
+  if (!TSVIOBufferGet(upstream_vio)) {
+    ats_transform_finish(ctx);
+    return;
+  }
+
+  upstream_todo = TSVIONTodoGet(upstream_vio);
+
+  if (upstream_todo > 0) {
+    upstream_avail = TSIOBufferReaderAvail(TSVIOReaderGet(upstream_vio));
+
+    if (upstream_todo > upstream_avail) {
+      upstream_todo = upstream_avail;
+    }
+
+    if (upstream_todo > 0) {
+      ats_transform_one(ctx, TSVIOReaderGet(upstream_vio), upstream_todo);
+      TSVIONDoneSet(upstream_vio, TSVIONDoneGet(upstream_vio) + upstream_todo);
+    }
+  }
+
+  if (TSVIONTodoGet(upstream_vio) > 0) {
+    if (upstream_todo > 0) {
+      if (ctx->downstream_length > downstream_bytes_written) {
+        TSVIOReenable(ctx->downstream_vio);
+      }
+      TSContCall(TSVIOContGet(upstream_vio), TS_EVENT_VCONN_WRITE_READY, upstream_vio);
+    }
+  } else {
+    ats_transform_finish(ctx);
+    TSContCall(TSVIOContGet(upstream_vio), TS_EVENT_VCONN_WRITE_COMPLETE, upstream_vio);
+  }
+}
+
+
+static int
+ats_pagespeed_transform(TSCont contp, TSEvent event, void * /* edata ATS_UNUSED */)
+{
+  if (TSVConnClosedGet(contp)) {
+    //ats_ctx_destroy((TransformCtx*)TSContDataGet(contp));
+    TSContDestroy(contp);
+    return 0;
+  } else {
+    switch (event) {
+    case TS_EVENT_ERROR:{
+      fprintf(stderr, "ats speed transform event: [%d] TS EVENT ERROR?!\n", event);
+      TSVIO upstream_vio = TSVConnWriteVIOGet(contp);
+      TSContCall(TSVIOContGet(upstream_vio), TS_EVENT_ERROR, upstream_vio);
+    }
+      break;
+    case TS_EVENT_VCONN_WRITE_COMPLETE:
+      TSVConnShutdown(TSTransformOutputVConnGet(contp), 0, 1);
+      break;
+    case TS_EVENT_VCONN_WRITE_READY:
+      ats_transform_do(contp);
+      break;
+    case TS_EVENT_IMMEDIATE:
+      ats_transform_do(contp);
+      break;
+    default:
+      DCHECK(false) << "unknown event: " << event;
+      ats_transform_do(contp);
+      break;
+    }
+  }
+
+  return 0;
+}
+
+static void
+ats_pagespeed_transform_add(TSHttpTxn txnp)
+{
+  TransformCtx* ctx = get_transaction_context(txnp);
+  CHECK(ctx);
+  if (ctx->transform_added) { // Happens with a stale cache hit
+    return;
+  } else {
+    ctx->transform_added = true;
+  }
+
+  TSHttpTxnUntransformedRespCache(txnp, 1);
+  TSHttpTxnTransformedRespCache(txnp, 0);
+
+  TSVConn connp;
+
+  connp = TSTransformCreate(ats_pagespeed_transform, txnp);
+  TSContDataSet(connp, ctx);
+  TSHttpTxnHookAdd(txnp, TS_HTTP_RESPONSE_TRANSFORM_HOOK, connp);
+}
+
+// Returns true if a server intercept was set up
+// Which means we should not attempt any further transformation
+void
+handle_read_request_header(TSHttpTxn txnp) {
+  TSMBuffer reqp = NULL;
+  TSMLoc hdr_loc = NULL;
+  char *url = NULL;
+  int url_length = -1;
+  
+  TransformCtx* ctx = ats_ctx_alloc();
+  ctx->txn = txnp;
+  TSHttpTxnArgSet(txnp, TXN_INDEX_ARG, (void*) ctx);
+  TSHttpTxnArgSet(txnp, TXN_INDEX_OWNED_ARG, &TXN_INDEX_OWNED_ARG_SET);
+  
+  if (TSHttpTxnClientReqGet(txnp, &reqp, &hdr_loc) == TS_SUCCESS) {
+    url = TSHttpTxnEffectiveUrlStringGet(txnp, &url_length);
+    if (!url || url_length <= 0) {
+      DCHECK(false) << "Could not get url!";
+    } else {
+      std::string s_url = std::string(url,url_length);
+      GoogleUrl gurl(s_url);
+ 
+      ctx->url_string = new GoogleString(url, url_length);
+      ctx->gurl = new GoogleUrl(*(ctx->url_string));
+      if (!ctx->gurl->IsWebValid()) {
+        TSDebug("ats-speed", "URL != WebValid(): %s", ctx->url_string->c_str());
+      } else {
+        const char * method;
+        int method_len;
+        method = TSHttpHdrMethodGet(reqp, hdr_loc, &method_len);
+        bool head_or_get = method == TS_HTTP_METHOD_GET || method == TS_HTTP_METHOD_HEAD;
+        ctx->request_method = method;
+        GoogleString user_agent = get_header(reqp, hdr_loc, "User-Agent");
+        ctx->user_agent = new GoogleString(user_agent);
+        ctx->server_context = ats_process_context->server_context();
+        if (user_agent.find(kModPagespeedSubrequestUserAgent) != user_agent.npos) {
+          ctx->mps_user_agent = true;
+        }
+        if (ats_process_context->server_context()->IsPagespeedResource(gurl)) {
+          if (head_or_get && !ctx->mps_user_agent) { 
+            ctx->resource_request = true;
+            TSHttpTxnArgSet(txnp, TXN_INDEX_OWNED_ARG, &TXN_INDEX_OWNED_ARG_UNSET);
+          }
+        } else if (ctx->gurl->PathSansQuery() == "/pagespeed_message"
+                   || ctx->gurl->PathSansQuery() == "/pagespeed_statistics"
+                   || ctx->gurl->PathSansQuery() == "/pagespeed_global_statistics"
+                   || ctx->gurl->PathSansQuery() == "/pagespeed_console"
+                   || ctx->gurl->PathSansLeaf() == "/ats_pagespeed_static/"
+                   || ctx->gurl->PathSansQuery() == "/robots.txt"
+                   ) {
+          ctx->resource_request = true;
+          TSHttpTxnArgSet(txnp, TXN_INDEX_OWNED_ARG, &TXN_INDEX_OWNED_ARG_UNSET);
+        }
+        else if (StringCaseEqual(gurl.PathSansQuery() ,"/ats_pagespeed_beacon")) {
+          ctx->beacon_request = true;
+          TSHttpTxnArgSet(txnp, TXN_INDEX_OWNED_ARG, &TXN_INDEX_OWNED_ARG_UNSET);
+          hook_beacon_intercept(txnp);
+        }
+      }
+      TSfree((void*)url);
+    } // gurl->IsWebValid() == true
+    TSHandleMLocRelease(reqp, TS_NULL_MLOC, hdr_loc);
+  } else {
+    DCHECK(false) << "Could not get client request header\n";
+  }
+  
+  TSHttpTxnReenable(txnp, TS_EVENT_HTTP_CONTINUE);
+}
+
+bool
+cache_hit(TSHttpTxn txnp) {
+  int obj_status;
+  if (TSHttpTxnCacheLookupStatusGet(txnp, &obj_status) == TS_ERROR) {
+    // TODO(oschaaf): log warning
+    return false;
+  }
+  return obj_status == TS_CACHE_LOOKUP_HIT_FRESH;
+}
+
+static int
+transform_plugin(TSCont contp, TSEvent event, void *edata)
+{
+  TSHttpTxn txn = (TSHttpTxn) edata;
+
+  CHECK(event == TS_EVENT_HTTP_READ_RESPONSE_HDR || event == TS_EVENT_HTTP_READ_CACHE_HDR
+        || event == TS_EVENT_HTTP_SEND_REQUEST_HDR || event == TS_EVENT_HTTP_READ_REQUEST_HDR
+        || event == TS_EVENT_HTTP_TXN_CLOSE || event == TS_EVENT_HTTP_SEND_RESPONSE_HDR) 
+      << "Invalid transform event";
+
+  if (event != TS_EVENT_HTTP_READ_REQUEST_HDR) {
+    // Bail if an intercept is running
+    bool is_owned = TSHttpTxnArgGet(txn, TXN_INDEX_OWNED_ARG) == &TXN_INDEX_OWNED_ARG_SET;
+    if (!is_owned) {
+      TSHttpTxnReenable(txn, TS_EVENT_HTTP_CONTINUE);
+      return 0;
+    }
+  }
+
+  if (event == TS_EVENT_HTTP_SEND_RESPONSE_HDR) {
+    handle_send_response_headers(txn);
+    TSHttpTxnReenable(txn, TS_EVENT_HTTP_CONTINUE);
+    return 0;
+  } if (event == TS_EVENT_HTTP_TXN_CLOSE) {
+    TransformCtx* ctx = get_transaction_context(txn);
+    //if (ctx != NULL && !ctx->resource_request && !ctx->beacon_request && !ctx->html_rewrite) {
+    // For intercepted requests like beacons and resource requests, we don't own the 
+    // ctx here - the interceptor does.
+    
+    if (ctx != NULL) {
+      bool is_owned = TSHttpTxnArgGet(txn, TXN_INDEX_OWNED_ARG) == &TXN_INDEX_OWNED_ARG_SET;
+      if (is_owned) {
+        ats_ctx_destroy(ctx);
+      }
+    }
+    TSHttpTxnReenable(txn, TS_EVENT_HTTP_CONTINUE);
+    return 0;
+  } if (event == TS_EVENT_HTTP_READ_REQUEST_HDR) {
+    handle_read_request_header(txn);
+    return 0;    
+  } else if (event == TS_EVENT_HTTP_SEND_REQUEST_HDR) {
+    TSMBuffer request_header_buf = NULL;
+    TSMLoc request_header_loc = NULL;
+  
+    if (TSHttpTxnServerReqGet(txn, &request_header_buf, &request_header_loc) == TS_SUCCESS) {
+      hide_accept_encoding(request_header_buf, request_header_loc, "@xxAccept-Encoding");
+      // Turn off pagespeed optimization at the origin
+      set_header(request_header_buf, request_header_loc, "PageSpeed", "off");
+      TSHandleMLocRelease(request_header_buf, TS_NULL_MLOC, request_header_loc);
+    } else {
+      CHECK(false) << "Could not find server request header";
+    }
+    TSHttpTxnReenable(txn, TS_EVENT_HTTP_CONTINUE);
+    return 0;
+  } else if (event == TS_EVENT_HTTP_READ_RESPONSE_HDR) {
+    TSMBuffer request_header_buf = NULL;
+    TSMLoc request_header_loc = NULL;
+    
+    if (TSHttpTxnServerReqGet(txn, &request_header_buf, &request_header_loc) == TS_SUCCESS) {
+      restore_accept_encoding(request_header_buf, request_header_loc, "@xxAccept-Encoding");
+      TSHandleMLocRelease(request_header_buf, TS_NULL_MLOC, request_header_loc);
+    } else {
+      CHECK(false) << "Could not find server request header";
+    }
+  }
+
+  CHECK(event == TS_EVENT_HTTP_READ_RESPONSE_HDR || event == TS_EVENT_HTTP_READ_CACHE_HDR);
+
+  TransformCtx* ctx = get_transaction_context(txn);
+  if (ctx == NULL) {
+      // TODO(oschaaf): document how and when this happens.
+    TSHttpTxnReenable(txn, TS_EVENT_HTTP_CONTINUE);
+    return 0;
+  }
+  std::string* to_host = new std::string();
+  to_host->append(get_remapped_host(ctx->txn));
+  ctx->to_host = to_host;
+  TSMBuffer response_header_buf = NULL;
+  TSMLoc response_header_loc = NULL;
+
+  // TODO(oschaaf): from configuration!
+  bool override_expiry = false;
+
+  const char* host = ctx->gurl->HostAndPort().as_string().c_str();
+      //request_headers->Lookup1(HttpAttributes::kHost);
+  if (host != NULL && strlen(host) > 0) {
+    override_expiry = get_override_expiry(host);
+  }
+
+  
+  if (ctx->mps_user_agent && override_expiry) {
+    if (TSHttpTxnServerRespGet(txn, &response_header_buf, &response_header_loc) == TS_SUCCESS) {
+      // TODO => set cacheable.
+      unset_header(response_header_buf, response_header_loc, "Cache-Control");
+      unset_header(response_header_buf, response_header_loc, "Expires");
+      unset_header(response_header_buf, response_header_loc, "Age");
+      set_header(response_header_buf, response_header_loc, "Cache-Control", "public, max-age=3600");    
+      TSHandleMLocRelease(response_header_buf, TS_NULL_MLOC, response_header_loc);    
+    }
+  }
+  bool ok = ctx->gurl->IsWebValid() &&
+            !(ctx->resource_request || ctx->beacon_request || ctx->mps_user_agent);
+  if (!ok) {
+    TSHttpTxnReenable(txn, TS_EVENT_HTTP_CONTINUE);
+    return 0;
+  }
+  
+  bool have_response_header = false;
+  
+  if (TSHttpTxnServerRespGet(txn, &response_header_buf, &response_header_loc) == TS_SUCCESS) {
+    have_response_header = true;
+    if (override_expiry) {
+      unset_header(response_header_buf, response_header_loc, "Cache-Control");
+      unset_header(response_header_buf, response_header_loc, "Expires");
+      unset_header(response_header_buf, response_header_loc, "Age");
+      set_header(response_header_buf, response_header_loc, "Cache-Control", "public, max-age=3600");
+    }
+  }
+  else if (TSHttpTxnCachedRespGet(txn, &response_header_buf, &response_header_loc) == TS_SUCCESS) {
+    have_response_header = true;
+  }  
+  if (!have_response_header) {
+    TSHttpTxnReenable(txn, TS_EVENT_HTTP_CONTINUE);
+    return 0;
+  }
+
+  if (ok) {
+    if (ctx->request_method != TS_HTTP_METHOD_GET && ctx->request_method != TS_HTTP_METHOD_HEAD
+        && ctx->request_method != TS_HTTP_METHOD_POST) {
+      ok = false;
+      TSHttpTxnReenable(txn, TS_EVENT_HTTP_CONTINUE);
+      return 0;
+    }
+  }
+
+  TSHttpStatus status = TSHttpHdrStatusGet(response_header_buf, response_header_loc);
+  if (ok) {
+    if (!(status == TS_HTTP_STATUS_OK || status == TS_HTTP_STATUS_NOT_FOUND)) {
+      ok = false;
+      TSHttpTxnReenable(txn, TS_EVENT_HTTP_CONTINUE);
+      return 0;
+    }
+  }
+  if (ok) { 
+    StringPiece s_content_type = get_header(response_header_buf, response_header_loc, "Content-Type");
+    const net_instaweb::ContentType* content_type =
+        net_instaweb::MimeTypeToContentType(s_content_type);
+
+    if ((content_type == NULL || !content_type->IsHtmlLike())) {
+      ok = false;
+      TSHttpTxnReenable(txn, TS_EVENT_HTTP_CONTINUE);
+      return 0;
+    }
+  }
+  
+  if (ok) {
+    StringPiece content_encoding = get_header(response_header_buf, response_header_loc, "Content-Encoding");
+    net_instaweb::GzipInflater::InflateType inflate_type;
+    bool is_encoded = false;
+  
+    if (StringCaseEqual(content_encoding, "deflate")) {
+      is_encoded = true;
+      inflate_type = GzipInflater::kDeflate;
+    } else if (StringCaseEqual(content_encoding, "gzip")) {
+      is_encoded = true;
+      inflate_type = GzipInflater::kGzip;
+    }
+
+    if (is_encoded) {
+      ctx->inflater = new GzipInflater(inflate_type);
+      ctx->inflater->Init();
+    }
+    TSDebug(DEBUG_TAG, "Will optimize [%s]", ctx->url_string->c_str());
+    ctx->html_rewrite = true;
+    set_header(response_header_buf,response_header_loc,"@gzip_nocache","0");
+    ats_pagespeed_transform_add(txn);
+  }
+
+  TSHandleMLocRelease(response_header_buf, TS_NULL_MLOC, response_header_loc);    
+  TSHttpTxnReenable(txn, TS_EVENT_HTTP_CONTINUE);
+    
+  return 0;
+}
+
+bool RegisterPlugin() {
+  TSPluginRegistrationInfo info;
+
+  info.plugin_name = (char *)"ats_pagespeed";
+  info.vendor_name = (char *)"Apache Software Foundation";
+  info.support_email = (char *)"dev@trafficserver.apache.org";
+
+  if (TSPluginRegister(TS_SDK_VERSION_3_0, &info) != TS_SUCCESS) {
+    TSError("Failed to register ATSSpeed");
+    return false;
+  }
+
+  return true;
+}
+
+void cleanup_process() {
+  delete ats_process_context;
+  AtsRewriteDriverFactory::Terminate(); 
+  AtsRewriteOptions::Terminate(); 
+}
+
+static void
+process_configuration()
+{
+  AtsConfig* new_config = new AtsConfig((AtsThreadSystem*)ats_process_context->server_context()->thread_system());
+  DIR *dir;
+  struct dirent *ent;
+  
+  if ((dir = opendir ("/usr/local/etc/trafficserver/psol/")) != NULL) {
+    while ((ent = readdir (dir)) != NULL) {
+      size_t len = strlen(ent->d_name);
+      if (len <= 0) continue;
+      if (ent->d_name[0] == '.') continue;
+      if (ent->d_name[len-1] == '~') continue;
+      if (ent->d_name[0] == '#') continue;
+      GoogleString s("/usr/local/etc/trafficserver/psol/");
+      s.append(ent->d_name);
+      fprintf (stderr, "parse [%s]\n", s.c_str());
+      if (!new_config->Parse(s.c_str())) {
+        TSError("Error parsing %s", s.c_str());
+      }
+    }
+    closedir (dir);
+  }
+
+  AtsConfig* old_config;
+  TSMutexLock(config_mutex);
+  fprintf(stderr, "Update configuration\n");
+  old_config = config;
+  config = new_config;
+  TSMutexUnlock(config_mutex);
+  if (old_config != NULL) {
+    delete old_config;
+  }
+}
+
+static void *
+config_notification_callback(void *data)
+{
+  int BUF_MAX = 1024 * (sizeof(struct inotify_event) + 16);
+  char buf[BUF_MAX];
+  int fd,wd;
+  
+  fd = inotify_init();
+
+  if (fd < 0) {
+    perror( "inotify_init" );
+    CHECK(false) << "Failed to initialize inotify";
+  }
+  
+  wd = inotify_add_watch(fd, "/usr/local/etc/trafficserver/psol/", IN_MODIFY | IN_CREATE | IN_DELETE);
+
+  while (1) {
+    int len = read(fd, buf, BUF_MAX);
+    int i = 0;
+    bool do_update = false;
+    while ( i < len ) {
+      struct inotify_event *event = ( struct inotify_event * ) &buf[ i ];
+      if ( event->len ) {
+        if (!(event->mask & IN_ISDIR)) {
+          const char* name = event->name;
+          size_t name_len = strlen(event->name);
+          if (name_len > 0 && name[0] != '.' && name[0] != '#' && name[name_len-1] != '~' ) {
+            do_update = true;
+          }
+        }
+      }
+      i += ( sizeof (struct inotify_event) ) + event->len;
+    }
+    if (do_update) {
+      process_configuration();
+    }
+  }
+
+  inotify_rm_watch( fd, wd );
+  close( fd );
+
+  return NULL;
+}
+
+
+void TSPluginInit(int argc, const char *argv[]) {
+  if (RegisterPlugin() == true) {
+    if (TSHttpArgIndexReserve("ats_pagespeed", "Stores the transaction context", &TXN_INDEX_ARG) != TS_SUCCESS) {
+      CHECK(false) << "failed to reserve an argument index";
+    }
+    if (TSHttpArgIndexReserve("ats_pagespeed", "Stores the transaction context", &TXN_INDEX_OWNED_ARG) != TS_SUCCESS) {
+      CHECK(false) << "failed to reserve an argument index";
+    }
+
+    AtsRewriteOptions::Initialize(); 
+    AtsRewriteDriverFactory::Initialize(); 
+    net_instaweb::log_message_handler::Install();
+    atexit(cleanup_process);
+    ats_process_context = new AtsProcessContext();
+    process_configuration();
+    TSCont transform_contp = TSContCreate(transform_plugin, NULL);
+    TSHttpHookAdd(TS_HTTP_READ_RESPONSE_HDR_HOOK, transform_contp);
+    TSHttpHookAdd(TS_HTTP_READ_CACHE_HDR_HOOK, transform_contp);
+    TSHttpHookAdd(TS_HTTP_SEND_REQUEST_HDR_HOOK, transform_contp);
+    TSHttpHookAdd(TS_HTTP_READ_REQUEST_HDR_HOOK, transform_contp);
+    TSHttpHookAdd(TS_HTTP_TXN_CLOSE_HOOK, transform_contp);
+    TSHttpHookAdd(TS_HTTP_SEND_RESPONSE_HDR_HOOK, transform_contp);
+
+    setup_resource_intercept();
+    CHECK(TSThreadCreate(config_notification_callback, NULL)) << "";
+    ats_process_context->message_handler()->Message(
+        kInfo, "TSPluginInit OK");
+  }
+}

http://git-wip-us.apache.org/repos/asf/trafficserver/blob/e8b899b0/plugins/experimental/ats_pagespeed/ats_pagespeed.h
----------------------------------------------------------------------
diff --git a/plugins/experimental/ats_pagespeed/ats_pagespeed.h b/plugins/experimental/ats_pagespeed/ats_pagespeed.h
new file mode 100644
index 0000000..ccf897a
--- /dev/null
+++ b/plugins/experimental/ats_pagespeed/ats_pagespeed.h
@@ -0,0 +1,102 @@
+/** @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.
+*/
+
+#ifndef ATS_PAGESPEED_H_
+#define ATS_PAGESPEED_H_
+
+#include <string>
+
+#include <ts/ts.h>
+
+#include "net/instaweb/util/public/google_url.h"
+#include "net/instaweb/util/public/string.h"
+#include "net/instaweb/util/public/string_util.h"
+
+namespace net_instaweb {
+
+class AtsBaseFetch;
+class AtsRewriteOptions;
+class AtsServerContext;
+class GzipInflater;
+class ProxyFetch;
+class RewriteOptions;
+class RequestHeaders;
+class ResponseHeaders;
+class ServerContext;
+
+}  // namespace net_instaweb
+
+enum transform_state {
+    transform_state_initialized,
+    transform_state_output,
+    transform_state_finished
+};
+
+typedef struct
+{
+  TSHttpTxn txn;
+  TSVIO downstream_vio;
+  TSIOBuffer downstream_buffer;
+  int64_t downstream_length;
+  enum transform_state state;
+
+  net_instaweb::AtsBaseFetch* base_fetch;
+  net_instaweb::ProxyFetch* proxy_fetch;
+  net_instaweb::GzipInflater* inflater;
+
+  bool write_pending;
+  bool fetch_done;
+  GoogleString* url_string;
+  bool beacon_request;
+  bool resource_request;
+  bool mps_user_agent;
+  bool transform_added;
+  net_instaweb::GoogleUrl* gurl;
+  net_instaweb::AtsServerContext* server_context;
+  GoogleString* user_agent;
+  bool html_rewrite;
+  const char* request_method;
+  int alive;
+  net_instaweb::AtsRewriteOptions* options;
+  // TODO: Use GoogleString*
+  std::string* to_host;
+} TransformCtx;
+
+TransformCtx* get_transaction_context(TSHttpTxn txnp);
+void ats_ctx_destroy(TransformCtx * ctx);
+bool cache_hit(TSHttpTxn txnp);
+
+bool ps_determine_options(net_instaweb::ServerContext* server_context,
+  // Directory-specific options, usually null.  They've already been rebased off
+  // of the global options as part of the configuration process.
+                          net_instaweb::RewriteOptions* directory_options,
+                          net_instaweb::RequestHeaders* request_headers,
+                          net_instaweb::ResponseHeaders* response_headers,
+                          net_instaweb::RewriteOptions** options,
+                          net_instaweb::GoogleUrl* url);
+
+void copy_request_headers_to_psol(TSMBuffer bufp, TSMLoc hdr_loc, net_instaweb::RequestHeaders* psol_headers);
+// You will own options returned by this:
+net_instaweb::AtsRewriteOptions* get_host_options(const StringPiece& host);
+
+#endif /* ATS_PAGESPEED_H_ */

http://git-wip-us.apache.org/repos/asf/trafficserver/blob/e8b899b0/plugins/experimental/ats_pagespeed/ats_process_context.cc
----------------------------------------------------------------------
diff --git a/plugins/experimental/ats_pagespeed/ats_process_context.cc b/plugins/experimental/ats_pagespeed/ats_process_context.cc
new file mode 100644
index 0000000..f3ca481
--- /dev/null
+++ b/plugins/experimental/ats_pagespeed/ats_process_context.cc
@@ -0,0 +1,86 @@
+/** @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.
+*/
+
+#include "ats_process_context.h"
+
+#include <vector>
+
+#include "ats_rewrite_driver_factory.h"
+#include "ats_server_context.h"
+#include "ats_message_handler.h"
+#include "ats_thread_system.h"
+
+#include "net/instaweb/automatic/public/proxy_fetch.h"
+#include "net/instaweb/util/public/pthread_shared_mem.h"
+
+namespace net_instaweb {
+
+  AtsProcessContext::AtsProcessContext() : ProcessContext() {
+  AtsThreadSystem* ts = new AtsThreadSystem();
+  message_handler_.reset(new AtsMessageHandler(ts->NewMutex()));
+  driver_factory_.reset(
+    new AtsRewriteDriverFactory(
+      *this, ts, ""/*hostname, not used*/, -1/*port, not used*/));
+  server_context_ = driver_factory()->MakeAtsServerContext();
+
+  AtsRewriteOptions* root_options_ = (AtsRewriteOptions*)driver_factory_->default_options();
+  AtsRewriteOptions* server_options = root_options_->Clone();
+  AtsRewriteOptions* options = new AtsRewriteOptions(driver_factory_->thread_system());
+  server_options->Merge(*options);
+  delete options;
+
+  server_context_->global_options()->Merge(*server_options);
+  delete server_options;
+
+  message_handler_->Message(kInfo,"global default options:\r\n[%s]",driver_factory_->default_options()->OptionsToString().c_str());
+  message_handler_->Message(kInfo,"server ctx default options:\r\n[%s]",server_context_->global_options()->OptionsToString().c_str());
+  std::vector<SystemServerContext*> server_contexts;
+  server_contexts.push_back(server_context_);
+  
+  //Statistics* statistics =
+  //    driver_factory_->MakeGlobalSharedMemStatistics(*(SystemRewriteOptions*)server_context_->global_options());
+  GoogleString error_message;
+  int error_index = -1;
+  Statistics* global_statistics = NULL;
+  driver_factory_.get()->PostConfig(
+      server_contexts, &error_message, &error_index, &global_statistics);
+  if (error_index != -1) {
+     server_contexts[error_index]->message_handler()->Message(
+         kError, "ngx_pagespeed is enabled. %s", error_message.c_str());
+     //return NGX_ERROR;
+     CHECK(false);
+  }
+  
+  AtsRewriteDriverFactory::InitStats(global_statistics);
+    
+  driver_factory()->RootInit();
+  driver_factory()->ChildInit();
+
+  proxy_fetch_factory_.reset(new ProxyFetchFactory(server_context_));
+  message_handler_->Message(kInfo, "Process context constructed");
+}
+
+AtsProcessContext::~AtsProcessContext() {
+}
+
+}  // namespace net_instaweb

http://git-wip-us.apache.org/repos/asf/trafficserver/blob/e8b899b0/plugins/experimental/ats_pagespeed/ats_process_context.h
----------------------------------------------------------------------
diff --git a/plugins/experimental/ats_pagespeed/ats_process_context.h b/plugins/experimental/ats_pagespeed/ats_process_context.h
new file mode 100644
index 0000000..aa344b2
--- /dev/null
+++ b/plugins/experimental/ats_pagespeed/ats_process_context.h
@@ -0,0 +1,58 @@
+/** @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.
+*/
+
+#ifndef ATS_PROCESS_CONTEXT_H_
+#define ATS_PROCESS_CONTEXT_H_
+
+#include "net/instaweb/util/public/google_message_handler.h"
+#include "net/instaweb/util/public/message_handler.h"
+#include "net/instaweb/util/public/scoped_ptr.h"
+#include "net/instaweb/rewriter/public/process_context.h"
+
+namespace net_instaweb {
+
+class AtsRewriteDriverFactory;
+class ProxyFetchFactory;
+class AtsServerContext;
+
+class AtsProcessContext : ProcessContext {
+ public:
+  explicit AtsProcessContext();
+  virtual ~AtsProcessContext();
+
+  // TODO(oschaaf): const correctness
+  MessageHandler* message_handler() { return message_handler_.get(); }
+  AtsRewriteDriverFactory* driver_factory() { return driver_factory_.get(); }
+  ProxyFetchFactory* proxy_fetch_factory() { return proxy_fetch_factory_.get(); }
+  AtsServerContext* server_context() { return server_context_; }
+ private:
+  scoped_ptr<MessageHandler> message_handler_;
+  scoped_ptr<AtsRewriteDriverFactory> driver_factory_;
+  scoped_ptr<ProxyFetchFactory> proxy_fetch_factory_;
+  AtsServerContext* server_context_;
+};
+
+
+}  // namespace net_instaweb
+
+#endif // ATS_PROCESS_CONTEXT_H_

http://git-wip-us.apache.org/repos/asf/trafficserver/blob/e8b899b0/plugins/experimental/ats_pagespeed/ats_resource_intercept.cc
----------------------------------------------------------------------
diff --git a/plugins/experimental/ats_pagespeed/ats_resource_intercept.cc b/plugins/experimental/ats_pagespeed/ats_resource_intercept.cc
new file mode 100644
index 0000000..42ece8f
--- /dev/null
+++ b/plugins/experimental/ats_pagespeed/ats_resource_intercept.cc
@@ -0,0 +1,363 @@
+/** @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.
+*/
+
+#include <ts/ts.h>
+
+#include <stdio.h>
+
+#include "ats_resource_intercept.h"
+
+
+#include "ats_base_fetch.h"
+#include "ats_rewrite_driver_factory.h"
+#include "ats_rewrite_options.h"
+#include "ats_server_context.h"
+#include "ats_pagespeed.h"
+
+#include "net/instaweb/http/public/request_context.h"
+#include "net/instaweb/rewriter/public/resource_fetch.h"
+#include "net/instaweb/rewriter/public/static_asset_manager.h"
+#include "net/instaweb/system/public/system_request_context.h"
+
+#include "net/instaweb/util/public/string_writer.h"
+
+
+using namespace net_instaweb;
+
+struct InterceptCtx
+{
+  TSVConn vconn;
+  TSIOBuffer req_buffer;
+  TSIOBufferReader req_reader;
+  TSIOBuffer resp_buffer;
+  TSIOBufferReader resp_reader;
+  GoogleString* response;
+  TransformCtx* request_ctx;
+  RequestHeaders* request_headers;
+  
+  InterceptCtx()
+      : vconn(NULL)
+      , req_buffer(NULL)
+      , req_reader(NULL)
+      , resp_buffer(NULL)
+      , resp_reader(NULL)
+      , response( new GoogleString() )
+      , request_ctx(NULL)
+      , request_headers(NULL)
+  {
+  };
+};
+
+static void
+shutdown (TSCont cont, InterceptCtx * intercept_ctx) {
+  if (intercept_ctx->req_reader != NULL) {
+    TSIOBufferReaderFree(intercept_ctx->req_reader);
+    intercept_ctx->req_reader = NULL;
+  }
+  if (intercept_ctx->req_buffer != NULL) {
+    TSIOBufferDestroy(intercept_ctx->req_buffer);
+    intercept_ctx->req_buffer = NULL;
+  }
+  if (intercept_ctx->resp_reader != NULL) {
+    TSIOBufferReaderFree(intercept_ctx->resp_reader);
+    intercept_ctx->resp_reader = NULL;
+  }
+  if (intercept_ctx->resp_buffer != NULL) {
+    TSIOBufferDestroy(intercept_ctx->resp_buffer);
+    intercept_ctx->resp_buffer = NULL;
+  }
+  if (intercept_ctx->vconn != NULL) {
+    TSVConnShutdown(intercept_ctx->vconn, 0, 1);
+    TSVConnClose(intercept_ctx->vconn);
+    intercept_ctx->vconn = NULL;
+  }
+  if (intercept_ctx->response != NULL) {
+    delete intercept_ctx->response;
+    intercept_ctx->response = NULL;
+  }
+  // TODO(oschaaf): think the ordering of this one through.
+  if (intercept_ctx->request_ctx) {
+    ats_ctx_destroy(intercept_ctx->request_ctx);
+    intercept_ctx->request_ctx = NULL;
+  }
+  if (intercept_ctx->request_headers != NULL) {
+    delete intercept_ctx->request_headers;
+    intercept_ctx->request_headers = NULL;
+  }
+  delete intercept_ctx;
+  TSContDestroy(cont);
+}
+
+static int
+resource_intercept(TSCont cont, TSEvent event, void *edata)
+{
+  InterceptCtx *intercept_ctx = static_cast<InterceptCtx *>(TSContDataGet(cont));
+  bool shutDown = false;
+
+  // TODO(oschaaf): have a look at https://github.com/apache/trafficserver/blob/master/plugins/experimental/esi/serverIntercept.c
+  // and see if we have any edge cases we should fix.
+  switch (event) {
+    case TS_EVENT_NET_ACCEPT: {
+      intercept_ctx->vconn = static_cast<TSVConn>(edata);
+      intercept_ctx->req_buffer = TSIOBufferCreate();
+      intercept_ctx->req_reader = TSIOBufferReaderAlloc(intercept_ctx->req_buffer);
+      intercept_ctx->resp_buffer = TSIOBufferCreate();
+      intercept_ctx->resp_reader = TSIOBufferReaderAlloc(intercept_ctx->resp_buffer);
+      TSVConnRead(intercept_ctx->vconn, cont, intercept_ctx->req_buffer, 0x7fffffff);
+    } break;
+    case TS_EVENT_VCONN_READ_READY: {
+      CHECK(intercept_ctx->request_ctx->base_fetch == NULL) << "Base fetch must not be set!";
+      CHECK(intercept_ctx->request_ctx->url_string != NULL) << "Url must be set!";
+
+      TSVConnShutdown(intercept_ctx->vconn, 1, 0);
+
+      // response will already have a size for internal pages at this point.
+      // resources, however, will have to be fetched.
+      // TODO(oschaaf): this is extremely ugly.
+      if (intercept_ctx->response->size() == 0) { 
+        // TODO(oschaaf): unused - must we close / clean this up?
+        TSVIO downstream_vio = TSVConnWrite(
+            intercept_ctx->vconn, cont, intercept_ctx->resp_reader, 0x7fffffff);
+
+        AtsServerContext* server_context = intercept_ctx->request_ctx->server_context;
+
+        // TODO:(oschaaf) host/port
+        SystemRequestContext* system_request_context = 
+            new SystemRequestContext(server_context->thread_system()->NewMutex(),
+                                     server_context->timer(),
+				     "www.foo.com",// TODO(oschaaf): compute these
+                                     80,
+                                     "127.0.0.1");
+
+        intercept_ctx->request_ctx->base_fetch = new AtsBaseFetch(
+            server_context, RequestContextPtr(system_request_context),
+            downstream_vio, intercept_ctx->resp_buffer, true);
+        intercept_ctx->request_ctx->base_fetch->set_request_headers(
+            intercept_ctx->request_headers);
+
+        RewriteOptions* options = NULL;
+         
+        //const char* host = intercept_ctx->request_headers->Lookup1(HttpAttributes::kHost);
+        const char* host = intercept_ctx->request_ctx->gurl->HostAndPort().as_string().c_str();
+        if (host != NULL && strlen(host) > 0) {
+          intercept_ctx->request_ctx->options = get_host_options(host);
+        }
+        
+        // TODO(oschaaf): directory options should be coming from configuration!
+        bool ok = ps_determine_options(server_context,
+                                       intercept_ctx->request_ctx->options,
+                                       intercept_ctx->request_ctx->base_fetch->request_headers(),
+                                       intercept_ctx->request_ctx->base_fetch->response_headers(),
+                                       &options,
+                                       intercept_ctx->request_ctx->gurl);
+        
+        // Take ownership of custom_options.
+        scoped_ptr<RewriteOptions> custom_options(options);
+        
+        if (!ok) {
+          TSError("Failure while determining request options for psol resource");
+          // options = server_context->global_options();
+        } else {
+          // ps_determine_options modified url, removing any ModPagespeedFoo=Bar query
+          // parameters.  Keep url_string in sync with url.
+          // TODO(oschaaf): we really should determine if we have to do the lookup
+          intercept_ctx->request_ctx->gurl->Spec().CopyToString(intercept_ctx->request_ctx->url_string);
+        }
+
+        // The url we have here is already checked for IsWebValid()
+        net_instaweb::ResourceFetch::Start(
+            GoogleUrl(*intercept_ctx->request_ctx->url_string),
+            custom_options.release() /* null if there aren't custom options */,
+            false /* using_spdy */, server_context, intercept_ctx->request_ctx->base_fetch);
+      } else {
+        int64_t numBytesToWrite, numBytesWritten;
+        numBytesToWrite = intercept_ctx->response->size();
+        numBytesWritten = TSIOBufferWrite(intercept_ctx->resp_buffer,
+                                          intercept_ctx->response->c_str(), numBytesToWrite);
+        
+        if (numBytesWritten == numBytesToWrite) {
+          TSVConnWrite(intercept_ctx->vconn, cont, intercept_ctx->resp_reader, numBytesToWrite);
+        } else {
+          TSError("Not all output could be written in one go");
+          DCHECK(false);
+        }
+      }
+    }  break;
+    case TS_EVENT_VCONN_EOS:
+      TSVConnShutdown(intercept_ctx->vconn, 1, 0);
+      break;
+    case TS_EVENT_VCONN_READ_COMPLETE: {
+      TSVConnShutdown(intercept_ctx->vconn, 1, 0);
+    } break;
+    case TS_EVENT_VCONN_WRITE_READY:
+      break;
+    case TS_EVENT_VCONN_WRITE_COMPLETE:
+      shutDown = true;
+      break;
+    case TS_EVENT_ERROR:
+      TSError("vconn event: error %s", intercept_ctx->request_ctx->url_string->c_str());
+      shutDown = true;
+      break;
+    case TS_EVENT_NET_ACCEPT_FAILED:
+      TSError("vconn event: accept failed");
+      shutDown = true;
+      break;
+    case TS_EVENT_IMMEDIATE:
+    case TS_EVENT_TIMEOUT:
+      break;
+    default:
+      TSError("default clause event: %d", event);
+      break;
+  }
+
+  if (shutDown) {
+    shutdown(cont, intercept_ctx);
+  }
+
+  return 1;
+}
+
+// We intercept here because serving from ats's own cache is faster
+// then serving from pagespeed's cache. (which needs to be looked in to)
+static int
+read_cache_header_callback(TSCont cont, TSEvent event, void *edata)
+{
+  TSHttpTxn txn = static_cast<TSHttpTxn>(edata);
+  TransformCtx* ctx = get_transaction_context(txn);
+
+  if (ctx == NULL) {
+    TSHttpTxnReenable(txn, TS_EVENT_HTTP_CONTINUE);
+    return 0;
+  }
+  if (!ctx->resource_request) {
+    TSHttpTxnReenable(txn, TS_EVENT_HTTP_CONTINUE);
+    return 0;    
+  }
+  // TODO(oschaaf): FIXME: Ownership of ctx has become too mucky.
+  // This is because I realised too late that the intercepts
+  // are able to outlive the transaction, which I hacked
+  // to work.
+  if (TSHttpIsInternalRequest(txn) == TS_SUCCESS) {
+    ats_ctx_destroy(ctx);
+    TSHttpTxnReenable(txn, TS_EVENT_HTTP_CONTINUE);
+    return 0;
+  }
+  
+  if (cache_hit(txn)) {
+    ats_ctx_destroy(ctx);
+    TSHttpTxnReenable(txn, TS_EVENT_HTTP_CONTINUE);
+    return 0;
+  }
+
+  AtsServerContext* server_context = ctx->server_context;
+  AtsRewriteDriverFactory* factory = (AtsRewriteDriverFactory*)server_context->factory();
+  GoogleString output;
+  StringWriter writer(&output);
+  HttpStatus::Code status = HttpStatus::kOK;
+  ContentType content_type = kContentTypeHtml;
+  StringPiece cache_control = HttpAttributes::kNoCache;
+  const char* error_message = NULL;
+  StringPiece request_uri_path = ctx->gurl->PathAndLeaf();  
+  
+  if (false && ctx->gurl->PathSansQuery() == "/robots.txt") {
+    content_type = kContentTypeText;
+    writer.Write("User-agent: *\n", server_context->message_handler());
+    writer.Write("Disallow: /\n", server_context->message_handler());
+  }
+ 
+  // TODO(oschaaf): /pagespeed_admin handling
+  else { 
+    // Optimized resource are highly cacheable (1 year expiry)
+    // TODO(oschaaf): configuration
+    TSHttpTxnRespCacheableSet(txn, 1);
+    TSHttpTxnReqCacheableSet(txn, 1);
+
+    TSMBuffer reqp;
+    TSMLoc req_hdr_loc;
+    if (TSHttpTxnClientReqGet(ctx->txn, &reqp, &req_hdr_loc) != TS_SUCCESS) {
+      TSError("Error TSHttpTxnClientReqGet for resource!");
+      TSHttpTxnReenable(txn, TS_EVENT_HTTP_CONTINUE);
+      return 0;
+    }
+    
+    TSCont interceptCont = TSContCreate(resource_intercept, TSMutexCreate());
+    InterceptCtx *intercept_ctx = new InterceptCtx();
+    intercept_ctx->request_ctx = ctx;
+    intercept_ctx->request_headers = new RequestHeaders();
+    copy_request_headers_to_psol(reqp, req_hdr_loc, intercept_ctx->request_headers);
+    TSHandleMLocRelease(reqp, TS_NULL_MLOC, req_hdr_loc);
+
+    
+    TSContDataSet(interceptCont, intercept_ctx);
+    TSHttpTxnServerIntercept(interceptCont, txn);
+    TSHttpTxnReenable(txn, TS_EVENT_HTTP_CONTINUE);
+    return 0;
+  } 
+
+  if (error_message != NULL) {
+    status = HttpStatus::kNotFound;
+    content_type = kContentTypeHtml;
+    output = error_message;
+  }
+
+  ResponseHeaders response_headers;
+  response_headers.SetStatusAndReason(status);
+  response_headers.set_major_version(1);
+  response_headers.set_minor_version(0);
+
+  response_headers.Add(HttpAttributes::kContentType, content_type.mime_type());
+
+  int64 now_ms = factory->timer()->NowMs();
+  response_headers.SetDate(now_ms);
+  response_headers.SetLastModified(now_ms);
+  response_headers.Add(HttpAttributes::kCacheControl, cache_control);
+
+  if (FindIgnoreCase(cache_control, "private") ==
+      static_cast<int>(StringPiece::npos)) {
+    response_headers.Add(HttpAttributes::kEtag, "W/\"0\"");
+  }
+
+  GoogleString header;
+  StringWriter header_writer(&header);
+  response_headers.WriteAsHttp(&header_writer, server_context->message_handler());
+  
+  TSCont interceptCont = TSContCreate(resource_intercept, TSMutexCreate());
+  InterceptCtx *intercept_ctx = new InterceptCtx(); 
+  intercept_ctx->request_ctx = ctx;
+  header.append(output);
+  TSHttpTxnRespCacheableSet(txn, 0);
+  TSHttpTxnReqCacheableSet(txn, 0);
+  TSContDataSet(interceptCont, intercept_ctx);
+  TSHttpTxnServerIntercept(interceptCont, txn);
+  intercept_ctx->response->append(header);
+  
+  TSHttpTxnReenable(txn, TS_EVENT_HTTP_CONTINUE);
+  return 0;
+}
+
+void setup_resource_intercept()
+{
+  TSCont cont = TSContCreate(read_cache_header_callback, NULL);
+  TSHttpHookAdd(TS_HTTP_CACHE_LOOKUP_COMPLETE_HOOK, cont);
+}
+

http://git-wip-us.apache.org/repos/asf/trafficserver/blob/e8b899b0/plugins/experimental/ats_pagespeed/ats_resource_intercept.h
----------------------------------------------------------------------
diff --git a/plugins/experimental/ats_pagespeed/ats_resource_intercept.h b/plugins/experimental/ats_pagespeed/ats_resource_intercept.h
new file mode 100644
index 0000000..933f20f
--- /dev/null
+++ b/plugins/experimental/ats_pagespeed/ats_resource_intercept.h
@@ -0,0 +1,29 @@
+/** @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.
+*/
+
+#ifndef ATS_RESOURCE_INTERCEPT_H
+#define ATS_RESOURCE_INTERCEPT_H
+
+void setup_resource_intercept();
+
+#endif // ATS_INTERCEPT_H

http://git-wip-us.apache.org/repos/asf/trafficserver/blob/e8b899b0/plugins/experimental/ats_pagespeed/ats_rewrite_driver_factory.cc
----------------------------------------------------------------------
diff --git a/plugins/experimental/ats_pagespeed/ats_rewrite_driver_factory.cc b/plugins/experimental/ats_pagespeed/ats_rewrite_driver_factory.cc
new file mode 100644
index 0000000..4ca3d87
--- /dev/null
+++ b/plugins/experimental/ats_pagespeed/ats_rewrite_driver_factory.cc
@@ -0,0 +1,196 @@
+/** @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.
+*/
+
+#include "ats_rewrite_driver_factory.h"
+
+#include <cstdio>
+#include <vector>
+
+#include "ats_thread_system.h"
+#include "ats_message_handler.h"
+#include "ats_server_context.h"
+
+#include "net/instaweb/http/public/content_type.h"
+#include "net/instaweb/http/public/rate_controller.h"
+#include "net/instaweb/http/public/rate_controlling_url_async_fetcher.h"
+#include "net/instaweb/http/public/wget_url_fetcher.h"
+#include "net/instaweb/rewriter/public/rewrite_driver.h"
+#include "net/instaweb/rewriter/public/rewrite_driver_factory.h"
+#include "net/instaweb/rewriter/public/server_context.h"
+#include "net/instaweb/rewriter/public/static_asset_manager.h"
+#include "net/instaweb/system/public/in_place_resource_recorder.h"
+#include "net/instaweb/system/public/serf_url_async_fetcher.h"
+#include "net/instaweb/system/public/system_caches.h"
+#include "net/instaweb/system/public/system_rewrite_options.h"
+#include "net/instaweb/util/public/google_message_handler.h"
+#include "net/instaweb/util/public/null_shared_mem.h"
+#include "net/instaweb/util/public/posix_timer.h"
+#include "net/instaweb/util/public/property_cache.h"
+#include "net/instaweb/util/public/pthread_shared_mem.h"
+#include "net/instaweb/util/public/scheduler_thread.h"
+#include "net/instaweb/util/public/shared_circular_buffer.h"
+#include "net/instaweb/util/public/shared_mem_statistics.h"
+#include "net/instaweb/util/public/slow_worker.h"
+#include "net/instaweb/util/public/stdio_file_system.h"
+#include "net/instaweb/util/public/string.h"
+#include "net/instaweb/util/public/string_util.h"
+#include "net/instaweb/util/public/thread_system.h"
+
+
+namespace net_instaweb {
+
+
+  AtsRewriteDriverFactory::AtsRewriteDriverFactory(
+						   const ProcessContext& process_context,
+						   AtsThreadSystem* thread_system,
+						   StringPiece hostname, int port)
+    : SystemRewriteDriverFactory(process_context, 
+				 thread_system, NULL /*default shared mem runtime*/,
+				 "" /*hostname, not used*/, -1/*port, not used*/)
+      , ats_message_handler_(new AtsMessageHandler(thread_system->NewMutex()))
+      , ats_html_parse_message_handler_(new AtsMessageHandler(thread_system->NewMutex()))
+      , use_per_vhost_statistics_(false)
+      , threads_started_(false)
+  {
+    InitializeDefaultOptions();
+    default_options()->set_beacon_url("/ats_pagespeed_beacon");
+    default_options()->set_enabled(RewriteOptions::kEnabledOn);
+    default_options()->SetRewriteLevel(RewriteOptions::kCoreFilters);
+    
+    SystemRewriteOptions* system_options = dynamic_cast<SystemRewriteOptions*>(
+									       default_options());
+    system_options->set_log_dir("/tmp/ps_log/");
+    system_options->set_statistics_logging_enabled(true);
+
+    system_options->set_file_cache_clean_inode_limit(500000);
+    system_options->set_file_cache_clean_size_kb(1024*10000);// 10 GB
+    system_options->set_avoid_renaming_introspective_javascript(true);
+    system_options->set_file_cache_path("/tmp/ats_ps/");
+    system_options->set_lru_cache_byte_limit(163840);
+    system_options->set_lru_cache_kb_per_process(1024*500);//500 MB
+
+    system_options->set_flush_html(true);
+    
+    AtsRewriteOptions* ats_options = (AtsRewriteOptions*)system_options;
+    std::vector<std::string> args;
+    args.push_back("RateLimitBackgroundFetches");
+    args.push_back("on");
+    global_settings settings;
+    const char* msg = ats_options->ParseAndSetOptions(args, ats_message_handler_, settings);
+    CHECK(!msg);
+    
+    set_message_buffer_size(1024*128);
+    set_message_handler(ats_message_handler_);
+    set_html_parse_message_handler(ats_html_parse_message_handler_);
+    StartThreads();
+  }
+
+  AtsRewriteDriverFactory::~AtsRewriteDriverFactory() {
+    ShutDown();
+    delete ats_message_handler_;
+    ats_message_handler_ = NULL;
+    delete ats_html_parse_message_handler_;
+    ats_html_parse_message_handler_ = NULL;
+    STLDeleteElements(&uninitialized_server_contexts_);
+  }
+
+  void AtsRewriteDriverFactory::InitStaticAssetManager(StaticAssetManager* static_js_manager) {
+    static_js_manager->set_library_url_prefix("/ats_pagespeed_static/");
+  }
+
+  Hasher* AtsRewriteDriverFactory::NewHasher() {
+    return new MD5Hasher;
+  }
+
+  MessageHandler* AtsRewriteDriverFactory::DefaultHtmlParseMessageHandler() {
+    return ats_html_parse_message_handler_;
+  }
+
+  MessageHandler* AtsRewriteDriverFactory::DefaultMessageHandler() {
+    return ats_message_handler_;
+  }
+
+  FileSystem* AtsRewriteDriverFactory::DefaultFileSystem() {
+    return new StdioFileSystem();
+  }
+
+  Timer* AtsRewriteDriverFactory::DefaultTimer() {
+    return new PosixTimer;
+  }
+
+  NamedLockManager* AtsRewriteDriverFactory::DefaultLockManager() {
+    CHECK(false) << "default lock manager should not be called";
+    return NULL;
+  }
+
+  RewriteOptions* AtsRewriteDriverFactory::NewRewriteOptions() {
+    AtsRewriteOptions* options = new AtsRewriteOptions(thread_system());
+    options->SetRewriteLevel(RewriteOptions::kCoreFilters);
+    return options;
+  }
+
+  ServerContext* AtsRewriteDriverFactory::NewDecodingServerContext() {
+    ServerContext* sc = new AtsServerContext(this);
+    InitStubDecodingServerContext(sc);
+    return sc;
+  }
+
+  void AtsRewriteDriverFactory::InitStats(Statistics* statistics) {
+    // Init standard PSOL stats.
+    SystemRewriteDriverFactory::InitStats(statistics);
+    // Init Ats-specific stats.
+    AtsServerContext::InitStats(statistics);
+  }
+
+
+  AtsServerContext* AtsRewriteDriverFactory::MakeAtsServerContext() {
+    AtsServerContext* server_context = new AtsServerContext(this);
+    uninitialized_server_contexts_.insert(server_context);
+    return server_context;
+  }
+
+  ServerContext* AtsRewriteDriverFactory::NewServerContext() {
+    LOG(DFATAL) << "MakeAtsServerContext should be used instead";
+    return NULL;
+  }
+
+net_instaweb::QueuedWorkerPool* AtsRewriteDriverFactory::CreateWorkerPool(net_instaweb::RewriteDriverFactory::WorkerPoolCategory pool,
+                                                                          StringPiece name) {
+  int tc = 8;
+  TSDebug("ats_pagespeed", "Created new QueuedWorkerPool of type %d named '%s' of size %d", pool, name.data(), tc);
+  net_instaweb::QueuedWorkerPool *q_pool = new net_instaweb::QueuedWorkerPool(tc, name, thread_system());
+  return q_pool;
+}
+
+void AtsRewriteDriverFactory::StartThreads() {
+  if (threads_started_) {
+    CHECK(false) << "threads already started";
+  }
+  SchedulerThread* thread = new SchedulerThread(thread_system(), scheduler());
+  bool ok = thread->Start();
+  CHECK(ok) << "Unable to start scheduler thread";
+  defer_cleanup(thread->MakeDeleter());
+  threads_started_ = true;
+}
+
+}  // namespace net_instaweb

http://git-wip-us.apache.org/repos/asf/trafficserver/blob/e8b899b0/plugins/experimental/ats_pagespeed/ats_rewrite_driver_factory.h
----------------------------------------------------------------------
diff --git a/plugins/experimental/ats_pagespeed/ats_rewrite_driver_factory.h b/plugins/experimental/ats_pagespeed/ats_rewrite_driver_factory.h
new file mode 100644
index 0000000..de18a28
--- /dev/null
+++ b/plugins/experimental/ats_pagespeed/ats_rewrite_driver_factory.h
@@ -0,0 +1,113 @@
+/** @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.
+*/
+
+#ifndef ATS_REWRITE_DRIVER_FACTORY_H_
+#define ATS_REWRITE_DRIVER_FACTORY_H_
+
+#include <set>
+
+#include "net/instaweb/system/public/system_rewrite_driver_factory.h"
+#include "net/instaweb/util/public/md5_hasher.h"
+#include "net/instaweb/util/public/scoped_ptr.h"
+
+
+namespace net_instaweb {
+
+
+  class AbstractSharedMem;
+  //class NgxMessageHandler;
+  //class NgxRewriteOptions;
+  class AtsServerContext;
+  class AtsThreadSystem;
+  class GoogleMessageHandler;
+  //class NgxUrlAsyncFetcher;
+  class SharedCircularBuffer;
+  class SharedMemRefererStatistics;
+  class SharedMemStatistics;
+  class SlowWorker;
+  class StaticAssetManager;
+  class Statistics;
+  class StaticAssetManager;
+  //class SystemCaches;
+
+class AtsRewriteDriverFactory : public SystemRewriteDriverFactory { 
+ public:
+  explicit AtsRewriteDriverFactory(const ProcessContext& process_context,
+				   AtsThreadSystem* thread_system,
+				   StringPiece hostname, int port);
+  virtual ~AtsRewriteDriverFactory();
+
+  virtual Hasher* NewHasher();
+  virtual MessageHandler* DefaultHtmlParseMessageHandler();
+  virtual MessageHandler* DefaultMessageHandler();
+  virtual FileSystem* DefaultFileSystem();
+  virtual Timer* DefaultTimer();
+  virtual NamedLockManager* DefaultLockManager();
+  virtual RewriteOptions* NewRewriteOptions();
+  virtual ServerContext* NewDecodingServerContext();
+
+  virtual bool UseBeaconResultsInFilters() const {
+    return true;
+  }
+
+  virtual void InitStaticAssetManager(StaticAssetManager* static_js_manager);
+  
+  // Initializes all the statistics objects created transitively by
+  // AtsRewriteDriverFactory, including nginx-specific and
+  // platform-independent statistics.
+  static void InitStats(Statistics* statistics);
+
+  virtual net_instaweb::QueuedWorkerPool* CreateWorkerPool(WorkerPoolCategory pool,
+                                                           StringPiece name);
+  virtual void NonStaticInitStats(Statistics* statistics) {
+    InitStats(statistics);
+  }
+
+  AtsServerContext* MakeAtsServerContext();
+  ServerContext* NewServerContext();
+  //AbstractSharedMem* shared_mem_runtime() const {
+  //  return shared_mem_runtime_.get();
+  //}
+
+  // Starts pagespeed threads if they've not been started already.  Must be
+  // called after the caller has finished any forking it intends to do.
+  void StartThreads();
+  bool use_per_vhost_statistics() const {
+    return use_per_vhost_statistics_;
+  }
+  void set_use_per_vhost_statistics(bool x) {
+    use_per_vhost_statistics_ = x;
+  }
+
+ protected:
+ private:
+  //scoped_ptr<AbstractSharedMem> shared_mem_runtime_;
+  GoogleMessageHandler* ats_message_handler_;
+  GoogleMessageHandler* ats_html_parse_message_handler_;
+  bool use_per_vhost_statistics_;
+  bool threads_started_;
+};
+
+}  // namespace net_instaweb
+
+#endif // ATS_REWRITE_DRIVER_FACTORY_H_

http://git-wip-us.apache.org/repos/asf/trafficserver/blob/e8b899b0/plugins/experimental/ats_pagespeed/ats_rewrite_options.cc
----------------------------------------------------------------------
diff --git a/plugins/experimental/ats_pagespeed/ats_rewrite_options.cc b/plugins/experimental/ats_pagespeed/ats_rewrite_options.cc
new file mode 100644
index 0000000..172db83
--- /dev/null
+++ b/plugins/experimental/ats_pagespeed/ats_rewrite_options.cc
@@ -0,0 +1,263 @@
+/** @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.
+*/
+
+#include "ats_rewrite_options.h"
+
+#include "net/instaweb/public/version.h"
+#include "net/instaweb/rewriter/public/rewrite_options.h"
+#include "net/instaweb/util/public/timer.h"
+
+#include "net/instaweb/util/public/message_handler.h"
+#include "net/instaweb/rewriter/public/file_load_policy.h"
+
+#include "net/instaweb/util/public/stdio_file_system.h"
+
+#include "ats_message_handler.h"
+#include "ats_rewrite_driver_factory.h"
+
+using namespace std;
+
+namespace net_instaweb {
+
+
+RewriteOptions::Properties* AtsRewriteOptions::ats_properties_ = NULL;
+
+AtsRewriteOptions::AtsRewriteOptions(ThreadSystem* thread_system)
+    : SystemRewriteOptions(thread_system) {
+
+  Init();
+}
+
+void AtsRewriteOptions::Init() {
+  DCHECK(ats_properties_ != NULL)
+      << "Call AtsRewriteOptions::Initialize() before construction";
+  InitializeOptions(ats_properties_);
+}
+
+void AtsRewriteOptions::AddProperties() {
+  MergeSubclassProperties(ats_properties_);
+  AtsRewriteOptions dummy_config(NULL);
+
+  dummy_config.set_default_x_header_value(MOD_PAGESPEED_VERSION_STRING "-" LASTCHANGE_STRING);
+}
+
+void AtsRewriteOptions::Initialize() {
+  if (Properties::Initialize(&ats_properties_)) {
+    SystemRewriteOptions::Initialize();
+    AddProperties();
+  }
+}
+
+void AtsRewriteOptions::Terminate() {
+  if (Properties::Terminate(&ats_properties_)) {
+    SystemRewriteOptions::Terminate();
+  }
+}
+
+bool AtsRewriteOptions::IsDirective(StringPiece config_directive,
+                                    StringPiece compare_directive) {
+  return StringCaseEqual(config_directive, compare_directive);
+}
+
+RewriteOptions::OptionSettingResult AtsRewriteOptions::ParseAndSetOptions0(
+    StringPiece directive, GoogleString* msg, MessageHandler* handler) {
+  if (IsDirective(directive, "on")) {
+    set_enabled(RewriteOptions::kEnabledOn);
+  } else if (IsDirective(directive, "off")) {
+    set_enabled(RewriteOptions::kEnabledOff);
+  } else if (IsDirective(directive, "unplugged")) {
+    set_enabled(RewriteOptions::kEnabledUnplugged);
+  } else {
+    return RewriteOptions::kOptionNameUnknown;
+  }
+  return RewriteOptions::kOptionOk;
+}
+
+
+RewriteOptions::OptionSettingResult
+AtsRewriteOptions::ParseAndSetOptionFromName1(
+    StringPiece name, StringPiece arg,
+    GoogleString* msg, MessageHandler* handler) {
+  // FileCachePath needs error checking.
+  if (StringCaseEqual(name, kFileCachePath)) {
+    if (!StringCaseStartsWith(arg, "/")) {
+      *msg = "must start with a slash";
+      return RewriteOptions::kOptionValueInvalid;
+    }
+  }
+
+  return SystemRewriteOptions::ParseAndSetOptionFromName1(
+      name, arg, msg, handler);
+}
+
+bool AtsRewriteOptions::SetBoolFlag(bool* v, StringPiece arg) {
+  if (IsDirective(arg, "on")) {
+    *v=true;
+    return true;
+  } else if (IsDirective(arg, "off")) {
+    *v=false;
+    return true;
+  }
+  return false;
+}
+
+const char*
+AtsRewriteOptions::ParseAndSetOptions(
+    vector<string> args, MessageHandler* handler, global_settings& global_config) {
+  int n_args = args.size();
+  CHECK_GE(n_args, 1);
+
+  StringPiece directive = args[0];
+
+  // Remove initial "ModPagespeed" if there is one.
+  StringPiece mod_pagespeed("ModPagespeed");
+  if (StringCaseStartsWith(directive, mod_pagespeed)) {
+    directive.remove_prefix(mod_pagespeed.size());
+  }
+
+  GoogleString msg;
+  OptionSettingResult result;
+  if (n_args == 1) {
+    result = ParseAndSetOptions0(directive, &msg, handler);
+  } else if (n_args == 2) {
+    StringPiece arg = args[1];
+    if (IsDirective(directive, "UsePerVHostStatistics")) {
+      if (!SetBoolFlag(&global_config.use_per_vhost_statistics,arg)) {
+        msg = "Failed to set UsePerVHostStatistics value";
+        result = RewriteOptions::kOptionValueInvalid;
+      } else {
+        result = RewriteOptions::kOptionOk;
+      }
+    } /* else if (IsDirective(directive, "InstallCrashHandler")) {
+         // Not applicable
+         } */ else if (IsDirective(directive, "MessageBufferSize")) {
+      int message_buffer_size;
+      bool ok = StringToInt(arg.as_string(), &message_buffer_size);
+      if (ok && message_buffer_size >= 0) {
+        global_config.message_buffer_size = message_buffer_size;
+        result = RewriteOptions::kOptionOk;
+      } else {
+        msg = "Failed to set MessageBufferSize value";
+        result = RewriteOptions::kOptionValueInvalid;
+      }
+    } else if (IsDirective(directive, "UseNativeFetcher")) {
+      if (!SetBoolFlag(&global_config.info_urls_local_only,arg)) {
+        msg = "Failed to set UseNativeFetcher value";
+        result = RewriteOptions::kOptionValueInvalid;
+      } else {
+        msg = "Native fetcher is not available in this release";
+
+        result = RewriteOptions::kOptionValueInvalid;
+      }
+    } else if (IsDirective(directive, "InfoUrlsLocalOnly")) {
+      if (!SetBoolFlag(&global_config.info_urls_local_only, arg)) {
+        msg = "Failed to set InfoUrlsLocalOnly value";
+        result = RewriteOptions::kOptionValueInvalid;
+      } else {
+        result = RewriteOptions::kOptionOk;
+      }
+    }/* else if (IsDirective(directive, "RateLimitBackgroundFetches")) {
+        if (!SetBoolFlag(&global_config.rate_limit_background_fetches, arg)) {
+        msg = "Failed to set RateLimitBackgroundFetches value";
+        result = RewriteOptions::kOptionValueInvalid;
+        } else {
+        result = RewriteOptions::kOptionOk;
+        }
+            }  else if (IsDirective(directive, "ForceCaching")) {
+            if (!SetBoolFlag(&global_config.force_caching, arg)) {
+            msg = "Failed to set ForceCaching value";
+            result = RewriteOptions::kOptionValueInvalid;
+            } else {
+            result = RewriteOptions::kOptionOk;
+            }
+                } else if (IsDirective(directive, "ListOutstandingUrlsOnError")) {
+                if (!SetBoolFlag(&global_config.list_outstanding_urls_on_error, arg)) {
+                msg = "Failed to set ListOutstandingUrlsOnError value";
+                result = RewriteOptions::kOptionValueInvalid;
+                } else {
+                result = RewriteOptions::kOptionOk;
+                }
+                    } else if (IsDirective(directive, "TrackOriginalContentLength")) {
+                    if (!SetBoolFlag(&global_config.track_original_content_length, arg)) {
+                    msg = "Failed to set TrackOriginalContentLength value";
+                    result = RewriteOptions::kOptionValueInvalid;
+                    } else {
+                    result = RewriteOptions::kOptionOk;
+                    }
+                    } */else {
+      result = ParseAndSetOptionFromName1(directive, args[1], &msg, handler);
+    }
+  } else if (n_args == 3) {
+    if (StringCaseEqual(directive, "CreateSharedMemoryMetadataCache")) {
+      int64 kb = 0;
+      if (!StringToInt64(args[2], &kb) || kb < 0) {
+        result = RewriteOptions::kOptionValueInvalid;
+        msg = "size_kb must be a positive 64-bit integer";
+      } else {
+        global_config.shm_cache_size_kb = kb;
+        result = kOptionOk;
+        //bool ok = driver_factory->caches()->CreateShmMetadataCache(
+        //    args[1].as_string(), kb, &msg);
+        //result = ok ? kOptionOk : kOptionValueInvalid;
+      }
+    } else {
+      result = ParseAndSetOptionFromName2(directive, args[1], args[2],
+                                          &msg, handler);
+    }
+  } else if (n_args == 4) {
+    result = ParseAndSetOptionFromName3(
+        directive, args[1], args[2], args[3], &msg, handler);
+  } else {
+    return "unknown option";
+  }
+
+  if (msg.size()) {
+    handler->Message(kWarning, "Error handling config line [%s]: [%s]",
+                     JoinString(args, ' ').c_str(), msg.c_str());
+  }
+
+  switch (result) {
+    case RewriteOptions::kOptionOk:
+      return NULL;
+    case RewriteOptions::kOptionNameUnknown:
+      handler->Message(kWarning, "%s", JoinString(args, ' ').c_str());
+      return "unknown option";
+    case RewriteOptions::kOptionValueInvalid: {
+      handler->Message(kWarning, "%s", JoinString(args, ' ').c_str());
+      return "Invalid value";
+    }
+  }
+
+  CHECK(false);
+  return NULL;
+}
+
+AtsRewriteOptions* AtsRewriteOptions::Clone() const {
+  AtsRewriteOptions* options = new AtsRewriteOptions(this->thread_system());
+  options->Merge(*this);
+  return options;
+}
+
+
+}  // namespace net_instaweb
+


[4/6] ats_pagespeed: rename ats_speed -> ats_pagespeed

Posted by am...@apache.org.
http://git-wip-us.apache.org/repos/asf/trafficserver/blob/e8b899b0/plugins/experimental/ats_pagespeed/ats_rewrite_options.h
----------------------------------------------------------------------
diff --git a/plugins/experimental/ats_pagespeed/ats_rewrite_options.h b/plugins/experimental/ats_pagespeed/ats_rewrite_options.h
new file mode 100644
index 0000000..4a39dcd
--- /dev/null
+++ b/plugins/experimental/ats_pagespeed/ats_rewrite_options.h
@@ -0,0 +1,103 @@
+/** @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.
+*/
+
+#ifndef ATS_REWRITE_OPTIONS_H_
+#define ATS_REWRITE_OPTIONS_H_
+
+#include <string>
+#include <vector>
+
+#include "net/instaweb/util/public/string.h"
+#include "net/instaweb/util/public/string_util.h"
+#include "net/instaweb/rewriter/public/rewrite_options.h"
+#include "net/instaweb/system/public/system_rewrite_options.h"
+
+
+//#include "ats_configuration.h"
+
+
+namespace net_instaweb {
+
+class ThreadSystem;
+
+struct global_settings {
+  global_settings()
+  : info_urls_local_only(true)
+  , use_native_fetcher(false)
+      , use_per_vhost_statistics(true)
+      , message_buffer_size(1024*128)
+      , shm_cache_size_kb(0)
+      //, rate_limit_background_fetches(true)
+      //, force_caching(false)
+      //, list_outstanding_urls_on_error(false)
+      //, track_original_content_length(false)
+  {
+  }
+  bool info_urls_local_only;
+  bool use_native_fetcher;
+  bool use_per_vhost_statistics;
+  int message_buffer_size;
+  //bool rate_limit_background_fetches;
+  //bool force_caching;
+  //bool list_outstanding_urls_on_error;
+  //bool track_original_content_length;
+  int shm_cache_size_kb;
+};
+
+
+class AtsRewriteOptions : public SystemRewriteOptions {
+ public:
+    // See rewrite_options::Initialize and ::Terminate
+    static void Initialize();
+    static void Terminate();
+
+    AtsRewriteOptions(ThreadSystem* thread_system);
+    virtual ~AtsRewriteOptions() {
+    }
+
+    const char* ParseAndSetOptions(
+        std::vector<std::string> args, MessageHandler* handler, global_settings& global_config);
+
+    virtual AtsRewriteOptions* Clone() const;
+    OptionSettingResult ParseAndSetOptions0(
+        StringPiece directive, GoogleString* msg, MessageHandler* handler);
+
+    virtual OptionSettingResult ParseAndSetOptionFromName1(
+        StringPiece name, StringPiece arg,
+        GoogleString* msg, MessageHandler* handler);
+
+
+ private:
+    bool SetBoolFlag(bool* v, StringPiece arg);
+    static Properties* ats_properties_;
+    static void AddProperties();
+    void Init();
+
+    bool IsDirective(StringPiece config_directive, StringPiece compare_directive);
+
+    DISALLOW_COPY_AND_ASSIGN(AtsRewriteOptions);
+  };
+
+} // namespace net_instaweb
+
+#endif  // ATS_REWRITE_OPTIONS_H_

http://git-wip-us.apache.org/repos/asf/trafficserver/blob/e8b899b0/plugins/experimental/ats_pagespeed/ats_server_context.cc
----------------------------------------------------------------------
diff --git a/plugins/experimental/ats_pagespeed/ats_server_context.cc b/plugins/experimental/ats_pagespeed/ats_server_context.cc
new file mode 100644
index 0000000..4fc9eff
--- /dev/null
+++ b/plugins/experimental/ats_pagespeed/ats_server_context.cc
@@ -0,0 +1,46 @@
+/** @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.
+*/
+
+#include "ats_server_context.h"
+#include "ats_rewrite_driver_factory.h"
+#include "ats_rewrite_options.h"
+
+#include "net/instaweb/system/public/system_caches.h"
+
+
+using namespace net_instaweb;
+
+AtsRewriteOptions* AtsServerContext::config() {
+  return (AtsRewriteOptions*)global_options();
+}
+
+AtsServerContext::AtsServerContext(AtsRewriteDriverFactory* factory) :
+  // TODO(oschaaf): host/port
+  SystemServerContext(factory, "foo.com" /*hostname*/, 8080/*port*/),
+    initialized_(false),
+    ats_factory_(factory) {
+}
+
+AtsServerContext::~AtsServerContext() {
+
+}

http://git-wip-us.apache.org/repos/asf/trafficserver/blob/e8b899b0/plugins/experimental/ats_pagespeed/ats_server_context.h
----------------------------------------------------------------------
diff --git a/plugins/experimental/ats_pagespeed/ats_server_context.h b/plugins/experimental/ats_pagespeed/ats_server_context.h
new file mode 100644
index 0000000..e156ed3
--- /dev/null
+++ b/plugins/experimental/ats_pagespeed/ats_server_context.h
@@ -0,0 +1,56 @@
+/** @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.
+*/
+
+#ifndef ATS_SERVER_CONTEXT_H_
+#define ATS_SERVER_CONTEXT_H_
+
+#include "ats_rewrite_options.h"
+
+#include "net/instaweb/system/public/system_server_context.h"
+#include "net/instaweb/util/public/statistics.h"
+
+namespace net_instaweb {
+
+class AtsRewriteOptions;
+class AtsRewriteDriverFactory;
+
+class AtsServerContext : public net_instaweb::SystemServerContext {
+ public:
+  explicit AtsServerContext(AtsRewriteDriverFactory* factory);
+  virtual ~AtsServerContext();
+
+  virtual bool ProxiesHtml() const {
+    return true;
+  }
+
+  AtsRewriteOptions *config();
+  AtsRewriteDriverFactory *ats_rewrite_driver_factory() { return ats_factory_; }
+
+ private:
+  bool initialized_;
+  AtsRewriteDriverFactory* ats_factory_;
+};
+
+} /* ats_pagespeed */
+
+#endif /* ATS_SERVER_CONTEXT_H_ */

http://git-wip-us.apache.org/repos/asf/trafficserver/blob/e8b899b0/plugins/experimental/ats_pagespeed/ats_thread_system.h
----------------------------------------------------------------------
diff --git a/plugins/experimental/ats_pagespeed/ats_thread_system.h b/plugins/experimental/ats_pagespeed/ats_thread_system.h
new file mode 100644
index 0000000..e3565a8
--- /dev/null
+++ b/plugins/experimental/ats_pagespeed/ats_thread_system.h
@@ -0,0 +1,50 @@
+/** @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.
+*/
+
+#ifndef ATS_THREAD_SYSTEM_H_
+#define ATS_THREAD_SYSTEM_H_
+
+#include <pthread.h>
+
+#include <ts/ts.h>
+#include "net/instaweb/system/public/system_thread_system.h"
+#include "net/instaweb/util/public/thread.h"
+#include "net/instaweb/util/public/thread_system.h"
+#include "net/instaweb/util/public/pthread_rw_lock.h"
+#include "net/instaweb/util/public/condvar.h"
+
+namespace net_instaweb {
+
+class AtsThreadSystem : public net_instaweb::SystemThreadSystem {
+ public:
+  virtual void BeforeThreadRunHook() {
+    TSThreadInit();
+  }
+
+  virtual ~AtsThreadSystem() { }
+};
+
+} // net_instaweb
+
+
+#endif // ATS_THREAD_SYSTEM_H_

http://git-wip-us.apache.org/repos/asf/trafficserver/blob/e8b899b0/plugins/experimental/ats_pagespeed/gzip/Makefile
----------------------------------------------------------------------
diff --git a/plugins/experimental/ats_pagespeed/gzip/Makefile b/plugins/experimental/ats_pagespeed/gzip/Makefile
new file mode 100644
index 0000000..6a02ae2
--- /dev/null
+++ b/plugins/experimental/ats_pagespeed/gzip/Makefile
@@ -0,0 +1,24 @@
+#  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.
+
+TSXS?=tsxs
+
+all:
+	$(TSXS) -o gzip.so -v -C *.cc
+install: 
+	$(TSXS) -v -i -o gzip.so
+clean:
+	rm -f *.lo *.so

http://git-wip-us.apache.org/repos/asf/trafficserver/blob/e8b899b0/plugins/experimental/ats_pagespeed/gzip/README
----------------------------------------------------------------------
diff --git a/plugins/experimental/ats_pagespeed/gzip/README b/plugins/experimental/ats_pagespeed/gzip/README
new file mode 100644
index 0000000..2e74681
--- /dev/null
+++ b/plugins/experimental/ats_pagespeed/gzip/README
@@ -0,0 +1,4 @@
+This gzip is not compiled, but only here to be able to diff later
+with the official gzip plugin. It is very slightly modified no 
+be able to disable caching of its compressed output through a 
+response header
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/trafficserver/blob/e8b899b0/plugins/experimental/ats_pagespeed/gzip/configuration.cc
----------------------------------------------------------------------
diff --git a/plugins/experimental/ats_pagespeed/gzip/configuration.cc b/plugins/experimental/ats_pagespeed/gzip/configuration.cc
new file mode 100644
index 0000000..b1c499d
--- /dev/null
+++ b/plugins/experimental/ats_pagespeed/gzip/configuration.cc
@@ -0,0 +1,264 @@
+/** @file
+
+  Transforms content using gzip or deflate
+
+  @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 "configuration.h"
+#include <fstream>
+#include <algorithm>
+#include <vector>
+#include <fnmatch.h>
+
+namespace Gzip {
+  using namespace std;
+
+  void ltrim_if(string& s, int (* fp) (int)) {
+    for (size_t i = 0; i < s.size();) {
+      if (fp(s[i])) {
+        s.erase(i,1);
+      } else  {
+        break;
+      }
+    }
+  }
+
+  void rtrim_if(string& s, int (* fp) (int)) {
+    for (ssize_t i = (ssize_t)s.size() - 1; i >= 0; i--) {
+      if (fp(s[i])) {
+        s.erase(i,1);
+      } else  {
+        break;
+      }
+    }
+  }
+
+  void trim_if(string& s, int (* fp) (int)) {
+    ltrim_if(s, fp);
+    rtrim_if(s, fp);
+  }
+
+  vector<string> tokenize(const string &s, int (* fp) (int)) {
+    vector<string> r;
+    string tmp;
+
+    for (size_t i = 0; i < s.size(); i++) {
+      if ( fp(s[i]) ) {
+        if ( tmp.size()  ) {
+          r.push_back(tmp);
+          tmp = "";
+        }
+      } else {
+          tmp += s[i];
+      }
+    }
+
+    if ( tmp.size()  ) {
+      r.push_back(tmp);
+    }
+
+    return r;
+  }
+
+  enum ParserState {
+    kParseStart,
+    kParseCompressibleContentType,
+    kParseRemoveAcceptEncoding,
+    kParseEnable,
+    kParseCache,
+    kParseDisallow,
+  };
+
+  void Configuration::AddHostConfiguration(HostConfiguration * hc){
+    host_configurations_.push_back(hc);
+  }
+
+  void HostConfiguration::add_disallow(const std::string & disallow) {
+    disallows_.push_back(disallow);
+  }
+
+  void HostConfiguration::add_compressible_content_type(const std::string & content_type) {
+    compressible_content_types_.push_back(content_type);
+  }
+
+  HostConfiguration * Configuration::Find(const char * host, int host_length) {
+    HostConfiguration * host_configuration = host_configurations_[0];
+
+    std::string shost(host, host_length);
+
+    for (size_t i = 1; i < host_configurations_.size(); i++ ) {
+      if (host_configurations_[i]->host() == shost){
+        host_configuration = host_configurations_[i];
+        break;
+      }
+    }
+
+    return host_configuration;
+  }
+
+  bool HostConfiguration::IsUrlAllowed(const char * url, int url_len) {
+    string surl(url, url_len);
+
+    for (size_t i = 0; i < disallows_.size(); i++) {
+      if ( fnmatch (disallows_[i].c_str(), surl.c_str(), 0) == 0 ) {
+        info("url [%s] disabled for compression, matched on pattern [%s]",
+            surl.c_str(), disallows_[i].c_str());
+        return false;
+      }
+    }
+
+    return true;
+  }
+
+  bool HostConfiguration::ContentTypeIsCompressible(const char * content_type, int content_type_length) {
+    string scontent_type(content_type, content_type_length);
+    bool is_match = false;
+    
+    for (size_t i = 0; i < compressible_content_types_.size(); i++) {
+      const char* match_string = compressible_content_types_[i].c_str();
+      bool exclude = match_string[0] == '!';
+      if (exclude) {
+        match_string++;//skip '!'
+      }
+      if ( fnmatch (match_string, scontent_type.c_str(), 0) == 0 ) {
+        info("compressible content type [%s], matched on pattern [%s]",
+            scontent_type.c_str(), compressible_content_types_[i].c_str());
+        is_match = !exclude;
+      }
+    }
+
+    return is_match;
+  }
+
+  Configuration * Configuration::Parse(const char * path ) {
+    string pathstring(path);
+
+    // If we have a path and it's not an absolute path, make it relative to the
+    // configuration directory.
+    if (!pathstring.empty() && pathstring[0] != '/') {
+      pathstring.assign(TSConfigDirGet());
+      pathstring.append("/");
+      pathstring.append(path);
+    }
+
+    trim_if(pathstring, isspace);
+
+    Configuration * c = new Configuration();
+    HostConfiguration * current_host_configuration = new HostConfiguration("");
+    c->AddHostConfiguration(current_host_configuration);
+    current_host_configuration->add_compressible_content_type("text/*");
+    current_host_configuration->add_compressible_content_type("application/xml*");
+    current_host_configuration->add_compressible_content_type("*javascript*");
+    current_host_configuration->add_compressible_content_type("image/svg+xml");
+
+    
+    if (pathstring.empty())  {
+      return c;
+    }
+
+    path = pathstring.c_str();
+    info("Parsing file \"%s\"", path);
+    std::ifstream f;
+
+    size_t lineno = 0;
+
+    f.open(path, std::ios::in);
+
+    if (!f.is_open()) {
+      warning("could not open file [%s], skip",path);
+      return c;
+    }
+
+    enum ParserState state = kParseStart;
+
+    while (!f.eof()) {
+      std::string line;
+      getline(f, line);
+      ++lineno;
+
+      trim_if(line, isspace);
+      if (line.size() == 0) {
+        continue;
+      }
+
+      vector<string> v = tokenize( line, isspace );
+
+      for(size_t i = 0; i < v.size(); i++ ) {
+        string token = v[i];
+        trim_if(token, isspace);
+
+        //should not happen
+        if (!token.size()) continue;
+
+        //once a comment is encountered, we are done processing the line
+        if (token[0] == '#') break;
+
+        switch(state) {
+        case kParseStart:
+          if ( (token[0] == '[') && (token[token.size()-1] == ']')){
+            std::string current_host = token.substr(1,token.size()-2);
+            current_host_configuration = new HostConfiguration(current_host);
+            c->AddHostConfiguration(current_host_configuration);
+          } else if (token == "compressible-content-type" ) {
+            state = kParseCompressibleContentType;
+          } else if (token == "remove-accept-encoding" ) {
+            state = kParseRemoveAcceptEncoding;
+          } else if (token == "enabled" ) {
+            state = kParseEnable;
+          } else if (token == "cache" ) {
+            state = kParseCache;
+          } else if (token == "disallow" ) {
+            state = kParseDisallow;
+          }
+          else {
+            warning("failed to interpret \"%s\" at line %zu", token.c_str(), lineno);
+          }
+          break;
+        case kParseCompressibleContentType:
+          current_host_configuration->add_compressible_content_type(token);
+          state = kParseStart;
+          break;
+        case kParseRemoveAcceptEncoding:
+          current_host_configuration->set_remove_accept_encoding(token == "true");
+          state = kParseStart;
+          break;
+        case kParseEnable:
+          current_host_configuration->set_enabled(token == "true");
+          state = kParseStart;
+          break;
+        case kParseCache:
+          current_host_configuration->set_cache(token == "true");
+          state = kParseStart;
+          break;
+        case kParseDisallow:
+          current_host_configuration->add_disallow(token);
+          state = kParseStart;
+          break;
+        }
+      }
+    }
+
+    if (state != kParseStart) {
+      warning("the parser state indicates that data was expected when it reached the end of the file (%d)", state);
+    }
+
+    return c;
+  } //Configuration::Parse
+} //namespace

http://git-wip-us.apache.org/repos/asf/trafficserver/blob/e8b899b0/plugins/experimental/ats_pagespeed/gzip/configuration.h
----------------------------------------------------------------------
diff --git a/plugins/experimental/ats_pagespeed/gzip/configuration.h b/plugins/experimental/ats_pagespeed/gzip/configuration.h
new file mode 100644
index 0000000..b38cb64
--- /dev/null
+++ b/plugins/experimental/ats_pagespeed/gzip/configuration.h
@@ -0,0 +1,84 @@
+/** @file
+
+  Transforms content using gzip or deflate
+
+  @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 GZIP_CONFIGURATION_H_
+#define GZIP_CONFIGURATION_H_
+
+#include <string>
+#include <vector>
+#include "debug_macros.h"
+
+namespace Gzip  { 
+  class HostConfiguration {
+  public: //todo -> only configuration should be able to construct hostconfig
+    explicit HostConfiguration(const std::string & host)
+      : host_(host)
+      , enabled_(true)
+      , cache_(true)
+      , remove_accept_encoding_(false)
+    {}
+
+    inline bool enabled() { return enabled_; }
+    inline void set_enabled(bool x) { enabled_ = x; } 
+    inline bool cache() { return cache_; }
+    inline void set_cache(bool x) { cache_ = x; } 
+    inline bool remove_accept_encoding() { return remove_accept_encoding_; }
+    inline void set_remove_accept_encoding(bool x) { remove_accept_encoding_ = x; } 
+    inline std::string host() { return host_; }
+    void add_disallow(const std::string & disallow);
+    void add_compressible_content_type(const std::string & content_type);
+    bool IsUrlAllowed(const char * url, int url_len);
+    bool ContentTypeIsCompressible(const char * content_type, int content_type_length);
+
+  private:
+    std::string host_;
+    bool enabled_;
+    bool cache_;
+    bool remove_accept_encoding_;
+    std::vector<std::string> compressible_content_types_;
+    std::vector<std::string> disallows_;
+    DISALLOW_COPY_AND_ASSIGN(HostConfiguration);
+  };//class HostConfiguration
+
+  class Configuration {
+    friend class HostConfiguration;
+  public:
+    static Configuration * Parse(const char * path);
+    HostConfiguration * Find(const char * host, int host_length); 
+    inline HostConfiguration * GlobalConfiguration() {
+      return host_configurations_[0];
+    }
+
+  private:
+    explicit Configuration()  {}
+    void AddHostConfiguration(HostConfiguration * hc);
+
+    std::vector<HostConfiguration *> host_configurations_;
+    //todo: destructor. delete owned host configurations
+    DISALLOW_COPY_AND_ASSIGN(Configuration);
+  }; //class Configuration
+
+}//namespace
+
+#endif

http://git-wip-us.apache.org/repos/asf/trafficserver/blob/e8b899b0/plugins/experimental/ats_pagespeed/gzip/debug_macros.h
----------------------------------------------------------------------
diff --git a/plugins/experimental/ats_pagespeed/gzip/debug_macros.h b/plugins/experimental/ats_pagespeed/gzip/debug_macros.h
new file mode 100644
index 0000000..151de31
--- /dev/null
+++ b/plugins/experimental/ats_pagespeed/gzip/debug_macros.h
@@ -0,0 +1,59 @@
+/** @file
+
+  Transforms content using gzip or deflate
+
+  @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 _DBG_MACROS_H
+#define _DBG_MACROS_H
+
+#include <ts/ts.h>
+
+#define TAG "gzip"
+
+#define debug(fmt, args...) do {                                    \
+  TSDebug(TAG, "DEBUG: [%s:%d] [%s] " fmt, __FILE__, __LINE__, __FUNCTION__ , ##args ); \
+  } while (0)
+
+#define info(fmt, args...) do {                                    \
+  TSDebug(TAG, "INFO: " fmt, ##args ); \
+  } while (0)
+
+#define warning(fmt, args...) do {                                    \
+  TSDebug(TAG, "WARNING: " fmt, ##args ); \
+} while (0)
+
+#define error(fmt, args...) do {                                    \
+  TSError("[%s:%d] [%s] ERROR: " fmt, __FILE__, __LINE__, __FUNCTION__ , ##args ); \
+  TSDebug(TAG, "[%s:%d] [%s] ERROR: " fmt, __FILE__, __LINE__, __FUNCTION__ , ##args ); \
+} while (0)
+
+#define fatal(fmt, args...) do {                                    \
+  TSError("[%s:%d] [%s] ERROR: " fmt, __FILE__, __LINE__, __FUNCTION__ , ##args ); \
+  TSDebug(TAG, "[%s:%d] [%s] ERROR: " fmt, __FILE__, __LINE__, __FUNCTION__ , ##args ); \
+  exit(-1); \
+} while (0)
+
+//FIXME: this one doesn't deserve to be here
+#define DISALLOW_COPY_AND_ASSIGN(TypeName) \
+  TypeName(const TypeName&);               \
+  void operator=(const TypeName&)
+
+#endif //_DBG_MACROS_H

http://git-wip-us.apache.org/repos/asf/trafficserver/blob/e8b899b0/plugins/experimental/ats_pagespeed/gzip/gzip.cc
----------------------------------------------------------------------
diff --git a/plugins/experimental/ats_pagespeed/gzip/gzip.cc b/plugins/experimental/ats_pagespeed/gzip/gzip.cc
new file mode 100644
index 0000000..1397762
--- /dev/null
+++ b/plugins/experimental/ats_pagespeed/gzip/gzip.cc
@@ -0,0 +1,826 @@
+/** @file
+
+  Transforms content using gzip or deflate
+
+  @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.
+ */
+#define __STDC_LIMIT_MACROS
+#define __STDC_CONSTANT_MACROS
+#include <stdint.h>
+
+#include <string>
+#include <string.h>
+#include <zlib.h>
+#include <ts/ts.h>
+#include "debug_macros.h"
+#include "misc.h"
+#include "configuration.h"
+//#include "ink_defs.h"
+
+using namespace std;
+using namespace Gzip;
+
+//FIXME: custom dictionaries would be nice. configurable/content-type?
+//FIXME: look into autoscaling the compression level based on connection speed
+// a gprs device might benefit from a higher compression ratio, whereas a desktop w. high bandwith
+// might be served better with little or no compression at all
+//FIXME: look into compressing from the task thread pool
+//FIXME: make normalizing accept encoding configurable
+
+// from mod_deflate:
+// ZLIB's compression algorithm uses a
+// 0-9 based scale that GZIP does where '1' is 'Best speed' 
+// and '9' is 'Best compression'. Testing has proved level '6' 
+// to be about the best level to use in an HTTP Server. 
+
+const int ZLIB_COMPRESSION_LEVEL = 6;
+
+int arg_idx_hooked;
+int arg_idx_host_configuration;
+int arg_idx_url_disallowed;
+
+
+const char * global_hidden_header_name;
+Configuration* config = NULL;
+const char *dictionary = NULL;
+
+static GzipData *
+gzip_data_alloc(int compression_type)
+{
+  GzipData *data;
+  int err;
+
+  data = (GzipData *) TSmalloc(sizeof(GzipData));
+  data->downstream_vio = NULL;
+  data->downstream_buffer = NULL;
+  data->downstream_reader = NULL;
+  data->downstream_length = 0;
+  data->state = transform_state_initialized;
+  data->compression_type = compression_type;
+  data->zstrm.next_in = Z_NULL;
+  data->zstrm.avail_in = 0;
+  data->zstrm.total_in = 0;
+  data->zstrm.next_out = Z_NULL;
+  data->zstrm.avail_out = 0;
+  data->zstrm.total_out = 0;
+  data->zstrm.zalloc = gzip_alloc;
+  data->zstrm.zfree = gzip_free;
+  data->zstrm.opaque = (voidpf) 0;
+  data->zstrm.data_type = Z_ASCII;
+
+  int window_bits = (compression_type == COMPRESSION_TYPE_GZIP) ? WINDOW_BITS_GZIP : WINDOW_BITS_DEFLATE;
+
+  err = deflateInit2(&data->zstrm, ZLIB_COMPRESSION_LEVEL, Z_DEFLATED, window_bits, ZLIB_MEMLEVEL, Z_DEFAULT_STRATEGY);
+
+  if (err != Z_OK) {
+    fatal("gzip-transform: ERROR: deflateInit (%d)!", err);
+  }
+
+  if (dictionary) {
+    err = deflateSetDictionary(&data->zstrm, (const Bytef *) dictionary, strlen(dictionary));
+    if (err != Z_OK) {
+      fatal("gzip-transform: ERROR: deflateSetDictionary (%d)!", err);
+    }
+  }
+
+  return data;
+}
+
+
+static void
+gzip_data_destroy(GzipData * data)
+{
+  TSReleaseAssert(data);
+
+  //deflateEnd returnvalue ignore is intentional
+  //it would spew log on every client abort
+  deflateEnd(&data->zstrm);
+
+  if (data->downstream_buffer) {
+    TSIOBufferDestroy(data->downstream_buffer);
+  }
+
+  TSfree(data);
+}
+
+static TSReturnCode
+gzip_content_encoding_header(TSMBuffer bufp, TSMLoc hdr_loc, const int compression_type)
+{
+  TSReturnCode ret;
+  TSMLoc ce_loc;
+
+  // Delete Content-Encoding if present???
+
+  if ((ret = TSMimeHdrFieldCreateNamed(bufp, hdr_loc, "Content-Encoding", sizeof("Content-Encoding") - 1, &ce_loc)) == TS_SUCCESS) {
+    if (compression_type == COMPRESSION_TYPE_DEFLATE) {
+      ret = TSMimeHdrFieldValueStringInsert(bufp, hdr_loc, ce_loc, -1, "deflate", sizeof("deflate") - 1);
+    } else if (compression_type == COMPRESSION_TYPE_GZIP) {
+      ret = TSMimeHdrFieldValueStringInsert(bufp, hdr_loc, ce_loc, -1, "gzip", sizeof("gzip") - 1);
+    }
+    if (ret == TS_SUCCESS) {
+      ret = TSMimeHdrFieldAppend(bufp, hdr_loc, ce_loc);
+    }
+    TSHandleMLocRelease(bufp, hdr_loc, ce_loc);
+  }
+
+  if (ret != TS_SUCCESS) {
+    error("cannot add the Content-Encoding header");
+  }
+
+  return ret;
+}
+
+static TSReturnCode
+gzip_vary_header(TSMBuffer bufp, TSMLoc hdr_loc)
+{
+  TSReturnCode ret;
+  TSMLoc ce_loc;
+
+  ce_loc = TSMimeHdrFieldFind(bufp, hdr_loc, "Vary", sizeof("Vary") - 1);
+  if (ce_loc) {
+    int idx, count, len; 
+    const char *value;
+
+    count = TSMimeHdrFieldValuesCount(bufp, hdr_loc, ce_loc);
+    for(idx=0; idx<count; idx++) {
+      value = TSMimeHdrFieldValueStringGet(bufp, hdr_loc, ce_loc, idx, &len);
+      if (len &&
+          strncasecmp("Accept-Encoding", value, len) == 0) {
+        // Bail, Vary: Accept-Encoding already sent from origin
+        TSHandleMLocRelease(bufp, hdr_loc, ce_loc);
+        return TS_SUCCESS;
+      }
+    }
+
+    ret = TSMimeHdrFieldValueStringInsert(bufp, hdr_loc, ce_loc, -1, "Accept-Encoding", sizeof("Accept-Encoding") - 1);
+    TSHandleMLocRelease(bufp, hdr_loc, ce_loc);
+  } else {
+    if ((ret = TSMimeHdrFieldCreateNamed(bufp, hdr_loc, "Vary", sizeof("Vary") - 1, &ce_loc)) == TS_SUCCESS) {
+      if ((ret = TSMimeHdrFieldValueStringInsert(bufp, hdr_loc, ce_loc, -1, "Accept-Encoding", sizeof("Accept-Encoding") - 1)) == TS_SUCCESS) {
+        ret = TSMimeHdrFieldAppend(bufp, hdr_loc, ce_loc);
+      }
+
+      TSHandleMLocRelease(bufp, hdr_loc, ce_loc);
+    }
+  }
+
+  if (ret != TS_SUCCESS) {
+    error("cannot add/update the Vary header");
+  }
+
+  return ret;
+}
+
+//FIXME: the etag alteration isn't proper. it should modify the value inside quotes
+//       specify a very header..
+static TSReturnCode
+gzip_etag_header(TSMBuffer bufp, TSMLoc hdr_loc)
+{
+  TSReturnCode ret = TS_SUCCESS;
+  TSMLoc ce_loc;
+
+  ce_loc = TSMimeHdrFieldFind(bufp, hdr_loc, TS_MIME_FIELD_ETAG, TS_MIME_LEN_ETAG);
+
+  if (ce_loc) {
+    int changetag = 1;
+    int strl;
+    const char *strv = TSMimeHdrFieldValueStringGet(bufp, hdr_loc, ce_loc, -1, &strl);
+    //do not alter weak etags.
+    //FIXME: consider just making the etag weak for compressed content
+    if (strl >= 2) {
+      if ((strv[0] == 'w' || strv[0] == 'W') && strv[1] == '/') {
+        changetag = 0;
+      }
+      if (changetag) {
+        ret = TSMimeHdrFieldValueAppend(bufp, hdr_loc, ce_loc, 0, "-df", 3);
+      }
+    }
+    TSHandleMLocRelease(bufp, hdr_loc, ce_loc);
+  }
+
+  if (ret != TS_SUCCESS) {
+    error("cannot handle the %s header", TS_MIME_FIELD_ETAG);
+  }
+
+  return ret;
+}
+
+//FIXME: some things are potentially compressible. those responses
+static void
+gzip_transform_init(TSCont contp, GzipData * data)
+{
+  //update the vary, content-encoding, and etag response headers
+  //prepare the downstream for transforming
+
+  TSVConn downstream_conn;
+  TSMBuffer bufp;
+  TSMLoc hdr_loc;
+
+  data->state = transform_state_output;
+
+  if (TSHttpTxnTransformRespGet(data->txn, &bufp, &hdr_loc) != TS_SUCCESS) {
+    error("Error TSHttpTxnTransformRespGet");
+    return;
+  }
+
+  if (gzip_content_encoding_header(bufp, hdr_loc, data->compression_type) == TS_SUCCESS &&
+      gzip_vary_header(bufp, hdr_loc) == TS_SUCCESS &&
+      gzip_etag_header(bufp, hdr_loc) == TS_SUCCESS) {
+    downstream_conn = TSTransformOutputVConnGet(contp);
+    data->downstream_buffer = TSIOBufferCreate();
+    data->downstream_reader = TSIOBufferReaderAlloc(data->downstream_buffer);
+    data->downstream_vio = TSVConnWrite(downstream_conn, contp, data->downstream_reader, INT64_MAX);
+  }
+
+  TSHandleMLocRelease(bufp, TS_NULL_MLOC, hdr_loc);
+}
+
+
+
+static void
+gzip_transform_one(GzipData * data, TSIOBufferReader upstream_reader, int amount)
+{
+  TSIOBufferBlock downstream_blkp;
+  const char *upstream_buffer;
+  char *downstream_buffer;
+  int64_t upstream_length, downstream_length;
+  int err;
+
+  while (amount > 0) {
+    downstream_blkp = TSIOBufferReaderStart(upstream_reader);
+    if (!downstream_blkp) {
+      error("couldn't get from IOBufferBlock");
+      return;
+    }
+
+    upstream_buffer = TSIOBufferBlockReadStart(downstream_blkp, upstream_reader, &upstream_length);
+    if (!upstream_buffer) {
+      error("couldn't get from TSIOBufferBlockReadStart");
+      return;
+    }
+
+    if (upstream_length > amount) {
+      upstream_length = amount;
+    }
+
+    data->zstrm.next_in = (unsigned char *) upstream_buffer;
+    data->zstrm.avail_in = upstream_length;
+
+    while (data->zstrm.avail_in > 0) {
+      downstream_blkp = TSIOBufferStart(data->downstream_buffer);
+      downstream_buffer = TSIOBufferBlockWriteStart(downstream_blkp, &downstream_length);
+
+      data->zstrm.next_out = (unsigned char *) downstream_buffer;
+      data->zstrm.avail_out = downstream_length;
+
+      err = deflate(&data->zstrm, Z_NO_FLUSH);
+
+      if (err != Z_OK)
+        warning("deflate() call failed: %d", err);
+
+      if (downstream_length > data->zstrm.avail_out) {
+        TSIOBufferProduce(data->downstream_buffer, downstream_length - data->zstrm.avail_out);
+        data->downstream_length += (downstream_length - data->zstrm.avail_out);
+      }
+
+      if (data->zstrm.avail_out > 0) {
+        if (data->zstrm.avail_in != 0) {
+          error("gzip-transform: ERROR: avail_in is (%d): should be 0", data->zstrm.avail_in);
+        }
+      }
+    }
+
+    TSIOBufferReaderConsume(upstream_reader, upstream_length);
+    amount -= upstream_length;
+  }
+}
+
+static void
+gzip_transform_finish(GzipData * data)
+{
+  if (data->state == transform_state_output) {
+    TSIOBufferBlock downstream_blkp;
+    char *downstream_buffer;
+    int64_t downstream_length;
+    int err;
+
+    data->state = transform_state_finished;
+
+    for (;;) {
+      downstream_blkp = TSIOBufferStart(data->downstream_buffer);
+
+      downstream_buffer = TSIOBufferBlockWriteStart(downstream_blkp, &downstream_length);
+      data->zstrm.next_out = (unsigned char *) downstream_buffer;
+      data->zstrm.avail_out = downstream_length;
+
+      err = deflate(&data->zstrm, Z_FINISH);
+
+      if (downstream_length > (int64_t) data->zstrm.avail_out) {
+        TSIOBufferProduce(data->downstream_buffer, downstream_length - data->zstrm.avail_out);
+        data->downstream_length += (downstream_length - data->zstrm.avail_out);
+      }
+
+      if (err == Z_OK) {        /* some more data to encode */
+        continue;
+      }
+
+      if (err != Z_STREAM_END) {
+        warning("deflate should report Z_STREAM_END");
+      }
+      break;
+    }
+
+    if (data->downstream_length != (int64_t) (data->zstrm.total_out)) {
+      error("gzip-transform: ERROR: output lengths don't match (%d, %ld)", data->downstream_length,
+            data->zstrm.total_out);
+    }
+
+    gzip_log_ratio(data->zstrm.total_in, data->downstream_length);
+  }
+}
+
+
+static void
+gzip_transform_do(TSCont contp)
+{
+  TSVIO upstream_vio;
+  GzipData *data;
+  int64_t upstream_todo;
+  int64_t upstream_avail;
+  int64_t downstream_bytes_written;
+
+  data = (GzipData*)TSContDataGet(contp);
+  if (data->state == transform_state_initialized) {
+    gzip_transform_init(contp, data);
+  }
+
+  upstream_vio = TSVConnWriteVIOGet(contp);
+  downstream_bytes_written = data->downstream_length;
+
+  if (!TSVIOBufferGet(upstream_vio)) {
+    gzip_transform_finish(data);
+
+    TSVIONBytesSet(data->downstream_vio, data->downstream_length);
+
+    if (data->downstream_length > downstream_bytes_written) {
+      TSVIOReenable(data->downstream_vio);
+    }
+    return;
+  }
+
+  upstream_todo = TSVIONTodoGet(upstream_vio);
+
+  if (upstream_todo > 0) {
+    upstream_avail = TSIOBufferReaderAvail(TSVIOReaderGet(upstream_vio));
+
+    if (upstream_todo > upstream_avail) {
+      upstream_todo = upstream_avail;
+    }
+
+    if (upstream_todo > 0) {
+      gzip_transform_one(data, TSVIOReaderGet(upstream_vio), upstream_todo);
+      TSVIONDoneSet(upstream_vio, TSVIONDoneGet(upstream_vio) + upstream_todo);
+    }
+  }
+
+  if (TSVIONTodoGet(upstream_vio) > 0) {
+    if (upstream_todo > 0) {
+      if (data->downstream_length > downstream_bytes_written) {
+        TSVIOReenable(data->downstream_vio);
+      }
+      TSContCall(TSVIOContGet(upstream_vio), TS_EVENT_VCONN_WRITE_READY, upstream_vio);
+    }
+  } else {
+    gzip_transform_finish(data);
+    TSVIONBytesSet(data->downstream_vio, data->downstream_length);
+
+    if (data->downstream_length > downstream_bytes_written) {
+      TSVIOReenable(data->downstream_vio);
+    }
+
+    TSContCall(TSVIOContGet(upstream_vio), TS_EVENT_VCONN_WRITE_COMPLETE, upstream_vio);
+  }
+}
+
+
+static int
+gzip_transform(TSCont contp, TSEvent event, void * /* edata ATS_UNUSED */)
+{
+  if (TSVConnClosedGet(contp)) {
+    gzip_data_destroy((GzipData*)TSContDataGet(contp));
+    TSContDestroy(contp);
+    return 0;
+  } else {
+    switch (event) {
+    case TS_EVENT_ERROR:{
+        debug("gzip_transform: TS_EVENT_ERROR starts");
+        TSVIO upstream_vio = TSVConnWriteVIOGet(contp);
+        TSContCall(TSVIOContGet(upstream_vio), TS_EVENT_ERROR, upstream_vio);
+      }
+      break;
+    case TS_EVENT_VCONN_WRITE_COMPLETE:
+      TSVConnShutdown(TSTransformOutputVConnGet(contp), 0, 1);
+      break;
+    case TS_EVENT_VCONN_WRITE_READY:
+      gzip_transform_do(contp);
+      break;
+    case TS_EVENT_IMMEDIATE:
+      gzip_transform_do(contp);
+      break;
+    default:
+      warning("unknown event [%d]", event);
+      gzip_transform_do(contp);
+      break;
+    }
+  }
+
+  return 0;
+}
+
+
+static int
+gzip_transformable(TSHttpTxn txnp, int server, HostConfiguration * host_configuration, int *compress_type)
+{
+  /* Server response header */
+  TSMBuffer bufp;
+  TSMLoc hdr_loc;
+  TSMLoc field_loc;
+
+  /* Client request header */
+  TSMBuffer cbuf;
+  TSMLoc chdr;
+  TSMLoc cfield;
+
+  const char *value;
+  int nvalues;
+  int i, compression_acceptable, len;
+
+  TSHttpStatus resp_status;
+  if (server) {
+    TSHttpTxnServerRespGet(txnp, &bufp, &hdr_loc);
+  } else {
+    TSHttpTxnCachedRespGet(txnp, &bufp, &hdr_loc);
+  }
+  resp_status = TSHttpHdrStatusGet(bufp, hdr_loc);
+  TSHandleMLocRelease(bufp, TS_NULL_MLOC, hdr_loc);
+
+  //conservatively pick some statusses to compress
+  if (!(resp_status == 200 || resp_status == 404 || resp_status == 500)) {
+    info("http response status [%d] is not compressible", resp_status);
+    return 0;
+  }
+
+  TSHttpTxnClientReqGet(txnp, &cbuf, &chdr);
+
+  //the only compressible method is currently GET.
+  int method_length;
+  const char *method = TSHttpHdrMethodGet(cbuf, chdr, &method_length);
+  if (!(method_length == TS_HTTP_LEN_GET && memcmp(method, TS_HTTP_METHOD_GET, TS_HTTP_LEN_GET) == 0)) {
+    debug("method is not GET, not compressible");
+    TSHandleMLocRelease(cbuf, TS_NULL_MLOC, chdr);
+    return 0;
+  }
+
+  cfield = TSMimeHdrFieldFind(cbuf, chdr, TS_MIME_FIELD_ACCEPT_ENCODING, TS_MIME_LEN_ACCEPT_ENCODING);
+  if (cfield != TS_NULL_MLOC) {
+    compression_acceptable = 0;
+    nvalues = TSMimeHdrFieldValuesCount(cbuf, chdr, cfield);
+    for (i=0; i<nvalues; i++) {
+      value = TSMimeHdrFieldValueStringGet(cbuf, chdr, cfield, i, &len);
+      if (!value) {
+        continue;
+      }
+
+      if (strncasecmp(value, "deflate", sizeof("deflate") - 1) == 0) {
+        compression_acceptable = 1;
+        *compress_type = COMPRESSION_TYPE_DEFLATE;
+        break;
+      } else if (strncasecmp(value, "gzip", sizeof("gzip") - 1) == 0) {
+        compression_acceptable = 1;
+        *compress_type = COMPRESSION_TYPE_GZIP;
+        break;
+      }
+    }
+
+    TSHandleMLocRelease(cbuf, chdr, cfield);
+    TSHandleMLocRelease(cbuf, TS_NULL_MLOC, chdr);
+
+    if (!compression_acceptable) {
+      info("no acceptable encoding found in request header, not compressible");
+      return 0;
+    }
+  } else {
+    info("no acceptable encoding found in request header, not compressible");
+    TSHandleMLocRelease(cbuf, chdr, cfield);
+    TSHandleMLocRelease(cbuf, TS_NULL_MLOC, chdr);
+    return 0;
+  }
+
+  if (server) {
+    TSHttpTxnServerRespGet(txnp, &bufp, &hdr_loc);
+  } else {
+    TSHttpTxnCachedRespGet(txnp, &bufp, &hdr_loc);
+  }
+
+  /* If there already exists a content encoding then we don't want
+     to do anything. */
+  field_loc = TSMimeHdrFieldFind(bufp, hdr_loc, TS_MIME_FIELD_CONTENT_ENCODING, -1);
+  if (field_loc) {
+    info("response is already content encoded, not compressible");
+    TSHandleMLocRelease(bufp, hdr_loc, field_loc);
+    TSHandleMLocRelease(bufp, TS_NULL_MLOC, hdr_loc);
+    return 0;
+  }
+
+  /* We only want to do gzip compression on documents that have a
+     content type of "text/" or "application/x-javascript". */
+  field_loc = TSMimeHdrFieldFind(bufp, hdr_loc, TS_MIME_FIELD_CONTENT_TYPE, -1);
+  if (!field_loc) {
+    info("no content type header found, not compressible");
+    TSHandleMLocRelease(bufp, TS_NULL_MLOC, hdr_loc);
+    return 0;
+  }
+
+  value = TSMimeHdrFieldValueStringGet(bufp, hdr_loc, field_loc, 0, &len);
+
+  int rv = host_configuration->ContentTypeIsCompressible(value, len);
+  if (!rv) { 
+    info("content-type [%.*s] not compressible", len, value);
+  }
+  TSHandleMLocRelease(bufp, hdr_loc, field_loc);
+  TSHandleMLocRelease(bufp, TS_NULL_MLOC, hdr_loc);
+  return rv;
+}
+
+
+static void
+gzip_transform_add(TSHttpTxn txnp, int /* server ATS_UNUSED */, HostConfiguration * hc, int compress_type)
+{
+  int *tmp = (int *) TSHttpTxnArgGet(txnp, arg_idx_hooked);
+  if (tmp) {
+    //happens on cache_stale_hit
+    debug("transform hook already set, bail");
+    return;
+  } else {
+    TSHttpTxnArgSet(txnp, arg_idx_hooked, (void *) &GZIP_ONE);
+    info("adding compression transform");
+  }
+
+  TSHttpTxnUntransformedRespCache(txnp, 1);
+
+  if (!hc->cache()) {
+    debug("@@@@@ Gzip cache disabled");
+    TSHttpTxnTransformedRespCache(txnp, 0);
+  } else {
+    TSMBuffer bufp;
+    TSMLoc hdr_loc, field_loc;
+    int cache = 1;
+    if (TSHttpTxnServerRespGet(txnp, &bufp, &hdr_loc) == TS_SUCCESS || TSHttpTxnCachedRespGet(txnp, &bufp, &hdr_loc) == TS_SUCCESS) {
+      field_loc = TSMimeHdrFieldFind(bufp, hdr_loc, "@gzip_nocache", strlen("@gzip_nocache"));
+      if (field_loc) {
+        cache = 0;
+        debug("@@@@@ Gzip disallows cacheing of transformed response");
+        TSHandleMLocRelease(bufp, hdr_loc, field_loc);
+      } else  {
+        debug("@@@@ Gzip allows cacheing of transformed response");
+      }
+      TSHandleMLocRelease(bufp, TS_NULL_MLOC, hdr_loc);
+    }
+    
+    TSHttpTxnTransformedRespCache(txnp, cache);
+  }
+
+  TSVConn connp;
+  GzipData *data;
+
+  connp = TSTransformCreate(gzip_transform, txnp);
+  data = gzip_data_alloc(compress_type);
+  data->txn = txnp;
+
+  TSContDataSet(connp, data);
+  TSHttpTxnHookAdd(txnp, TS_HTTP_RESPONSE_TRANSFORM_HOOK, connp);
+}
+
+static int
+cache_transformable(TSHttpTxn txnp)
+{
+  int obj_status;
+
+  if (TSHttpTxnCacheLookupStatusGet(txnp, &obj_status) == TS_ERROR) {
+    warning("Couldn't get cache status of object");
+    return 0;
+  }
+  if (obj_status == TS_CACHE_LOOKUP_HIT_STALE) {
+    info("stale cache hit");
+    return 0;
+  }
+  if (obj_status == TS_CACHE_LOOKUP_HIT_FRESH) {
+    info("fresh cache hit");
+    return 1;
+  }
+
+  return 0;
+}
+
+HostConfiguration * 
+find_host_configuration(TSHttpTxn /* txnp ATS_UNUSED */, TSMBuffer bufp, TSMLoc locp)
+{
+  TSMLoc fieldp = TSMimeHdrFieldFind(bufp, locp, TS_MIME_FIELD_HOST, TS_MIME_LEN_HOST);
+
+  if (fieldp) {
+    int strl;
+    const char *strv = TSMimeHdrFieldValueStringGet(bufp, locp, fieldp, -1, &strl);
+    TSHandleMLocRelease(bufp, locp, fieldp);
+
+    HostConfiguration * host_configuration = config->Find(strv, strl);   
+    return host_configuration;
+  }
+
+  return config->GlobalConfiguration();
+}
+
+
+static int
+transform_plugin(TSCont /* contp ATS_UNUSED */, TSEvent event, void *edata)
+{
+  TSHttpTxn txnp = (TSHttpTxn) edata;
+  int compress_type = COMPRESSION_TYPE_DEFLATE;
+
+  switch (event) {
+    case TS_EVENT_HTTP_READ_REQUEST_HDR:
+      {
+        TSMBuffer req_buf;
+        TSMLoc req_loc;
+        if (TSHttpTxnClientReqGet(txnp, &req_buf, &req_loc) == TS_SUCCESS) {
+          int url_len;
+          char * url = TSHttpTxnEffectiveUrlStringGet(txnp, &url_len);
+          HostConfiguration * hc = find_host_configuration(txnp, req_buf, req_loc);
+          //we could clone the hosting configuration here, to make it deletable on reload?
+          TSHttpTxnArgSet(txnp, arg_idx_host_configuration, (void *) hc);
+
+          if (!hc->enabled() || !hc->IsUrlAllowed(url, url_len)) {
+            //FIXME: no double negatives
+            TSHttpTxnArgSet(txnp, arg_idx_url_disallowed, (void *) &GZIP_ONE);
+            info("url [%.*s] not allowed", url_len, url);
+          } else {
+            normalize_accept_encoding(txnp, req_buf, req_loc);	
+          }
+          TSfree(url);
+          TSHandleMLocRelease(req_buf, TS_NULL_MLOC, req_loc);
+        }
+        TSHttpTxnReenable(txnp, TS_EVENT_HTTP_CONTINUE);
+      }
+      break;
+
+    case TS_EVENT_HTTP_READ_RESPONSE_HDR:
+      {
+        //os: the accept encoding header needs to be restored..
+        //otherwise the next request won't get a cache hit on this
+        HostConfiguration * hc = (HostConfiguration*)TSHttpTxnArgGet(txnp, arg_idx_host_configuration);
+        if (hc != NULL) { 
+          if (hc->remove_accept_encoding()) {
+            TSMBuffer req_buf;
+            TSMLoc req_loc;
+            if (TSHttpTxnServerReqGet(txnp, &req_buf, &req_loc) == TS_SUCCESS) {
+              restore_accept_encoding(txnp, req_buf, req_loc, global_hidden_header_name);
+              TSHandleMLocRelease(req_buf, TS_NULL_MLOC, req_loc);
+            }
+          }
+
+          int allowed = !TSHttpTxnArgGet(txnp, arg_idx_url_disallowed);
+          if ( allowed && gzip_transformable(txnp, 1, hc, &compress_type)) {
+            gzip_transform_add(txnp, 1, hc, compress_type);
+          }
+        }
+        TSHttpTxnReenable(txnp, TS_EVENT_HTTP_CONTINUE);
+      }
+      break;
+
+    case TS_EVENT_HTTP_SEND_REQUEST_HDR:
+      {
+        HostConfiguration * hc = (HostConfiguration*)TSHttpTxnArgGet(txnp, arg_idx_host_configuration);
+        if (hc!=NULL) {
+          if (hc->remove_accept_encoding()) {
+            TSMBuffer req_buf;
+            TSMLoc req_loc;
+            if (TSHttpTxnServerReqGet(txnp, &req_buf, &req_loc) == TS_SUCCESS) {
+              hide_accept_encoding(txnp, req_buf, req_loc, global_hidden_header_name);
+              TSHandleMLocRelease(req_buf, TS_NULL_MLOC, req_loc);
+            }
+          }
+        }
+        TSHttpTxnReenable(txnp, TS_EVENT_HTTP_CONTINUE);
+      }
+      break;
+
+    case TS_EVENT_HTTP_CACHE_LOOKUP_COMPLETE:
+      {
+        int allowed = !TSHttpTxnArgGet(txnp, arg_idx_url_disallowed);
+        HostConfiguration * hc = (HostConfiguration*)TSHttpTxnArgGet(txnp, arg_idx_host_configuration);
+        if ( hc != NULL ) { 
+          if (allowed && cache_transformable(txnp) && gzip_transformable(txnp, 0, hc, &compress_type)) {
+            gzip_transform_add(txnp, 0, hc, compress_type);
+          }
+        }
+        TSHttpTxnReenable(txnp, TS_EVENT_HTTP_CONTINUE);
+      }
+      break;
+
+    default:
+      fatal("gzip transform unknown event");
+  }
+
+  return 0;
+}
+
+
+static void
+read_configuration(TSCont contp) {
+  const char * path = (const char *)TSContDataGet(contp);
+  Configuration * newconfig = Configuration::Parse(path);
+
+  Configuration * oldconfig =__sync_lock_test_and_set(&config, newconfig);
+  debug("config swapped,old config %p", oldconfig);
+
+  //FIXME: we have leaked.
+  //consider cloning or refcounting the configuration passed to the txn
+  //to make deleting the old configuration possible
+  //if (config != NULL )
+  //  delete config;
+}
+
+static int
+management_update(TSCont contp, TSEvent event, void * /* edata ATS_UNUSED */)
+{
+  TSReleaseAssert(event == TS_EVENT_MGMT_UPDATE);
+  info("management update event received");
+  read_configuration(contp);
+  return 0;
+}
+
+
+void
+TSPluginInit(int argc, const char *argv[])
+{
+  string config_path;
+
+  if (argc > 2)  {
+    fatal("the gzip plugin does not accept more than 1 plugin argument");
+  } else if (argc == 2) { 
+    config_path = std::string(argv[1]);
+  }
+
+  info("TSPluginInit %s", argv[0]);
+
+  if (!register_plugin()) {
+    fatal("The gzip plugin failed to register");
+  }
+
+  //if (argc == 2) {
+  //  dictionary = load_dictionary(argv[1]);
+  //}
+
+  if (TSHttpArgIndexReserve("gzip", "for remembering if the hook was set", &arg_idx_hooked) != TS_SUCCESS) {
+    fatal("failed to reserve an argument index");
+  }
+  if (TSHttpArgIndexReserve("gzip", "for storing if compression is applicable", &arg_idx_host_configuration) != TS_SUCCESS) {
+    fatal("failed to reserve an argument index");
+  }
+  if (TSHttpArgIndexReserve("gzip", "for storing if compression is disallowed for this txn", &arg_idx_url_disallowed) != TS_SUCCESS) {
+    fatal("failed to reserve an argument index");
+  }
+
+  global_hidden_header_name = init_hidden_header_name();
+
+  TSCont management_contp = TSContCreate(management_update, NULL);
+  //fixme: never freed. there is no shutdown event?
+  char * p = (char*)TSmalloc(config_path.size()+1);
+  strcpy(p,config_path.c_str());
+  TSContDataSet(management_contp,(void*)p);
+  TSMgmtUpdateRegister(management_contp, TAG);
+  read_configuration(management_contp);
+
+  TSCont transform_contp = TSContCreate(transform_plugin, NULL);
+  TSHttpHookAdd(TS_HTTP_READ_REQUEST_HDR_HOOK, transform_contp);
+  TSHttpHookAdd(TS_HTTP_READ_RESPONSE_HDR_HOOK, transform_contp);
+  TSHttpHookAdd(TS_HTTP_SEND_REQUEST_HDR_HOOK, transform_contp);
+  TSHttpHookAdd(TS_HTTP_CACHE_LOOKUP_COMPLETE_HOOK, transform_contp);
+
+  info("loaded");
+}

http://git-wip-us.apache.org/repos/asf/trafficserver/blob/e8b899b0/plugins/experimental/ats_pagespeed/gzip/gzip.config
----------------------------------------------------------------------
diff --git a/plugins/experimental/ats_pagespeed/gzip/gzip.config b/plugins/experimental/ats_pagespeed/gzip/gzip.config
new file mode 100644
index 0000000..81e9fa4
--- /dev/null
+++ b/plugins/experimental/ats_pagespeed/gzip/gzip.config
@@ -0,0 +1,6 @@
+# Set some global options first
+cache true
+enabled true
+remove-accept-encoding false
+compressible-content-type text/*
+compressible-content-type *javascript*

http://git-wip-us.apache.org/repos/asf/trafficserver/blob/e8b899b0/plugins/experimental/ats_pagespeed/gzip/misc.cc
----------------------------------------------------------------------
diff --git a/plugins/experimental/ats_pagespeed/gzip/misc.cc b/plugins/experimental/ats_pagespeed/gzip/misc.cc
new file mode 100644
index 0000000..0ea6911
--- /dev/null
+++ b/plugins/experimental/ats_pagespeed/gzip/misc.cc
@@ -0,0 +1,197 @@
+/** @file
+
+  Transforms content using gzip or deflate
+
+  @section license License
+
+  Licensed to the Apache Software Foundation (ASF) under one
+  or more contributor license agreements.  See the NOTICE file
+  distributed with this work for additional information
+  regarding copyright ownership.  The ASF licenses this file
+  to you under the Apache License, Version 2.0 (the
+  "License"); you may not use this file except in compliance
+  with the License.  You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+ */
+
+#include "ts/ts.h"
+//#include "ink_defs.h"
+#include <stdint.h>
+#include <inttypes.h>
+#include "misc.h"
+#include <string.h>
+#include "debug_macros.h"
+
+voidpf
+gzip_alloc(voidpf /* opaque ATS_UNUSED */, uInt items, uInt size)
+{
+  return (voidpf) TSmalloc(items * size);
+}
+
+void
+gzip_free(voidpf /* opaque ATS_UNUSED */, voidpf address)
+{
+  TSfree(address);
+}
+
+void
+normalize_accept_encoding(TSHttpTxn /* txnp ATS_UNUSED */, TSMBuffer reqp, TSMLoc hdr_loc)
+{
+  TSMLoc field = TSMimeHdrFieldFind(reqp, hdr_loc, TS_MIME_FIELD_ACCEPT_ENCODING, TS_MIME_LEN_ACCEPT_ENCODING);
+  int deflate = 0;
+  int gzip = 0;
+
+  //remove the accept encoding field(s), 
+  //while finding out if gzip or deflate is supported.    
+  while (field) {
+    TSMLoc tmp;
+
+    if (!deflate && !gzip) {
+      int value_count = TSMimeHdrFieldValuesCount(reqp, hdr_loc, field);
+
+      while (value_count > 0) {
+        int val_len = 0;
+        const char *val;
+
+        --value_count;
+        val = TSMimeHdrFieldValueStringGet(reqp, hdr_loc, field, value_count, &val_len);
+
+        if (val_len == (int) strlen("gzip"))
+          gzip = !strncmp(val, "gzip", val_len);
+        else if (val_len == (int) strlen("deflate"))
+          deflate = !strncmp(val, "deflate", val_len);
+      }
+    }
+
+    tmp = TSMimeHdrFieldNextDup(reqp, hdr_loc, field);
+    TSMimeHdrFieldDestroy(reqp, hdr_loc, field);        //catch retval?
+    TSHandleMLocRelease(reqp, hdr_loc, field);
+    field = tmp;
+  }
+
+  //append a new accept-encoding field in the header
+  if (deflate || gzip) {
+    TSMimeHdrFieldCreate(reqp, hdr_loc, &field);
+    TSMimeHdrFieldNameSet(reqp, hdr_loc, field, TS_MIME_FIELD_ACCEPT_ENCODING, TS_MIME_LEN_ACCEPT_ENCODING);
+
+    if (gzip) {
+      TSMimeHdrFieldValueStringInsert(reqp, hdr_loc, field, -1, "gzip", strlen("gzip"));
+      info("normalized accept encoding to gzip");
+    } else if (deflate) {
+      TSMimeHdrFieldValueStringInsert(reqp, hdr_loc, field, -1, "deflate", strlen("deflate"));
+      info("normalized accept encoding to deflate");
+    }
+
+    TSMimeHdrFieldAppend(reqp, hdr_loc, field);
+    TSHandleMLocRelease(reqp, hdr_loc, field);
+  }
+}
+
+void
+hide_accept_encoding(TSHttpTxn /* txnp ATS_UNUSED */, TSMBuffer reqp, TSMLoc hdr_loc, const char * hidden_header_name)
+{
+  TSMLoc field = TSMimeHdrFieldFind(reqp, hdr_loc, TS_MIME_FIELD_ACCEPT_ENCODING, TS_MIME_LEN_ACCEPT_ENCODING);
+  while (field) {
+    TSMLoc tmp;
+    tmp = TSMimeHdrFieldNextDup(reqp, hdr_loc, field);
+    TSMimeHdrFieldNameSet(reqp, hdr_loc, field, hidden_header_name, -1);
+    TSHandleMLocRelease(reqp, hdr_loc, field);
+    field = tmp;
+  }
+}
+
+void
+restore_accept_encoding(TSHttpTxn /* txnp ATS_UNUSED */, TSMBuffer reqp, TSMLoc hdr_loc, const char * hidden_header_name)
+{
+  TSMLoc field = TSMimeHdrFieldFind(reqp, hdr_loc, hidden_header_name, -1);
+
+  while (field) {
+    TSMLoc tmp;
+    tmp = TSMimeHdrFieldNextDup(reqp, hdr_loc, field);
+    TSMimeHdrFieldNameSet(reqp, hdr_loc, field, TS_MIME_FIELD_ACCEPT_ENCODING, TS_MIME_LEN_ACCEPT_ENCODING);
+    TSHandleMLocRelease(reqp, hdr_loc, field);
+    field = tmp;
+  }
+}
+
+const char *
+init_hidden_header_name()
+{
+  char * hidden_header_name;
+  const char *var_name = "proxy.config.proxy_name";
+  TSMgmtString result;
+
+  if (TSMgmtStringGet(var_name, &result) != TS_SUCCESS) {
+    fatal("failed to get server name");
+  } else {
+    int hidden_header_name_len = strlen("x-accept-encoding-") + strlen(result);
+    hidden_header_name = (char *) TSmalloc(hidden_header_name_len + 1);
+    hidden_header_name[hidden_header_name_len] = 0;
+    sprintf(hidden_header_name, "x-accept-encoding-%s", result);
+  }
+  return hidden_header_name;
+}
+
+int
+register_plugin()
+{
+  TSPluginRegistrationInfo info;
+
+  info.plugin_name = (char*)"gzip";
+  info.vendor_name = (char*)"Apache";
+  info.support_email = (char*)"dev@trafficserver.apache.org";
+
+  if (TSPluginRegister(TS_SDK_VERSION_3_0, &info) != TS_SUCCESS) {
+    return 0;
+  }
+  return 1;
+}
+
+const char *
+load_dictionary(const char *preload_file)
+{
+  char *dict = (char *) malloc(800000);
+  uLong dictId = adler32(0L, Z_NULL, 0);
+  uLong *adler = &dictId;
+
+  FILE *fp;
+  int i = 0;
+
+  fp = fopen(preload_file, "r");
+  if (!fp) {
+    fatal("gzip-transform: ERROR: Unable to open dict file %s", preload_file);
+  }
+
+  /* dict = (char *) calloc(8000, sizeof(char)); */
+
+  i = 0;
+  while (!feof(fp)) {
+    if (fscanf(fp, "%s\n", dict + i) == 1) {
+      i = strlen(dict);
+      strcat(dict + i, " ");
+      ++i;
+    }
+  }
+  dict[i - 1] = '\0';
+
+  /* TODO get the adler compute right */
+  *adler = adler32(*adler, (const Byte *) dict, sizeof(dict));
+  return dict;
+}
+
+void
+gzip_log_ratio(int64_t in, int64_t out)
+{
+  //  if (in) {
+  //  info("Compressed size %PRId64 (bytes), Original size %" PRId64", ratio: %f", out, in, ((float) (in - out) / in));
+  //} else {
+  //  debug("Compressed size %PRId64 (bytes), Original size %" PRId64", ratio: %f", out, in, 0.0F);
+  // }
+}

http://git-wip-us.apache.org/repos/asf/trafficserver/blob/e8b899b0/plugins/experimental/ats_pagespeed/gzip/misc.h
----------------------------------------------------------------------
diff --git a/plugins/experimental/ats_pagespeed/gzip/misc.h b/plugins/experimental/ats_pagespeed/gzip/misc.h
new file mode 100644
index 0000000..c44fb6b
--- /dev/null
+++ b/plugins/experimental/ats_pagespeed/gzip/misc.h
@@ -0,0 +1,84 @@
+/** @file
+
+  Transforms content using gzip or deflate
+
+  @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 _GZIP_MISC_H_
+#define _GZIP_MISC_H_
+
+#define __STDC_LIMIT_MACROS
+#define __STDC_CONSTANT_MACROS
+#include <stdint.h>
+#include <zlib.h>
+#include <ts/ts.h>
+#include <stdlib.h>             //exit()
+#include <stdio.h>
+
+//zlib stuff, see [deflateInit2] at http://www.zlib.net/manual.html
+static const int ZLIB_MEMLEVEL = 9;     //min=1 (optimize for memory),max=9 (optimized for speed)
+static const int WINDOW_BITS_DEFLATE = -15;
+static const int WINDOW_BITS_GZIP = 31;
+
+//misc
+static const int COMPRESSION_TYPE_DEFLATE = 1;
+static const int COMPRESSION_TYPE_GZIP = 2;
+//this one is just for txnargset/get to point to
+static const int GZIP_ONE = 1;
+static const int DICT_PATH_MAX = 512;
+static const int DICT_ENTRY_MAX = 2048;
+
+//this one is used to rename the accept encoding header
+//it will be restored later on
+//to make it work, the name must be different then downstream proxies though
+//otherwise the downstream will restore the accept encoding header
+
+enum transform_state
+{
+  transform_state_initialized,
+  transform_state_output,
+  transform_state_finished
+};
+
+typedef struct
+{
+  TSHttpTxn txn;
+  TSVIO downstream_vio;
+  TSIOBuffer downstream_buffer;
+  TSIOBufferReader downstream_reader;
+  int downstream_length;
+  z_stream zstrm;
+  enum transform_state state;
+  int compression_type;
+} GzipData;
+
+
+voidpf gzip_alloc(voidpf opaque, uInt items, uInt size);
+void gzip_free(voidpf opaque, voidpf address);
+void normalize_accept_encoding(TSHttpTxn txnp, TSMBuffer reqp, TSMLoc hdr_loc);
+void hide_accept_encoding(TSHttpTxn txnp, TSMBuffer reqp, TSMLoc hdr_loc, const char * hidden_header_name);
+void restore_accept_encoding(TSHttpTxn txnp, TSMBuffer reqp, TSMLoc hdr_loc, const char * hidden_header_name);
+const char * init_hidden_header_name();
+int check_ts_version();
+int register_plugin();
+const char *load_dictionary(const char *preload_file);
+void gzip_log_ratio(int64_t in, int64_t out);
+
+#endif

http://git-wip-us.apache.org/repos/asf/trafficserver/blob/e8b899b0/plugins/experimental/ats_pagespeed/scripts/prepare_psol.sh
----------------------------------------------------------------------
diff --git a/plugins/experimental/ats_pagespeed/scripts/prepare_psol.sh b/plugins/experimental/ats_pagespeed/scripts/prepare_psol.sh
new file mode 100755
index 0000000..5193e1d
--- /dev/null
+++ b/plugins/experimental/ats_pagespeed/scripts/prepare_psol.sh
@@ -0,0 +1,93 @@
+#!/bin/bash
+#
+# 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.
+#
+# Author: jefftk@google.com (Jeff Kaufman)
+# Author: oschaaf@we-amp.com (Otto van der Schaaf)
+#
+# Usage:
+#   scripts/prepare_psol.sh /path/to/mod_pagespeed/src
+#
+# Creates a directory psol/ and copies headers and a few source files from a
+# depot_tools (glient) checkout into psol/include.  Along with creating
+# binaries, this is a step in preparing psol.tar.gz for distribution.
+#
+
+set -u  # check for undefined variables
+set -e  # exit on failed commands
+
+if [ "$(basename "$PWD")" != "ats_pagespeed" ] ; then
+  echo "$(basename $0) must be invoked from the ats_pagespeed directory"
+  exit 1
+fi
+
+if [ $# -ne 1 ] ; then
+  echo "Usage: $(basename $0) /path/to/mod_pagespeed/src"
+  exit 1
+fi
+
+MOD_PAGESPEED_SRC="$1"
+
+if [ "$(basename "$(dirname "$MOD_PAGESPEED_SRC")")/$( \
+        basename "$MOD_PAGESPEED_SRC")" != "mod_pagespeed/src" ] ; then
+  echo "Usage: $(basename $0) /path/to/mod_pagespeed/src"
+  exit 1
+fi
+
+if [ -e psol ] ; then
+  echo "A psol/ directory already exists.  Move it somewhere else and rerun."
+  exit 1
+fi
+mkdir psol/
+# Copy over the .h files, plus a few selected .cc and .c files.
+rsync -arvz "$MOD_PAGESPEED_SRC/" "psol/include/" --prune-empty-dirs \
+  --exclude=".svn" \
+  --exclude=".git" \
+  --include='*.h' \
+  --include='*/' \
+  --include="apr_thread_compatible_pool.cc" \
+  --include="serf_url_async_fetcher.cc" \
+  --include="apr_mem_cache.cc" \
+  --include="key_value_codec.cc" \
+  --include="apr_memcache2.c" \
+  --include="loopback_route_fetcher.cc" \
+  --include="add_headers_fetcher.cc" \
+  --include="console_css_out.cc" \
+  --include="console_out.cc" \
+  --include="dense_hash_map" \
+  --include="dense_hash_set" \
+  --include="sparse_hash_map" \
+  --include="sparse_hash_set" \
+  --include="sparsetable" \
+  --include="mod_pagespeed_console_out.cc" \
+  --include="mod_pagespeed_console_css_out.cc" \
+  --include="mod_pagespeed_console_html_out.cc" \
+  --exclude='*'
+mkdir -p psol/lib/Debug/linux/ia32
+mkdir -p psol/lib/Debug/linux/x64
+mkdir -p psol/lib/Release/linux/ia32
+mkdir -p psol/lib/Release/linux/x64
+
+# Log that we did this.
+SVN_REVISION="$(svn info $MOD_PAGESPEED_SRC | grep Revision | awk '{print $2}')"
+SVN_TAG="$(svn info $MOD_PAGESPEED_SRC | grep URL |  awk -F/ '{print $(NF-1)}')"
+
+DATE="$(date +%F)"
+echo "${DATE}: Copied from mod_pagespeed ${SVN_TAG}@r${SVN_REVISION} ($USER)" \
+  >> psol/include_history.txt
+
+echo
+echo "Output is in psol/include.  Now put binaries in psol/lib following"
+echo "https://github.com/pagespeed/ngx_pagespeed/wiki/Building-Release-Binaries"
+echo "and then you can distribute PSOL."
+

http://git-wip-us.apache.org/repos/asf/trafficserver/blob/e8b899b0/plugins/experimental/ats_speed/.gitignore
----------------------------------------------------------------------
diff --git a/plugins/experimental/ats_speed/.gitignore b/plugins/experimental/ats_speed/.gitignore
deleted file mode 100644
index a12b1d2..0000000
--- a/plugins/experimental/ats_speed/.gitignore
+++ /dev/null
@@ -1,15 +0,0 @@
-# Compiled Object files
-*.slo
-*.lo
-*.o
-
-# Compiled Dynamic libraries
-*.so
-*.dylib
-
-# Compiled Static libraries
-*.lai
-*.la
-*.a
-*.gz
-*~
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/trafficserver/blob/e8b899b0/plugins/experimental/ats_speed/Makefile
----------------------------------------------------------------------
diff --git a/plugins/experimental/ats_speed/Makefile b/plugins/experimental/ats_speed/Makefile
deleted file mode 100644
index 7498b2b..0000000
--- a/plugins/experimental/ats_speed/Makefile
+++ /dev/null
@@ -1,83 +0,0 @@
-#  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.
-
-SHELL := /bin/bash
-TSXS?=tsxs
-# Specify BUILDTYPE=Debug for a debug build
-BUILDTYPE?=Release
-MOD_PAGESPEED_DIR=$(shell pwd)/psol/include/
-PAGESPEED_OUT=$(shell pwd)/psol/lib/$(BUILDTYPE)/linux/x64/
-
-
-os_name=unknown_os
-arch_name=ia32
-uname_os=$(shell uname)
-uname_arch=$(shell uname -m)
-
-ifeq ($(uname_os),Linux)
-  os_name=linux
-endif
-
-ifeq ($(uname_arch), x86_64)
-  arch_name=x64
-endif
-ifeq ($(uname_arch), amd64)
-  arch_name=x64
-endif
-
-INC =-I$(MOD_PAGESPEED_DIR)\
- -I$(MOD_PAGESPEED_DIR)third_party/chromium/src/\
- -I$(MOD_PAGESPEED_DIR)third_party/google-sparsehash/src\
- -I$(MOD_PAGESPEED_DIR)third_party/google-sparsehash/gen/arch/$(os_name)/$(arch_name)/include\
- -I$(MOD_PAGESPEED_DIR)third_party/protobuf/src\
- -I$(MOD_PAGESPEED_DIR)third_party/re2/src\
- -I$(MOD_PAGESPEED_DIR)third_party/out/$(BUILDTYPE)/obj/gen\
- -I$(MOD_PAGESPEED_DIR)third_party/apr/src/include/\
- -I$(MOD_PAGESPEED_DIR)third_party/aprutil/src/include/\
- -I$(MOD_PAGESPEED_DIR)third_party/apr/gen/arch/$(os_name)/$(arch_name)/include/\
- -I$(MOD_PAGESPEED_DIR)third_party/aprutil/gen/arch/$(os_name)/$(arch_name)/include/\
- -I$(MOD_PAGESPEED_DIR)out/$(BUILDTYPE)/obj/gen\
- -I$(MOD_PAGESPEED_DIR)out/$(BUILDTYPE)/obj/gen/protoc_out/instaweb
-
-PSOL_LIBS = $(PAGESPEED_OUT)pagespeed_automatic.a 
-#PSOL_LIBS = $(PAGESPEED_OUT)pagespeed_automatic.a $(PAGESPEED_OUT)libserf.a $(PAGESPEED_OUT)libaprutil.a $(PAGESPEED_OUT)libapr.a
-
-%.so: psol %.cc
-# https://github.com/pagespeed/ngx_pagespeed/issues/433: it would be nice to have -Wall -Werror, only suppressing when needed.
-	g++ $(INC) -shared -o ats_speed.so -g -pipe -O3 -fpic *.cc -lstdc++ -lstdc++  -lpthread $(PSOL_LIBS) -lrt
-
-all: psol gzip/gzip.so ats_speed.so
-
-1.8.31.4.tar.gz:
-	wget --no-check-certificate https://dl.google.com/dl/page-speed/psol/1.8.31.4.tar.gz
-
-psol/: 1.8.31.4.tar.gz
-	tar -xzvf 1.8.31.4.tar.gz
-
-gzip/gzip.so:
-	cd gzip && make
-
-install: all
-	$(TSXS) -i -o ats_speed.so
-	cd gzip && make install
-
-cleanpsol:
-	rm -rf psol/
-	rm *.gz
-
-clean:
-	rm -f *.lo *.so *.o
-	rm -f gzip/*.lo gzip/*.so gzip/*.o

http://git-wip-us.apache.org/repos/asf/trafficserver/blob/e8b899b0/plugins/experimental/ats_speed/Makefile.psol_source
----------------------------------------------------------------------
diff --git a/plugins/experimental/ats_speed/Makefile.psol_source b/plugins/experimental/ats_speed/Makefile.psol_source
deleted file mode 100755
index 80d3206..0000000
--- a/plugins/experimental/ats_speed/Makefile.psol_source
+++ /dev/null
@@ -1,49 +0,0 @@
-#  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.
-
-TSXS?=tsxs
-BUILDTYPE=Release
-MOD_PAGESPEED_DIR=$(HOME)/code/google/mod_pagespeed/src/
-PAGESPEED_OUT=$(MOD_PAGESPEED_DIR)out/$(BUILDTYPE)/
-
-INC =-I$(MOD_PAGESPEED_DIR)\
- -I$(MOD_PAGESPEED_DIR)third_party/chromium/src/\
- -I$(MOD_PAGESPEED_DIR)third_party/google-sparsehash/src\
- -I$(MOD_PAGESPEED_DIR)third_party/google-sparsehash/gen/arch/linux/x64/include\
- -I$(MOD_PAGESPEED_DIR)third_party/protobuf/src\
- -I$(MOD_PAGESPEED_DIR)third_party/re2/src\
- -I$(MOD_PAGESPEED_DIR)third_party/out/$(BUILDTYPE)/obj/gen\
- -I$(MOD_PAGESPEED_DIR)third_party/apr/src/include/\
- -I$(MOD_PAGESPEED_DIR)third_party/aprutil/src/include/\
- -I$(MOD_PAGESPEED_DIR)third_party/apr/gen/arch/linux/x64/include/\
- -I$(MOD_PAGESPEED_DIR)third_party/aprutil/gen/arch/linux/x64/include/\
- -I$(PAGESPEED_OUT)obj/gen/\
- -I$(PAGESPEED_OUT)obj/gen/protoc_out/instaweb/
-
-PSOL_LIBS = $(MOD_PAGESPEED_DIR)net/instaweb/automatic/pagespeed_automatic.a
-
-%.so: %.cc
-	g++ $(INC) -shared -o ats_speed.so -g -pipe -Wall -Werror -O3 -fpic *.cc -lstdc++  -lpthread -lrt $(PSOL_LIBS)
-
-all: gzip/gzip.so ats_speed.so
-
-install: all
-	$(TSXS) -i -o ats_speed.so 
-	cp gzip/gzip.so ./
-	$(TSXS) -i -o zip.so 
-
-clean:
-	rm -f *.lo *.so *.o

http://git-wip-us.apache.org/repos/asf/trafficserver/blob/e8b899b0/plugins/experimental/ats_speed/README.md
----------------------------------------------------------------------
diff --git a/plugins/experimental/ats_speed/README.md b/plugins/experimental/ats_speed/README.md
deleted file mode 100644
index ae5db92..0000000
--- a/plugins/experimental/ats_speed/README.md
+++ /dev/null
@@ -1,52 +0,0 @@
-![ScreenShot](http://www.atsspeed.com/images/xATSSPEED_logo_plusshout_728x91.png.pagespeed.ic.8mRpu2PXS0.png
-)
-
-Apache Traffic Server web content optimization plugin powered by Google PageSpeed
-
-http://www.atsspeed.com/
-
-To build, a simple 'make' should work. Use 'sudo make install' to install.
-Optionally, patching ATS with ethread.patch helps with eliminating latency that 
-sometimes gets induced when synchronising ATS's and PSOL's thread pools.
-
-After that, update ATS's plugin.config with:
-```
-ats_speed.so                                                                                 
-gzip.so /usr/local/etc/trafficserver/gzip.config  
-````
-gzip.so also is build with ats_speed, as it currently is a slightly
-modified version of the official one from the ATS repository.
-
-There are some hard-coded things in the plugin, these directories should exist:
-- /tmp/ps_log/ to exist
-- /tmp/ats_ps/ to exist
-
-Configuration files go into `/usr/local/etc/trafficserver/psol.`
-That folder is monitored, and changes to files in there are picked
-up immediately. A sample configuration:
-
-```
-# [host]
-[192.168.185.185]
-# Force traffic server to cache all origin responses
-override_expiry
-pagespeed FlushHtml on
-pagespeed RewriteLevel CoreFilters
-pagespeed EnableFilters rewrite_domains,trim_urls
-pagespeed MapRewriteDomain http://192.168.185.185 http://www.foo.com
-pagespeed MapOriginDomain http://192.168.185.185 http://www.foo.com
-pagespeed EnableFilters prioritize_critical_css,move_css_to_head,move_css_above_scripts
-pagespeed EnableFilters fallback_rewrite_css_urls,insert_img_dimensions,lazyload_images,local_storage_cache
-pagespeed EnableFilters prioritize_critical_css,rewrite_css
-pagespeed EnableFilters combine_javascript,combine_css
-```
-
-It also expects this in records.config from ATS to function:
-`CONFIG proxy.config.url_remap.pristine_host_hdr INT 0`
-
-You can view debug output of the plugin using `traffic_server -T ".*speed.*"`
-
-The current state compiles against PSOL 1.7.30.4-beta.
-Please note the this plugin will generate asserts when build against
-the debug version of mps (option->Merge from a different thread).
-

http://git-wip-us.apache.org/repos/asf/trafficserver/blob/e8b899b0/plugins/experimental/ats_speed/ats_base_fetch.cc
----------------------------------------------------------------------
diff --git a/plugins/experimental/ats_speed/ats_base_fetch.cc b/plugins/experimental/ats_speed/ats_base_fetch.cc
deleted file mode 100644
index 769e79b..0000000
--- a/plugins/experimental/ats_speed/ats_base_fetch.cc
+++ /dev/null
@@ -1,142 +0,0 @@
-/** @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.
-*/
-
-#include "ats_base_fetch.h"
-
-#include <ts/ts.h>
-
-#include "ats_server_context.h"
-
-#include "net/instaweb/util/public/string_util.h"
-#include "net/instaweb/util/public/string_writer.h"
-#include "net/instaweb/util/public/google_message_handler.h"
-
-
-using namespace net_instaweb;
-
-// TODO(oschaaf): rename is_resource_fetch -> write_raw_response_headers
-AtsBaseFetch::AtsBaseFetch(AtsServerContext* server_context,
-                           const net_instaweb::RequestContextPtr& request_ctx,
-                           TSVIO downstream_vio, TSIOBuffer downstream_buffer, bool is_resource_fetch) :
-  AsyncFetch(request_ctx),
-  server_context_(server_context),
-  done_called_(false),
-  last_buf_sent_(false),
-  references_(2),
-  downstream_vio_(downstream_vio),
-  downstream_buffer_(downstream_buffer),
-  is_resource_fetch_(is_resource_fetch),
-  downstream_length_(0),
-  txn_mutex_(TSVIOMutexGet(downstream_vio)) {
-  buffer_.reserve(1024 * 32);
-}
-
-AtsBaseFetch::~AtsBaseFetch() {
-  CHECK(references_ == 0);
-}
-
-// Should be called from the event loop,
-// and thus with the txn mutex held by ATS
-void AtsBaseFetch::Release() {
-  DecrefAndDeleteIfUnreferenced();
-}
-
-void AtsBaseFetch::Lock(){
-  TSMutexLock(txn_mutex_);
-}
-
-void AtsBaseFetch::Unlock() {
-  TSMutexUnlock(txn_mutex_);
-}
-
-bool AtsBaseFetch::HandleWrite(const StringPiece& sp, net_instaweb::MessageHandler* handler) {
-  ForwardData(sp, false, false);
-  return true;
-}
-
-bool AtsBaseFetch::HandleFlush( net_instaweb::MessageHandler* handler ) {
-  ForwardData("", true, false);
-  return true;
-}
-
-void AtsBaseFetch::HandleHeadersComplete() {
-  // oschaaf: ATS will currently send its response headers
-  // earlier than this will fire. So this has become a no-op.
-  // This implies that we can't support convert_meta_tags
-  TSDebug("ats-speed", "HeadersComplete()!");
-  // For resource fetches, we need to output the headers in raw HTTP format.
-  if (is_resource_fetch_) {
-    GoogleMessageHandler mh;
-    GoogleString s;
-    StringWriter string_writer(&s);
-    response_headers()->Add("Connection", "Close");
-    response_headers()->WriteAsHttp(&string_writer, &mh);
-    ForwardData(StringPiece(s.data(),s.size()), true, false);
-  }
-}
-
-void AtsBaseFetch::ForwardData(const StringPiece& sp, bool reenable, bool last) {
-  TSIOBufferBlock downstream_blkp;
-  char *downstream_buffer;
-  int64_t downstream_length;
-  int64_t to_write = sp.size();
-
-  Lock();
-  if (references_ == 2) {
-    while (to_write > 0) {
-      downstream_blkp = TSIOBufferStart(downstream_buffer_);
-      downstream_buffer = TSIOBufferBlockWriteStart(downstream_blkp, &downstream_length);
-      int64_t bytes_written = to_write > downstream_length ? downstream_length : to_write;
-      memcpy(downstream_buffer, sp.data() + (sp.size() - to_write), bytes_written);
-      to_write -= bytes_written;
-      downstream_length_ += bytes_written;
-      TSIOBufferProduce(downstream_buffer_, bytes_written);
-    }
-    CHECK(to_write == 0) << "to_write failure";
-    if (last) {
-      TSVIONBytesSet(downstream_vio_, downstream_length_);
-    }
-    if (reenable) { 
-      TSVIOReenable(downstream_vio_);
-    }
-  }
-  Unlock();
-}
-
-void AtsBaseFetch::HandleDone(bool success) {
-  CHECK(!done_called_);
-  CHECK(downstream_vio_);
-  TSDebug("ats-speed", "Done()!");
-
-  Lock();
-  done_called_ = true;
-  ForwardData("", true, true);
-  DecrefAndDeleteIfUnreferenced();
-  Unlock();
-}
-
-void AtsBaseFetch::DecrefAndDeleteIfUnreferenced() {
-  if (__sync_add_and_fetch(&references_, -1) == 0) {
-    delete this;
-  }
-}

http://git-wip-us.apache.org/repos/asf/trafficserver/blob/e8b899b0/plugins/experimental/ats_speed/ats_base_fetch.h
----------------------------------------------------------------------
diff --git a/plugins/experimental/ats_speed/ats_base_fetch.h b/plugins/experimental/ats_speed/ats_base_fetch.h
deleted file mode 100644
index 8e4d93d..0000000
--- a/plugins/experimental/ats_speed/ats_base_fetch.h
+++ /dev/null
@@ -1,88 +0,0 @@
-/** @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.
-*/
-
-#ifndef ATS_BASE_FETCH_H_
-#define ATS_BASE_FETCH_H_
-
-#include <string>
-
-#include <ts/ts.h>
-
-#include "ats_speed.h"
-
-#include "net/instaweb/http/public/async_fetch.h"
-#include "net/instaweb/http/public/headers.h"
-#include "net/instaweb/util/public/string.h"
-
-
-namespace net_instaweb {
-
-class AtsServerContext;
-class AbstractMutex;
-
-class AtsBaseFetch : public net_instaweb::AsyncFetch {
-
-public:
-  // TODO(oschaaf): change this to take the downstream buffer and vio
-  // instead of AtsData*. Also, make the bytes send a property
-  // of the fetch itself instead of tracking it on data.
-  // Doing so, would allow us to share this with the server intercept
-  // code for resources.
-  AtsBaseFetch(AtsServerContext* server_context,
-               const net_instaweb::RequestContextPtr& request_ctx,
-               TSVIO downstream_vio,
-               TSIOBuffer downstream_buffer,
-               bool is_resource_fetch);
-  
-  virtual ~AtsBaseFetch();
-  void Release();
-private:
-  virtual bool HandleWrite(const StringPiece& sp, net_instaweb::MessageHandler* handler);
-  virtual bool HandleFlush( net_instaweb::MessageHandler* handler);
-  virtual void HandleHeadersComplete();
-  virtual void HandleDone(bool success);
-  void Lock();
-  void Unlock();
-  void DecrefAndDeleteIfUnreferenced();
-  void ForwardData(const StringPiece& sp, bool reenable, bool last);
-  GoogleString buffer_;
-  AtsServerContext* server_context_;
-  bool done_called_;
-  bool last_buf_sent_;
-
-  // How many active references there are to this fetch. Starts at two,
-  // decremented once when Done() is called and once when Release() is called.
-  int references_;
-  TSVIO downstream_vio_;
-  TSIOBuffer downstream_buffer_;
-  bool is_resource_fetch_;
-  int64_t downstream_length_;
-
-  // We don't own this mutex
-  TSMutex txn_mutex_;
-};
-
-} /* ats_pagespeed */
-
-
-#endif /* ATS_BASE_FETCH_H_ */