[ 
https://issues.apache.org/jira/browse/TS-4395?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=15357353#comment-15357353
 ] 

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_r69162190
  
    --- 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);
    +    ;
    +
    +    TSHttpHdrStatusSet(bufp, hdr_loc, TS_HTTP_STATUS_OK);
    +    TSHttpHdrReasonSet(bufp, hdr_loc, "OK", 2);
    +    TSHttpTxnErrorBodySet(txnp, TSstrdup(response), len, NULL);
    +
    +    TSHandleMLocRelease(bufp, TS_NULL_MLOC, hdr_loc);
    +    TSHttpTxnReenable(txnp, TS_EVENT_HTTP_CONTINUE);
    +  } else {
    +    TSHttpTxnReenable(txnp, TS_EVENT_HTTP_ERROR);
    +  }
    +
    +  return TS_SUCCESS;
    +}
    +
    +/* This is the main continuation, triggered after DoRemap has decided we 
should
    +   handle this request internally. */
    +static int
    +purge_cont(TSCont contp, TSEvent event, void *edata)
    +{
    +  TSHttpTxn txnp       = (TSHttpTxn)edata;
    +  PurgeInstance *purge = (PurgeInstance *)TSContDataGet(contp);
    +
    +  switch (event) {
    +  case TS_EVENT_HTTP_SEND_RESPONSE_HDR:
    +    return on_send_response_header(txnp, contp, purge);
    +    break;
    +
    +  case TS_EVENT_HTTP_CACHE_LOOKUP_COMPLETE:
    +    return on_http_cache_lookup_complete(txnp, contp, purge);
    +    break;
    +
    +  default:
    +    TSDebug(PLUGIN_NAME, "Unexpected event: %d", event);
    +    break;
    +  }
    +
    +  return TS_SUCCESS;
    +}
    +
    +static void
    +handle_purge(TSHttpTxn txnp, PurgeInstance *purge)
    +{
    +  TSMBuffer reqp;
    +  TSMLoc hdr_loc = NULL, url_loc = NULL;
    +  bool should_purge = false;
    +
    +  if (TS_SUCCESS == TSHttpTxnClientReqGet(txnp, &reqp, &hdr_loc)) {
    +    /* First see if we require the "secret" to be passed in a header, and 
then use that */
    +    if (purge->header) {
    +      TSMLoc field_loc = TSMimeHdrFieldFind(reqp, hdr_loc, purge->header, 
purge->header_len);
    +
    +      if (field_loc) {
    +        const char *header;
    +        int header_len;
    +
    +        header = TSMimeHdrFieldValueStringGet(reqp, hdr_loc, field_loc, 
-1, &header_len);
    +        TSDebug(PLUGIN_NAME, "Checking for %.*s == %s ?", header_len, 
header, purge->secret);
    +        if (header && (header_len == purge->secret_len) && !memcmp(header, 
purge->secret, header_len)) {
    +          should_purge = true;
    --- End diff --
    
    Why don't you check the method on this branch?


> 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)

Reply via email to