You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@trafficcontrol.apache.org by ro...@apache.org on 2018/05/23 16:41:56 UTC

[incubator-trafficcontrol] 03/04: Add "store_range" mode, and required hook to change the cachekey

This is an automated email from the ASF dual-hosted git repository.

rob pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-trafficcontrol.git

commit bda941fd62661e8b556fbbf5662b6bb8353e6761
Author: Jan van Doorn <ja...@comcast.com>
AuthorDate: Sun May 13 12:29:17 2018 -0600

    Add "store_range" mode, and required hook to change the cachekey
---
 grove/cache/handler.go            |  4 ++++
 grove/plugin/plugin.go            | 19 +++++++++++++++++
 grove/plugin/range_req_handler.go | 44 +++++++++++++++++++++++++++++++++------
 grove/remap/remap.go              |  1 +
 4 files changed, 62 insertions(+), 6 deletions(-)

diff --git a/grove/cache/handler.go b/grove/cache/handler.go
index 216378c..74b40a5 100644
--- a/grove/cache/handler.go
+++ b/grove/cache/handler.go
@@ -223,6 +223,10 @@ func (h *Handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
 	log.Debugf("Serve got Cache-Control %+v (reqid %v)\n", reqCacheControl, reqID)
 
 	connectionClose := h.connectionClose || remappingProducer.ConnectionClose()
+
+	beforeCacheLookUpData := plugin.BeforeCacheLookUpData{Req: r, DefaultCacheKey: remappingProducer.CacheKey()}
+	h.plugins.OnBeforeCacheLookup(remappingProducer.PluginCfg(), pluginContext, beforeCacheLookUpData, remappingProducer.OverrideCacheKey)
+
 	cacheKey := remappingProducer.CacheKey()
 	retrier := NewRetrier(h, reqHeader, reqTime, reqCacheControl, remappingProducer, reqID)
 
diff --git a/grove/plugin/plugin.go b/grove/plugin/plugin.go
index ec425c7..32d1280 100644
--- a/grove/plugin/plugin.go
+++ b/grove/plugin/plugin.go
@@ -47,6 +47,7 @@ type Funcs struct {
 	load                LoadFunc
 	startup             StartupFunc
 	onRequest           OnRequestFunc
+	beforeCacheLookUp   BeforeCacheLookupFunc
 	beforeParentRequest BeforeParentRequestFunc
 	beforeRespond       BeforeRespondFunc
 	afterRespond        AfterRespondFunc
@@ -91,6 +92,12 @@ type BeforeRespondData struct {
 	Context   *interface{}
 }
 
+type BeforeCacheLookUpData struct {
+	Req             *http.Request
+	DefaultCacheKey string
+	Context         *interface{}
+}
+
 type AfterRespondData struct {
 	W         http.ResponseWriter
 	Stats     stat.Stats
@@ -105,6 +112,7 @@ type AfterRespondData struct {
 type LoadFunc func(json.RawMessage) interface{}
 type StartupFunc func(icfg interface{}, d StartupData)
 type OnRequestFunc func(icfg interface{}, d OnRequestData) bool
+type BeforeCacheLookupFunc func(icfg interface{}, d BeforeCacheLookUpData, cacheKeyOverRideFunc func(string))
 type BeforeParentRequestFunc func(icfg interface{}, d BeforeParentRequestData)
 type BeforeRespondFunc func(icfg interface{}, d BeforeRespondData)
 type AfterRespondFunc func(icfg interface{}, d AfterRespondData)
@@ -132,6 +140,7 @@ type Plugins interface {
 	LoadFuncs() map[string]LoadFunc
 	OnStartup(cfgs map[string]interface{}, context map[string]*interface{}, d StartupData)
 	OnRequest(cfgs map[string]interface{}, context map[string]*interface{}, d OnRequestData) bool
+	OnBeforeCacheLookup(cfgs map[string]interface{}, context map[string]*interface{}, d BeforeCacheLookUpData, cacheKeyOverrideFunc func(string))
 	OnBeforeParentRequest(cfgs map[string]interface{}, context map[string]*interface{}, d BeforeParentRequestData)
 	OnBeforeRespond(cfgs map[string]interface{}, context map[string]*interface{}, d BeforeRespondData)
 	OnAfterRespond(cfgs map[string]interface{}, context map[string]*interface{}, d AfterRespondData)
@@ -175,6 +184,16 @@ func (ps pluginsSlice) OnRequest(cfgs map[string]interface{}, context map[string
 	return false
 }
 
+func (ps pluginsSlice) OnBeforeCacheLookup(cfgs map[string]interface{}, context map[string]*interface{}, d BeforeCacheLookUpData, cacheKeyOverrideFunc func(string)) {
+	for _, p := range ps {
+		if p.funcs.beforeCacheLookUp == nil {
+			continue
+		}
+		d.Context = context[p.name]
+		p.funcs.beforeCacheLookUp(cfgs[p.name], d, cacheKeyOverrideFunc)
+	}
+}
+
 func (ps pluginsSlice) OnBeforeParentRequest(cfgs map[string]interface{}, context map[string]*interface{}, d BeforeParentRequestData) {
 	for _, p := range ps {
 		if p.funcs.beforeParentRequest == nil {
diff --git a/grove/plugin/range_req_handler.go b/grove/plugin/range_req_handler.go
index 321aa3c..354a6cc 100644
--- a/grove/plugin/range_req_handler.go
+++ b/grove/plugin/range_req_handler.go
@@ -37,7 +37,13 @@ type rangeRequestConfig struct {
 }
 
 func init() {
-	AddPlugin(10000, Funcs{load: rangeReqHandleLoad, onRequest: rangeReqHandlerOnRequest, beforeParentRequest: rangeReqHandleBeforeParent, beforeRespond: rangeReqHandleBeforeRespond})
+	AddPlugin(10000, Funcs{
+		load:                rangeReqHandleLoad,
+		onRequest:           rangeReqHandlerOnRequest,
+		beforeCacheLookUp:   rangeReqHandleBeforeCacheLookup,
+		beforeParentRequest: rangeReqHandleBeforeParent,
+		beforeRespond:       rangeReqHandleBeforeRespond,
+	})
 }
 
 // rangeReqHandleLoad loads the configuration
@@ -50,7 +56,7 @@ func rangeReqHandleLoad(b json.RawMessage) interface{} {
 		log.Errorln("range_rew_handler  loading config, unmarshalling JSON: " + err.Error())
 		return nil
 	}
-	if !(cfg.Mode == "getfull" || cfg.Mode == "patch") {
+	if !(cfg.Mode == "get_full_serve_range" || cfg.Mode == "patch") {
 		log.Errorf("Unknown mode for range_req_handler plugin: %s", cfg.Mode)
 	}
 	log.Debugf("range_rew_handler: load success: %+v\n", cfg)
@@ -71,7 +77,24 @@ func rangeReqHandlerOnRequest(icfg interface{}, d OnRequestData) bool {
 	return false
 }
 
-// rangeReqHandleBeforeParent changes the parent request if needed (mode == getfull)
+func rangeReqHandleBeforeCacheLookup(icfg interface{}, d BeforeCacheLookUpData, overRideFunc func(string)) {
+	cfg, ok := icfg.(*rangeRequestConfig)
+	if !ok {
+		log.Errorf("range_req_handler config '%v' type '%T' expected *rangeRequestConfig\n", icfg, icfg)
+		return
+	}
+	if cfg.Mode == "store_ranges" {
+		sep := "?"
+		if strings.Contains(d.DefaultCacheKey, "?") {
+			sep = "&"
+		}
+		newKey := d.DefaultCacheKey + sep + "grove_range_req_handler_plugin_data=" + d.Req.Header.Get("Range")
+		overRideFunc(newKey)
+		log.Debugf("range_req_handler: store_ranges default key:%s, new key:%s", d.DefaultCacheKey, newKey)
+	}
+}
+
+// rangeReqHandleBeforeParent changes the parent request if needed (mode == get_full_serve_range)
 func rangeReqHandleBeforeParent(icfg interface{}, d BeforeParentRequestData) {
 	log.Debugf("rangeReqHandleBeforeParent calling.")
 	rHeader := d.Req.Header.Get("Range")
@@ -85,15 +108,15 @@ func rangeReqHandleBeforeParent(icfg interface{}, d BeforeParentRequestData) {
 		log.Errorf("range_req_handler config '%v' type '%T' expected *rangeRequestConfig\n", icfg, icfg)
 		return
 	}
-	if cfg.Mode == "getfull" {
-		// getfull means get the whole thing from parent/org, but serve the requested range. Just remove the Range header from the upstream request
+	if cfg.Mode == "get_full_serve_range" {
+		// get_full_serve_range means get the whole thing from parent/org, but serve the requested range. Just remove the Range header from the upstream request
 		d.Req.Header.Del("Range")
 	}
 	return
 }
 
 // rangeReqHandleBeforeRespond builds the 206 response
-// Assume all the needed ranges have been put in cache before, which is the truth for "getfull" mode which gets the whole object into cache.
+// Assume all the needed ranges have been put in cache before, which is the truth for "get_full_serve_range" mode which gets the whole object into cache.
 func rangeReqHandleBeforeRespond(icfg interface{}, d BeforeRespondData) {
 	log.Debugf("rangeReqHandleBeforeRespond calling\n")
 	ictx := d.Context
@@ -105,6 +128,15 @@ func rangeReqHandleBeforeRespond(icfg interface{}, d BeforeRespondData) {
 		return // there was no (valid) range header
 	}
 
+	cfg, ok := icfg.(*rangeRequestConfig)
+	if !ok {
+		log.Errorf("range_req_handler config '%v' type '%T' expected *rangeRequestConfig\n", icfg, icfg)
+		return
+	}
+	if cfg.Mode == "store_ranges" {
+		return // no need to do anything here.
+	}
+
 	multipartBoundaryString := ""
 	originalContentType := d.Hdr.Get("Content-type")
 	*d.Hdr = web.CopyHeader(*d.Hdr) // copy the headers, we don't want to mod the cacheObj
diff --git a/grove/remap/remap.go b/grove/remap/remap.go
index 9793566..b21f279 100644
--- a/grove/remap/remap.go
+++ b/grove/remap/remap.go
@@ -118,6 +118,7 @@ type RemappingProducer struct {
 }
 
 func (p *RemappingProducer) CacheKey() string                  { return p.cacheKey }
+func (p *RemappingProducer) OverrideCacheKey(newKey string)    { p.cacheKey = newKey }
 func (p *RemappingProducer) ConnectionClose() bool             { return p.rule.ConnectionClose }
 func (p *RemappingProducer) Name() string                      { return p.rule.Name }
 func (p *RemappingProducer) DSCP() int                         { return p.rule.DSCP }

-- 
To stop receiving notification emails like this one, please contact
rob@apache.org.