[ https://issues.apache.org/jira/browse/TS-4395?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=15357333#comment-15357333 ]
ASF GitHub Bot commented on TS-4395: ------------------------------------ Github user jpeach commented on a diff in the pull request: https://github.com/apache/trafficserver/pull/747#discussion_r69160469 --- Diff: plugins/experimental/remap_purge/remap_purge.c --- @@ -0,0 +1,335 @@ +/** @file + + Per-remap purge RESTful API for stateful generation ID management. + + @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 <stdio.h> +#include <stdlib.h> +#include <ctype.h> +#include <string.h> +#include <sys/types.h> +#include <unistd.h> +#include <getopt.h> +#include <sys/stat.h> +#include <sys/types.h> + +#include "ts/ts.h" +#include "ts/remap.h" +#include "ts/ink_defs.h" + +static const char *PLUGIN_NAME = "remap_purge"; +static const char *DEFAULT_DIR = "var/trafficserver"; /* Not perfect, but no better API) */ + +typedef struct PurgeInstance_t { + char *id; + char *secret; + int secret_len; + char *header; + int header_len; + char *state_file; + bool allow_get; + int64_t gen_id; + TSMutex lock; +} PurgeInstance; + +static char * +make_state_path(const char *filename) +{ + if ('/' == *filename) { + return TSstrdup(filename); + } else { + char buf[8192]; + struct stat s; + const char *dir = TSInstallDirGet(); + + snprintf(buf, sizeof(buf) - 1, "%s/%s/%s", dir, DEFAULT_DIR, PLUGIN_NAME); + if (-1 == stat(buf, &s)) { + if (ENOENT == errno) { + if (-1 == mkdir(buf, S_IRWXU)) { + TSError("[%s] Unable to create directory %s: errno=%d", PLUGIN_NAME, buf, errno); + return NULL; + } + } else { + TSError("[%s] Unable to stat() directory %s: errno=%d", PLUGIN_NAME, buf, errno); + return NULL; + } + } else { + if (!S_ISDIR(s.st_mode)) { + TSError("[%s] Can not create directory %s, file exists", PLUGIN_NAME, buf); + return NULL; + } + } + snprintf(buf, sizeof(buf) - 1, "%s/%s/%s/%s.genid", dir, DEFAULT_DIR, PLUGIN_NAME, filename); + return TSstrdup(buf); + } + + return NULL; +} + +/* Constructor and destructor for the PurgeInstance */ +static void +init_purge_instance(PurgeInstance *purge, char *id) +{ + FILE *file = fopen(purge->state_file, "r"); + + if (file) { + fscanf(file, "%" PRId64 "", &purge->gen_id); + TSDebug(PLUGIN_NAME, "Read genID from %s for %s", purge->state_file, purge->id); + } + + /* If not specified, we set the ID tag to the fromURL from the remap rule that triggered */ + if (!purge->id) { + purge->id = TSstrdup(id); + } + + purge->lock = TSMutexCreate(); +} + +static void +delete_purge_instance(PurgeInstance *purge) +{ + if (purge) { + TSfree(purge->id); + TSfree(purge->state_file); + TSfree(purge->secret); + TSfree(purge->header); + TSMutexDestroy(purge->lock); + TSfree(purge); + } +} + +/* This is where we start the PURGE events, setting up the transactino to fail, + and bump the generation ID, and finally save the state. */ +static int +on_http_cache_lookup_complete(TSHttpTxn txnp, TSCont contp, PurgeInstance *purge) +{ + FILE *file; + + TSMutexLock(purge->lock); + + ++purge->gen_id; + TSDebug(PLUGIN_NAME, "Bumping the Generation ID to %" PRId64 " for %s", purge->gen_id, purge->id); + + if ((file = fopen(purge->state_file, "w"))) { + TSDebug(PLUGIN_NAME, "\tsaving state to %s", purge->state_file); + fprintf(file, "%" PRId64 "", purge->gen_id); + fclose(file); + } else { + TSError("[%s] Unable to save state to file %s: errno=%d", PLUGIN_NAME, purge->state_file, errno); + } + + TSMutexUnlock(purge->lock); + + TSHttpTxnReenable(txnp, TS_EVENT_HTTP_ERROR); + return TS_SUCCESS; +} + +/* Before we can send the response, we want to modify it to a "200 OK" again, + and produce some reasonabel body output. */ +static int +on_send_response_header(TSHttpTxn txnp, TSCont contp, PurgeInstance *purge) +{ + TSMBuffer bufp; + TSMLoc hdr_loc; + + TSDebug(PLUGIN_NAME, "Fixing up the response on the succseful PURGE"); + if (TS_SUCCESS == TSHttpTxnClientRespGet(txnp, &bufp, &hdr_loc)) { + char response[1024]; + int len = snprintf(response, sizeof(response) - 1, "PURGED %s\r\n\r\n", purge->id); --- End diff -- ``snprintf(response, sizeof(response), ...)``. ``snprintf`` writes at most ``size - 1`` characters. > conf_purge: Simple plugin to purge an entire remap rule > ------------------------------------------------------- > > Key: TS-4395 > URL: https://issues.apache.org/jira/browse/TS-4395 > Project: Traffic Server > Issue Type: New Feature > Components: Plugins > Reporter: Leif Hedstrom > Assignee: Leif Hedstrom > Fix For: 7.0.0 > > > This is similar to the existing plugin to purge based on a genID stored in a > persistent storage. The difference is that the purging is done exclusively > via a restful API, and has little (no) overhead on performance (since the > generation ID is always in memory). > Example: > {code} > map http://example.com/p1 http://p1.example.com > @plugin=remap_purge.so @pparam=--path=__secret_purge__ > @pparam=--state=example_p1 > {code} > And to purge: > {code} > $ curl -s -D - -X PURGE http://example.com/p1/__secret_purge__ > HTTP/1.1 200 OK > Date: Sat, 30 Apr 2016 00:09:34 GMT > Connection: close > Server: ATS/7.0.0 > Content-Length: 39 > Content-Type: text/html > PURGED http://example.com/p1 > {code} -- This message was sent by Atlassian JIRA (v6.3.4#6332)