[
https://issues.apache.org/jira/browse/TS-4723?focusedWorklogId=26924&page=com.atlassian.jira.plugin.system.issuetabpanels:worklog-tabpanel#worklog-26924
]
ASF GitHub Bot logged work on TS-4723:
--------------------------------------
Author: ASF GitHub Bot
Created on: 23/Aug/16 14:36
Start Date: 23/Aug/16 14:36
Worklog Time Spent: 10m
Work Description: Github user SolidWallOfCode commented on a diff in the
pull request:
https://github.com/apache/trafficserver/pull/843#discussion_r75879116
--- Diff: plugins/experimental/carp/HttpFetch.cc ---
@@ -0,0 +1,439 @@
+/** @file
+
+ Limited URL fetcher..
+
+ @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.
+ */
+
+#define __STDC_LIMIT_MACROS // need INT64_MAX definition
+#include <stdint.h>
+#include <sys/time.h>
+
+#include "HttpFetch.h"
+#include "UrlComponents.h"
+#include "Common.h"
+
+using std::string;
+
+/**********************************************************/
+// just 'pass through' and call object's handlEvent fn
+
+static int
+handleHttpFetchIOEvents(TSCont cont, TSEvent event, void *edata)
+{
+ HttpFetch *fetchObj = static_cast<HttpFetch *> (TSContDataGet(cont));
+ if (NULL == fetchObj) {
+ TSDebug(DEBUG_FETCH_TAG, "handleHttpFetchEvents continuation data
NULL");
+ TSAssert(fetchObj);
+ }
+ return fetchObj->handleIOEvent(cont, event, edata);
+}
+
+/**********************************************************/
+HttpFetch::HttpFetch(const std::string &url, HashAlgorithm *hashAlgo,
+ HashNode *hashNode,const char *method)
+{
+ TSMBuffer bufp;
+ _url = url;
+ _respInfo = NULL;
+ _reqInfo = NULL;
+ _hashAlgo = hashAlgo;
+ _hashNode = hashNode;
+ _hcTimeoutSecond = DEFAULT_HEALTH_CHECK_TIMEOUT;
+
+ bufp = TSMBufferCreate();
+
+ if (bufp != NULL) {
+ TSMLoc urlp;
+ if (TSUrlCreate(bufp, &urlp) == TS_SUCCESS) {
+ const char *start = url.data();
+ if (TSUrlParse(bufp, urlp, &start, start + url.length()) ==
TS_PARSE_DONE) {
+ UrlComponents reqUrl;
+ string sPath;
+ string sHost;
+ reqUrl.populate(bufp, urlp);
+ reqUrl.getCompletePathString(sPath);
+ reqUrl.getCompleteHostString(sHost);
+ _request = string(method) + " " + sPath + " HTTP/1.0\r\nHost: " +
sHost + "\r\n";
+ _request += CARP_ROUTED_HEADER + ": 1\r\n";
+ _request += "\r\n";
+ }
+ TSHandleMLocRelease(bufp, NULL, urlp);
+ }
+ }
+ TSMBufferDestroy(bufp);
+ TSDebug(DEBUG_FETCH_TAG, "HttpFetch assembled this request %s",
_request.c_str());
+ _responseStatus=TS_HTTP_STATUS_NONE;
+ _ready = true;
+}
+
+/**********************************************************/
+HttpFetch::~HttpFetch()
+{
+}
+/**********************************************************/
+void
+HttpFetch::setHealthcheckTimeout(int timeout) {
+ _hcTimeoutSecond = timeout;
+}
+/**********************************************************/
+void
+HttpFetch::makeAsyncRequest(struct sockaddr const* serverAddr)
+{
+ _ready = false;
+ __sync_synchronize();
+ _result = UNKNOWN;
+ TSCont fetchCont = TSContCreate(handleHttpFetchIOEvents,
TSMutexCreate());
+ //TSCont fetchCont = TSContCreate(handleHttpFetchIOEvents, NULL);
+ TSContDataSet(fetchCont, static_cast<void *> (this));
+
+ // save server addr
+ memmove((void *) &_serverAddr, (void *) serverAddr, sizeof (struct
sockaddr));
+
+ // initiate request
+ TSDebug(DEBUG_FETCH_TAG, "TSNetConnect()");
+
+ struct timeval tvStart;
+ gettimeofday(&tvStart, NULL);
+ _startTime = tvStart.tv_sec*1000 + tvStart.tv_usec/1000;
+
+ struct sockaddr_in tempServerAddr;
+ memmove((void *) &tempServerAddr, (void *) &_serverAddr, sizeof (struct
sockaddr));
+ TSDebug(DEBUG_FETCH_TAG, "serverAddr: %s:%d",
inet_ntoa(tempServerAddr.sin_addr), ntohs(tempServerAddr.sin_port) );
+ _hcTimeout = TSContSchedule(fetchCont, _hcTimeoutSecond * 1000,
TS_THREAD_POOL_DEFAULT);
+ _connAction = TSNetConnect(fetchCont, (const struct sockaddr *)
&_serverAddr);
+
+}
+
+/**********************************************************/
+void
+HttpFetch::parseResponse()
+{
+ TSIOBufferBlock block;
+ TSParseResult pr = TS_PARSE_CONT;
+ int64_t avail = 0;
+ char *start = NULL;
+ char *initialStart = NULL;
+
+ TSDebug(DEBUG_FETCH_TAG, "Entering parse_response");
+
+ block = TSIOBufferReaderStart(_respIOBufReader);
+
+ if (!_respInfo->headerParsed) {
+ while ((pr == TS_PARSE_CONT) && (block != NULL)) {
+ initialStart = start = (char *) TSIOBufferBlockReadStart(block,
_respIOBufReader, &avail);
+ if (avail > 0) {
+ pr = TSHttpHdrParseResp(_respInfo->parser, _respInfo->buf,
_respInfo->http_hdr_loc, (const char **) &start, (const char *) (start +
avail));
+ _responseHeaders.append(initialStart, start - initialStart);
+ }
+ block = TSIOBufferBlockNext(block);
+ }
+ // update avail
+ if (start && initialStart) {
+ avail -= (start - initialStart);
+ }
+ if (pr != TS_PARSE_CONT) {
+ _respInfo->status = TSHttpHdrStatusGet(_respInfo->buf,
_respInfo->http_hdr_loc);
+ _responseStatus = _respInfo->status;
+ _respInfo->headerParsed = true;
+ TSDebug(DEBUG_FETCH_TAG, "HTTP Status: %d", _respInfo->status);
+ }
+ }
+
+ if (_respInfo->headerParsed) {
+ if (avail && start) { // if bytes left from header parsing, get those
+ _responseBody.append(start, avail);
+ if(block) {
+ block = TSIOBufferBlockNext(block);
+ }
+ }
+
+ while (block != NULL) {
+ start = (char *) TSIOBufferBlockReadStart(block, _respIOBufReader,
&avail);
+ if (avail > 0) {
+ _responseBody.append(start, avail);
+ }
+ block = TSIOBufferBlockNext(block);
+ }
+ }
+ TSDebug(DEBUG_FETCH_TAG, "Leaving parseResponse");
+}
+
+
+/**********************************************************/
+int
+HttpFetch::handleIOEvent(TSCont cont, TSEvent event, void *edata)
+{
+ int64_t avail;
+ bool bCleanUp = false; // free everything when transaction is complete
+
+
+ TSDebug(DEBUG_FETCH_TAG, "Entering handleIOEvent");
+
+ switch (event) {
+ case TS_EVENT_NET_CONNECT: // connected to server
+ TSDebug(DEBUG_FETCH_TAG, "Connected (maybe)");
+ _connAction = NULL;
+ _respInfo = createResponseInfo();
+ _reqInfo = createRequestInfo();
+
+ _reqIOBuf = TSIOBufferCreate();
+ _reqIOBufReader = TSIOBufferReaderAlloc(_reqIOBuf);
+ _respIOBuf = TSIOBufferCreate();
+ _respIOBufReader = TSIOBufferReaderAlloc(_respIOBuf);
+
+ TSHttpHdrPrint(_reqInfo->buf, _reqInfo->http_hdr_loc, _reqIOBuf);
+ TSIOBufferWrite(_reqIOBuf, "\r\n", 2);
+
+ _vConn = static_cast<TSVConn> (edata); // get connection
+
+ _rVIO = TSVConnRead(_vConn, cont, _respIOBuf, INT64_MAX);
+
+ TSDebug(DEBUG_FETCH_TAG, "Writing %ld bytes",
TSIOBufferReaderAvail(_reqIOBufReader));
+ _wVIO = TSVConnWrite(_vConn, cont, _reqIOBufReader,
TSIOBufferReaderAvail(_reqIOBufReader));
+ break;
+ case TS_EVENT_NET_CONNECT_FAILED:
+ TSDebug(DEBUG_FETCH_TAG, "Connect failed");
+ _connAction = NULL;
+ TSActionCancel(_hcTimeout);
+ _hcTimeout = NULL;
+ _result = FAILURE;
+ break;
+ case TS_EVENT_ERROR:
+ TSDebug(DEBUG_FETCH_TAG, "Error event");
--- End diff --
Cancel `_hcTimeout`?
Issue Time Tracking
-------------------
Worklog Id: (was: 26924)
Time Spent: 7h (was: 6h 50m)
> ATS CARP Plugin
> ---------------
>
> Key: TS-4723
> URL: https://issues.apache.org/jira/browse/TS-4723
> Project: Traffic Server
> Issue Type: New Feature
> Components: Plugins
> Reporter: Eric Schwartz
> Assignee: Eric Schwartz
> Fix For: 7.0.0
>
> Time Spent: 7h
> Remaining Estimate: 0h
>
> Open sourcing this plugin we use internally within Yahoo in place of
> hierarchical caching.
> CARP is a plugin that allows you to group a bunch of ATS hosts into a cluster
> and share cache space across the entire group. This is done with consistent
> hashing on the object URL to generate an "owner" node in the cluster.
> Requests to any other node in the cluster will be forwarded on to the
> corresponding owner. More info in the README.
> Difference from internal version of note:
> I've ripped out some code we weren't entirely sure we could open source
> because of a hash function. If it turns out that we can open source this,
> I'll do so. The CarpHashAlgorithm class is meant to be extensible, so any
> consistent hash function can replace it. The function included here is pretty
> straightforward but not what we use in production, so just wanted to use that
> caveat.
> One last caveat:
> You'll see some code and documentation in here for object replication. This
> is something I added recently to CARP that allows you to specify an object be
> replicated a certain number of times in the cluster. This is useful if you
> have a network partition or if you're performing some sort of update. When an
> object's primary owner is unreachable, a node in the cluster can go to the
> secondary owner if it's available rather than having to fall all the way back
> to origin. While I've done some initial testing on this with my own cluster
> of hosts, it's not been tested in production so use at your own risk for now.
> I'll be sure to keep the open source community informed on the progress of
> our tests with this feature.
--
This message was sent by Atlassian JIRA
(v6.3.4#6332)