Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 4 additions & 3 deletions NOTICE
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ This product includes software developed at
- Comcast
- LinkedIn
- Mike Pall
- GoDaddy

~~~

Expand Down Expand Up @@ -44,8 +45,8 @@ Copyright (C) 2012 Oregon Health & Science University

~~~

healthcheck Plugin developed by GoDaddy.
Copyright (C) 2012 GoDaddy.
cache-key-genid Plugin developed by GoDaddy
Copyright (C) 2013 GoDaddy Operating Company, LLC

~~~

Expand Down Expand Up @@ -78,7 +79,7 @@ Copyright (C) 2014 Yahoo! Inc. All rights reserved.
~~~

healthchecks: Plugin for ATS healthchecks.
Copyright (C) 2012 Go Daddy Operating Company, LLC
Copyright (C) 2012 GoDaddy Operating Company, LLC

~~~

Expand Down
14 changes: 14 additions & 0 deletions configure.ac
Original file line number Diff line number Diff line change
Expand Up @@ -1891,13 +1891,27 @@ AC_CHECK_LIB([mysqlclient],[mysql_info],[AC_SUBST([LIB_MYSQLCLIENT],["-lmysqlcli
AC_SUBST(has_mysql)
AM_CONDITIONAL([HAS_MYSQL], [ test "x${has_mysql}" = "x1" ])

AC_CHECK_HEADERS([kclangc.h], [
AC_CHECK_LIB([kyotocabinet], [kcdbopen], [
AC_SUBST([LIB_KYOTOCABINET], ["-lkyotocabinet"])
has_kyotocabinet=1
], [
has_kyotocabinet=0
])
],
[has_kyotocabinet=0]
)
AC_SUBST(has_kyotocabinet)
AM_CONDITIONAL([HAS_KYOTOCABINET], [ test "x${has_kyotocabinet}" = "x1" ])

AS_IF([test "x$enable_experimental_plugins" = "xyes"], [
AC_CONFIG_FILES([
plugins/experimental/Makefile
plugins/experimental/authproxy/Makefile
plugins/experimental/background_fetch/Makefile
plugins/experimental/balancer/Makefile
plugins/experimental/buffer_upload/Makefile
plugins/experimental/cache_key_genid/Makefile
plugins/experimental/cache_range_requests/Makefile
plugins/experimental/channel_stats/Makefile
plugins/experimental/cache_promote/Makefile
Expand Down
4 changes: 4 additions & 0 deletions plugins/experimental/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -51,3 +51,7 @@ endif
if BUILD_LUAJIT
SUBDIRS += ts_lua
endif

if HAS_KYOTOCABINET
SUBDIRS += cache_key_genid
endif
22 changes: 22 additions & 0 deletions plugins/experimental/cache_key_genid/Makefile.am
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

include $(top_srcdir)/build/plugins.mk

pkglib_LTLIBRARIES = cache_key_genid.la
cache_key_genid_la_SOURCES = cache_key_genid.c
cache_key_genid_la_LDFLAGS = $(TS_PLUGIN_LDFLAGS) $(LIB_KYOTOCABINET)

175 changes: 175 additions & 0 deletions plugins/experimental/cache_key_genid/cache_key_genid.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,175 @@
/*
* 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.
*/

/* cache-key-genid.c - Plugin to modify the URL used as a cache key for
* requests, without modifying the URL used for actually fetching data from
* the origin server.
*/

#include <ts/ts.h>
#include <stdio.h>
#include <string.h>
#include "kclangc.h"

#define PLUGIN_NAME "cache-key-genid"

static char genid_kyoto_db[PATH_MAX + 1];

// Find the host in url and set host to it
static void
get_genid_host(char **host, char *url)
{
char *pt1;
char *pt2;
size_t host_len;
unsigned num = 1;

pt1 = strstr(url, "//");

if (pt1) {
pt1 = pt1 + 2;
pt2 = strstr(pt1, "/");
}

if (pt1 && pt2 && pt2 > pt1) {
host_len = pt2 - pt1;
*host = calloc(num, host_len + 1);
strncpy(*host, pt1, host_len);
}
}

/* get_genid
* Looks up the host's genid in the host->genid database
*/
static int
get_genid (char *host)
{
KCDB* db;
char *vbuf;
size_t vsiz;
int answer = 0;
int host_size;

/* create the database object */
db = kcdbnew();

/* open the database */
if (!kcdbopen(db, genid_kyoto_db, KCOREADER | KCONOLOCK)) {
TSDebug(PLUGIN_NAME, "could not open the genid database %s", genid_kyoto_db);
TSError("[%s] could not open the genid database %s: %s",
PLUGIN_NAME, genid_kyoto_db, strerror(errno));
return 0;
}

vbuf = kcdbget(db, host, strlen(host), &vsiz);

if (vbuf) {
TSDebug(PLUGIN_NAME, "kcdbget(%s) = %s", host, vbuf);
answer = (int) strtol(vbuf, NULL, 10);
kcfree(vbuf);
} else {
host_size = strlen(host);
TSDebug(PLUGIN_NAME, "kcdbget(%s) - no record found, len(%d)", host, host_size);
answer = 0;
}

kcdbclose(db);
return answer;
}

/* handle_hook
* Fires on TS_EVENT_HTTP_READ_REQUEST_HDR events, gets the effectiveUrl
* finds the host, gets the generation ID, gen_id, for the host
* and runs TSCacheUrlSet to change the cache key for the read
*/
static int
handle_hook(TSCont *contp, TSEvent event, void *edata)
{
TSHttpTxn txnp = (TSHttpTxn) edata;
char *url = NULL, *host = NULL;
int url_length;
int gen_id;
int ok = 1;

switch (event) {
case TS_EVENT_HTTP_READ_REQUEST_HDR:
TSDebug(PLUGIN_NAME, "handling TS_EVENT_HTTP_READ_REQUEST_HDR");

if (ok) {
url = TSHttpTxnEffectiveUrlStringGet(txnp, &url_length);
if (!url) {
TSError("[%s] could not retrieve request url", PLUGIN_NAME);
ok = 0;
}
}

if (ok) {
get_genid_host(&host, url);
if (!host) {
TSError("[%s] could not retrieve request host", PLUGIN_NAME);
ok = 0;
}
}

if (ok) {
TSDebug(PLUGIN_NAME, "From url (%s) discovered host (%s)", url, host);
if ((gen_id = get_genid(host)) != 0) {
if (TSHttpTxnConfigIntSet(txnp, TS_CONFIG_HTTP_CACHE_GENERATION, gen_id) != TS_SUCCESS) {
TSDebug(PLUGIN_NAME, "Error, unable to modify cache url");
TSError("[%s] Unable to set cache generation for %s to %d", PLUGIN_NAME, url, gen_id);
ok = 0;
}
}
}

/* Clean up */
if (url)
TSfree(url);
if (host)
TSfree(host);
TSHttpTxnReenable(txnp, TS_EVENT_HTTP_CONTINUE);
break;

default:
TSAssert(!"Unexpected event");
ok = 0;
break;
}

return ok;
}

void
TSPluginInit(int argc, const char *argv[])
{
TSPluginRegistrationInfo info;

info.plugin_name = (char *)PLUGIN_NAME;
info.vendor_name = (char *)"Apache Software Foundation";
info.support_email = (char *)"dev@trafficserver.apache.org";

if (argc > 1) {
TSstrlcpy(genid_kyoto_db, argv[1], sizeof(genid_kyoto_db));
} else {
TSError("[%s] plugin registration failed. check argv[1] for db path", PLUGIN_NAME);
return;
}

if (TSPluginRegister(&info) != TS_SUCCESS) {
TSError("[%s] plugin registration failed. check version.", PLUGIN_NAME);
return;
}

TSHttpHookAdd(TS_HTTP_READ_REQUEST_HDR_HOOK, TSContCreate((TSEventFunc)handle_hook, NULL));
}