Github user SolidWallOfCode commented on a diff in the pull request:

    https://github.com/apache/trafficserver/pull/877#discussion_r75409533
  
    --- Diff: plugins/experimental/header_freq/header_freq.cc ---
    @@ -0,0 +1,260 @@
    +/** @file
    +
    +  This plugin counts the number of times every header has appeared.
    +  Maintains separate counts for client and origin headers.
    +
    +  @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 <iostream>
    +#include <map>
    +#include <sstream>
    +#include <stdlib.h>
    +#include <string.h>
    +#include <string>
    +#include <ts/ts.h>
    +
    +
    +// plugin registration info
    +static char plugin_name[]   = "header_freq";
    +static char vendor_name[]   = "Apache Software Foundation";
    +static char support_email[] = "d...@trafficserver.apache.org";
    +
    +// debug messages during one-time initialization
    +static const char DEBUG_TAG_INIT[] = "header_freq.init";
    +
    +// debug messages in continuation callbacks
    +static const char DEBUG_TAG_HOOK[] = "header_freq.hook";
    +
    +// maps from header name to # of times encountered
    +static std::map<std::string, unsigned int> client_freq;
    +static std::map<std::string, unsigned int> origin_freq;
    +
    +// for traffic_ctl, name is a convenient identifier
    +static const char *ctl_tag = plugin_name;
    +static const char *ctl_log = "log"; // log all data
    +
    +static TSMutex freq_mutex;          // lock on global data
    +static const int retry_time = 10;   // spin after TSMutexLockTry failures
    +
    +static const char *log_name = plugin_name;
    +static TSTextLogObject log;
    +
    +static bool
    +freq_lock_try(TSCont contp)
    +{
    +  if (TSMutexLockTry(freq_mutex) != TS_SUCCESS) {
    +    TSDebug(DEBUG_TAG_HOOK, "Unable to acquire lock. Retrying in %d "
    +                            "milliseconds", retry_time);
    +    TSContSchedule(contp, retry_time, TS_THREAD_POOL_DEFAULT);
    +    return false;
    +  }
    +  return true;
    +}
    +
    +/**
    + * Logs the data collected, first the client, and then
    + * the origin headers.
    + */
    +static void
    +log_frequencies()
    +{
    +  std::stringstream ss("");
    +
    +  ss << std::endl << std::string(100, '+') << std::endl;
    +
    +  ss << "CLIENT HEADERS" << std::endl;
    +  for (auto &elem: client_freq) {
    +    ss << elem.first << ": " << elem.second << std::endl;
    +  }
    +
    +  ss << std::endl;
    +
    +  ss << "ORIGIN HEADERS" << std::endl;
    +  for (auto &elem: origin_freq) {
    +    ss << elem.first << ": " << elem.second << std::endl;
    +  }
    +
    +  ss << std::string(100, '+') << std::endl;
    +  TSTextLogObjectWrite(log, "%s", ss.str().c_str());
    +}
    +
    +/**
    + * Records all headers found in the buffer in the map provided. Comparison
    + * against existing entries is case-insensitive.
    + */
    +static void
    +count_all_headers(TSMBuffer &bufp, TSMLoc &hdr_loc, std::map<std::string, 
unsigned int> &map)
    +{
    +  TSMLoc hdr, next_hdr;
    +  hdr = TSMimeHdrFieldGet(bufp, hdr_loc, 0);
    +  int n_headers = TSMimeHdrFieldsCount(bufp, hdr_loc);
    +  TSDebug(DEBUG_TAG_HOOK, "%d headers found", n_headers);
    +
    +  // iterate through all headers
    +  for (int i = 0; i < n_headers; ++i) {
    +    if (hdr == NULL)
    +      break;
    +    next_hdr = TSMimeHdrFieldNext(bufp, hdr_loc, hdr);
    +    int hdr_len;
    +    const char *hdr_name = TSMimeHdrFieldNameGet(bufp, hdr_loc, hdr, 
&hdr_len);
    +
    +    std::string str = std::string(hdr_name, hdr_len);
    +
    +    // make case-insensitive by converting to lowercase
    +    for (auto &c: str) {
    +      c = tolower(c);
    +    }
    +
    +    // count the header
    +    if (map.find(str) == map.end()) {
    +      // Not found.
    +      map[str] = 1;
    +     } else {
    +      // Found.
    +      ++map[str];
    +    }
    +
    +    TSHandleMLocRelease(bufp, hdr_loc, hdr);
    +    hdr = next_hdr;
    +  }
    +
    +  TSHandleMLocRelease(bufp, TS_NULL_MLOC, hdr_loc);
    +}
    +
    +/**
    + * Continuation callback. Invoked to count headers on READ_REQUEST_HDR and
    + * SEND_RESPONSE_HDR hooks and to log through traffic_ctl's LIFECYCLE_MSG.
    + */
    +static int
    +handle_hook(TSCont contp, TSEvent event, void *edata)
    +{
    +  TSHttpTxn txnp;
    +  TSMBuffer bufp;
    +  TSMLoc hdr_loc;
    +  int ret_val = 0;
    +
    +  // Treats the handler as a critical section because all events touch 
global
    +  // data
    +  if (!freq_lock_try(contp)) {
    --- End diff --
    
    This is wasteful. If a continuation has a mutex then the hook and event 
dispatchers will lock that mutex before invoking the continuation.


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastruct...@apache.org or file a JIRA ticket
with INFRA.
---

Reply via email to