[ https://issues.apache.org/jira/browse/TS-4755?focusedWorklogId=26623&page=com.atlassian.jira.plugin.system.issuetabpanels:worklog-tabpanel#worklog-26623 ]
ASF GitHub Bot logged work on TS-4755: -------------------------------------- Author: ASF GitHub Bot Created on: 19/Aug/16 01:31 Start Date: 19/Aug/16 01:31 Worklog Time Spent: 10m Work Description: Github user petarpenkov commented on a diff in the pull request: https://github.com/apache/trafficserver/pull/877#discussion_r75416546 --- 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 -- The way I understand your comment is "If I create a continuation with a non-NULL mutex, ex. TSContCreate( HANDLER, TSMutexCreate()), then the HANDLER becomes a critical section." Is that correct? Does that mean that in this scenario a lock is not needed and initializing the cont with a mutex will suffice? Issue Time Tracking ------------------- Worklog Id: (was: 26623) Time Spent: 1.5h (was: 1h 20m) > Create a plugin that would count the frequency of headers > --------------------------------------------------------- > > Key: TS-4755 > URL: https://issues.apache.org/jira/browse/TS-4755 > Project: Traffic Server > Issue Type: Improvement > Components: Plugins > Reporter: Bryan Call > Assignee: Petar Penkov > Fix For: 7.2.0 > > Time Spent: 1.5h > Remaining Estimate: 0h > > Create a plugin that would count the frequency of headers. Have separate > frequency counters for origin and client. -- This message was sent by Atlassian JIRA (v6.3.4#6332)