mirror of
				https://github.com/minio/minio.git
				synced 2025-10-29 15:55:00 -04:00 
			
		
		
		
	Merge commit '4aa2e2eaa01e04e05cfbcd765afb5059ff85b8e1' as 'third_party/src/github.com/gorilla/context'
This commit is contained in:
		
						commit
						111b2639cd
					
				
							
								
								
									
										7
									
								
								third_party/src/github.com/gorilla/context/.travis.yml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								third_party/src/github.com/gorilla/context/.travis.yml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @ -0,0 +1,7 @@ | |||||||
|  | language: go | ||||||
|  | 
 | ||||||
|  | go: | ||||||
|  |   - 1.0 | ||||||
|  |   - 1.1 | ||||||
|  |   - 1.2 | ||||||
|  |   - tip | ||||||
							
								
								
									
										27
									
								
								third_party/src/github.com/gorilla/context/LICENSE
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										27
									
								
								third_party/src/github.com/gorilla/context/LICENSE
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @ -0,0 +1,27 @@ | |||||||
|  | Copyright (c) 2012 Rodrigo Moraes. All rights reserved. | ||||||
|  | 
 | ||||||
|  | Redistribution and use in source and binary forms, with or without | ||||||
|  | modification, are permitted provided that the following conditions are | ||||||
|  | met: | ||||||
|  | 
 | ||||||
|  | 	 * Redistributions of source code must retain the above copyright | ||||||
|  | notice, this list of conditions and the following disclaimer. | ||||||
|  | 	 * Redistributions in binary form must reproduce the above | ||||||
|  | copyright notice, this list of conditions and the following disclaimer | ||||||
|  | in the documentation and/or other materials provided with the | ||||||
|  | distribution. | ||||||
|  | 	 * Neither the name of Google Inc. nor the names of its | ||||||
|  | contributors may be used to endorse or promote products derived from | ||||||
|  | this software without specific prior written permission. | ||||||
|  | 
 | ||||||
|  | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||||||
|  | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||||||
|  | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||||||
|  | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||||||
|  | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||||||
|  | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | ||||||
|  | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||||||
|  | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||||||
|  | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||||||
|  | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||||||
|  | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||||||
							
								
								
									
										7
									
								
								third_party/src/github.com/gorilla/context/README.md
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								third_party/src/github.com/gorilla/context/README.md
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @ -0,0 +1,7 @@ | |||||||
|  | context | ||||||
|  | ======= | ||||||
|  | [](https://travis-ci.org/gorilla/context) | ||||||
|  | 
 | ||||||
|  | gorilla/context is a general purpose registry for global request variables. | ||||||
|  | 
 | ||||||
|  | Read the full documentation here: http://www.gorillatoolkit.org/pkg/context | ||||||
							
								
								
									
										143
									
								
								third_party/src/github.com/gorilla/context/context.go
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										143
									
								
								third_party/src/github.com/gorilla/context/context.go
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @ -0,0 +1,143 @@ | |||||||
|  | // Copyright 2012 The Gorilla Authors. All rights reserved. | ||||||
|  | // Use of this source code is governed by a BSD-style | ||||||
|  | // license that can be found in the LICENSE file. | ||||||
|  | 
 | ||||||
|  | package context | ||||||
|  | 
 | ||||||
|  | import ( | ||||||
|  | 	"net/http" | ||||||
|  | 	"sync" | ||||||
|  | 	"time" | ||||||
|  | ) | ||||||
|  | 
 | ||||||
|  | var ( | ||||||
|  | 	mutex sync.RWMutex | ||||||
|  | 	data  = make(map[*http.Request]map[interface{}]interface{}) | ||||||
|  | 	datat = make(map[*http.Request]int64) | ||||||
|  | ) | ||||||
|  | 
 | ||||||
|  | // Set stores a value for a given key in a given request. | ||||||
|  | func Set(r *http.Request, key, val interface{}) { | ||||||
|  | 	mutex.Lock() | ||||||
|  | 	if data[r] == nil { | ||||||
|  | 		data[r] = make(map[interface{}]interface{}) | ||||||
|  | 		datat[r] = time.Now().Unix() | ||||||
|  | 	} | ||||||
|  | 	data[r][key] = val | ||||||
|  | 	mutex.Unlock() | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // Get returns a value stored for a given key in a given request. | ||||||
|  | func Get(r *http.Request, key interface{}) interface{} { | ||||||
|  | 	mutex.RLock() | ||||||
|  | 	if ctx := data[r]; ctx != nil { | ||||||
|  | 		value := ctx[key] | ||||||
|  | 		mutex.RUnlock() | ||||||
|  | 		return value | ||||||
|  | 	} | ||||||
|  | 	mutex.RUnlock() | ||||||
|  | 	return nil | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // GetOk returns stored value and presence state like multi-value return of map access. | ||||||
|  | func GetOk(r *http.Request, key interface{}) (interface{}, bool) { | ||||||
|  | 	mutex.RLock() | ||||||
|  | 	if _, ok := data[r]; ok { | ||||||
|  | 		value, ok := data[r][key] | ||||||
|  | 		mutex.RUnlock() | ||||||
|  | 		return value, ok | ||||||
|  | 	} | ||||||
|  | 	mutex.RUnlock() | ||||||
|  | 	return nil, false | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // GetAll returns all stored values for the request as a map. Nil is returned for invalid requests. | ||||||
|  | func GetAll(r *http.Request) map[interface{}]interface{} { | ||||||
|  | 	mutex.RLock() | ||||||
|  | 	if context, ok := data[r]; ok { | ||||||
|  | 		result := make(map[interface{}]interface{}, len(context)) | ||||||
|  | 		for k, v := range context { | ||||||
|  | 			result[k] = v | ||||||
|  | 		} | ||||||
|  | 		mutex.RUnlock() | ||||||
|  | 		return result | ||||||
|  | 	} | ||||||
|  | 	mutex.RUnlock() | ||||||
|  | 	return nil | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // GetAllOk returns all stored values for the request as a map and a boolean value that indicates if | ||||||
|  | // the request was registered. | ||||||
|  | func GetAllOk(r *http.Request) (map[interface{}]interface{}, bool) { | ||||||
|  | 	mutex.RLock() | ||||||
|  | 	context, ok := data[r] | ||||||
|  | 	result := make(map[interface{}]interface{}, len(context)) | ||||||
|  | 	for k, v := range context { | ||||||
|  | 		result[k] = v | ||||||
|  | 	} | ||||||
|  | 	mutex.RUnlock() | ||||||
|  | 	return result, ok | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // Delete removes a value stored for a given key in a given request. | ||||||
|  | func Delete(r *http.Request, key interface{}) { | ||||||
|  | 	mutex.Lock() | ||||||
|  | 	if data[r] != nil { | ||||||
|  | 		delete(data[r], key) | ||||||
|  | 	} | ||||||
|  | 	mutex.Unlock() | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // Clear removes all values stored for a given request. | ||||||
|  | // | ||||||
|  | // This is usually called by a handler wrapper to clean up request | ||||||
|  | // variables at the end of a request lifetime. See ClearHandler(). | ||||||
|  | func Clear(r *http.Request) { | ||||||
|  | 	mutex.Lock() | ||||||
|  | 	clear(r) | ||||||
|  | 	mutex.Unlock() | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // clear is Clear without the lock. | ||||||
|  | func clear(r *http.Request) { | ||||||
|  | 	delete(data, r) | ||||||
|  | 	delete(datat, r) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // Purge removes request data stored for longer than maxAge, in seconds. | ||||||
|  | // It returns the amount of requests removed. | ||||||
|  | // | ||||||
|  | // If maxAge <= 0, all request data is removed. | ||||||
|  | // | ||||||
|  | // This is only used for sanity check: in case context cleaning was not | ||||||
|  | // properly set some request data can be kept forever, consuming an increasing | ||||||
|  | // amount of memory. In case this is detected, Purge() must be called | ||||||
|  | // periodically until the problem is fixed. | ||||||
|  | func Purge(maxAge int) int { | ||||||
|  | 	mutex.Lock() | ||||||
|  | 	count := 0 | ||||||
|  | 	if maxAge <= 0 { | ||||||
|  | 		count = len(data) | ||||||
|  | 		data = make(map[*http.Request]map[interface{}]interface{}) | ||||||
|  | 		datat = make(map[*http.Request]int64) | ||||||
|  | 	} else { | ||||||
|  | 		min := time.Now().Unix() - int64(maxAge) | ||||||
|  | 		for r := range data { | ||||||
|  | 			if datat[r] < min { | ||||||
|  | 				clear(r) | ||||||
|  | 				count++ | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	mutex.Unlock() | ||||||
|  | 	return count | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // ClearHandler wraps an http.Handler and clears request values at the end | ||||||
|  | // of a request lifetime. | ||||||
|  | func ClearHandler(h http.Handler) http.Handler { | ||||||
|  | 	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { | ||||||
|  | 		defer Clear(r) | ||||||
|  | 		h.ServeHTTP(w, r) | ||||||
|  | 	}) | ||||||
|  | } | ||||||
							
								
								
									
										161
									
								
								third_party/src/github.com/gorilla/context/context_test.go
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										161
									
								
								third_party/src/github.com/gorilla/context/context_test.go
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @ -0,0 +1,161 @@ | |||||||
|  | // Copyright 2012 The Gorilla Authors. All rights reserved. | ||||||
|  | // Use of this source code is governed by a BSD-style | ||||||
|  | // license that can be found in the LICENSE file. | ||||||
|  | 
 | ||||||
|  | package context | ||||||
|  | 
 | ||||||
|  | import ( | ||||||
|  | 	"net/http" | ||||||
|  | 	"testing" | ||||||
|  | ) | ||||||
|  | 
 | ||||||
|  | type keyType int | ||||||
|  | 
 | ||||||
|  | const ( | ||||||
|  | 	key1 keyType = iota | ||||||
|  | 	key2 | ||||||
|  | ) | ||||||
|  | 
 | ||||||
|  | func TestContext(t *testing.T) { | ||||||
|  | 	assertEqual := func(val interface{}, exp interface{}) { | ||||||
|  | 		if val != exp { | ||||||
|  | 			t.Errorf("Expected %v, got %v.", exp, val) | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	r, _ := http.NewRequest("GET", "http://localhost:8080/", nil) | ||||||
|  | 	emptyR, _ := http.NewRequest("GET", "http://localhost:8080/", nil) | ||||||
|  | 
 | ||||||
|  | 	// Get() | ||||||
|  | 	assertEqual(Get(r, key1), nil) | ||||||
|  | 
 | ||||||
|  | 	// Set() | ||||||
|  | 	Set(r, key1, "1") | ||||||
|  | 	assertEqual(Get(r, key1), "1") | ||||||
|  | 	assertEqual(len(data[r]), 1) | ||||||
|  | 
 | ||||||
|  | 	Set(r, key2, "2") | ||||||
|  | 	assertEqual(Get(r, key2), "2") | ||||||
|  | 	assertEqual(len(data[r]), 2) | ||||||
|  | 
 | ||||||
|  | 	//GetOk | ||||||
|  | 	value, ok := GetOk(r, key1) | ||||||
|  | 	assertEqual(value, "1") | ||||||
|  | 	assertEqual(ok, true) | ||||||
|  | 
 | ||||||
|  | 	value, ok = GetOk(r, "not exists") | ||||||
|  | 	assertEqual(value, nil) | ||||||
|  | 	assertEqual(ok, false) | ||||||
|  | 
 | ||||||
|  | 	Set(r, "nil value", nil) | ||||||
|  | 	value, ok = GetOk(r, "nil value") | ||||||
|  | 	assertEqual(value, nil) | ||||||
|  | 	assertEqual(ok, true) | ||||||
|  | 
 | ||||||
|  | 	// GetAll() | ||||||
|  | 	values := GetAll(r) | ||||||
|  | 	assertEqual(len(values), 3) | ||||||
|  | 
 | ||||||
|  | 	// GetAll() for empty request | ||||||
|  | 	values = GetAll(emptyR) | ||||||
|  | 	if values != nil { | ||||||
|  | 		t.Error("GetAll didn't return nil value for invalid request") | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	// GetAllOk() | ||||||
|  | 	values, ok = GetAllOk(r) | ||||||
|  | 	assertEqual(len(values), 3) | ||||||
|  | 	assertEqual(ok, true) | ||||||
|  | 
 | ||||||
|  | 	// GetAllOk() for empty request | ||||||
|  | 	values, ok = GetAllOk(emptyR) | ||||||
|  | 	assertEqual(value, nil) | ||||||
|  | 	assertEqual(ok, false) | ||||||
|  | 
 | ||||||
|  | 	// Delete() | ||||||
|  | 	Delete(r, key1) | ||||||
|  | 	assertEqual(Get(r, key1), nil) | ||||||
|  | 	assertEqual(len(data[r]), 2) | ||||||
|  | 
 | ||||||
|  | 	Delete(r, key2) | ||||||
|  | 	assertEqual(Get(r, key2), nil) | ||||||
|  | 	assertEqual(len(data[r]), 1) | ||||||
|  | 
 | ||||||
|  | 	// Clear() | ||||||
|  | 	Clear(r) | ||||||
|  | 	assertEqual(len(data), 0) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func parallelReader(r *http.Request, key string, iterations int, wait, done chan struct{}) { | ||||||
|  | 	<-wait | ||||||
|  | 	for i := 0; i < iterations; i++ { | ||||||
|  | 		Get(r, key) | ||||||
|  | 	} | ||||||
|  | 	done <- struct{}{} | ||||||
|  | 
 | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func parallelWriter(r *http.Request, key, value string, iterations int, wait, done chan struct{}) { | ||||||
|  | 	<-wait | ||||||
|  | 	for i := 0; i < iterations; i++ { | ||||||
|  | 		Get(r, key) | ||||||
|  | 	} | ||||||
|  | 	done <- struct{}{} | ||||||
|  | 
 | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func benchmarkMutex(b *testing.B, numReaders, numWriters, iterations int) { | ||||||
|  | 
 | ||||||
|  | 	b.StopTimer() | ||||||
|  | 	r, _ := http.NewRequest("GET", "http://localhost:8080/", nil) | ||||||
|  | 	done := make(chan struct{}) | ||||||
|  | 	b.StartTimer() | ||||||
|  | 
 | ||||||
|  | 	for i := 0; i < b.N; i++ { | ||||||
|  | 		wait := make(chan struct{}) | ||||||
|  | 
 | ||||||
|  | 		for i := 0; i < numReaders; i++ { | ||||||
|  | 			go parallelReader(r, "test", iterations, wait, done) | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		for i := 0; i < numWriters; i++ { | ||||||
|  | 			go parallelWriter(r, "test", "123", iterations, wait, done) | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		close(wait) | ||||||
|  | 
 | ||||||
|  | 		for i := 0; i < numReaders+numWriters; i++ { | ||||||
|  | 			<-done | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func BenchmarkMutexSameReadWrite1(b *testing.B) { | ||||||
|  | 	benchmarkMutex(b, 1, 1, 32) | ||||||
|  | } | ||||||
|  | func BenchmarkMutexSameReadWrite2(b *testing.B) { | ||||||
|  | 	benchmarkMutex(b, 2, 2, 32) | ||||||
|  | } | ||||||
|  | func BenchmarkMutexSameReadWrite4(b *testing.B) { | ||||||
|  | 	benchmarkMutex(b, 4, 4, 32) | ||||||
|  | } | ||||||
|  | func BenchmarkMutex1(b *testing.B) { | ||||||
|  | 	benchmarkMutex(b, 2, 8, 32) | ||||||
|  | } | ||||||
|  | func BenchmarkMutex2(b *testing.B) { | ||||||
|  | 	benchmarkMutex(b, 16, 4, 64) | ||||||
|  | } | ||||||
|  | func BenchmarkMutex3(b *testing.B) { | ||||||
|  | 	benchmarkMutex(b, 1, 2, 128) | ||||||
|  | } | ||||||
|  | func BenchmarkMutex4(b *testing.B) { | ||||||
|  | 	benchmarkMutex(b, 128, 32, 256) | ||||||
|  | } | ||||||
|  | func BenchmarkMutex5(b *testing.B) { | ||||||
|  | 	benchmarkMutex(b, 1024, 2048, 64) | ||||||
|  | } | ||||||
|  | func BenchmarkMutex6(b *testing.B) { | ||||||
|  | 	benchmarkMutex(b, 2048, 1024, 512) | ||||||
|  | } | ||||||
							
								
								
									
										82
									
								
								third_party/src/github.com/gorilla/context/doc.go
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										82
									
								
								third_party/src/github.com/gorilla/context/doc.go
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @ -0,0 +1,82 @@ | |||||||
|  | // Copyright 2012 The Gorilla Authors. All rights reserved. | ||||||
|  | // Use of this source code is governed by a BSD-style | ||||||
|  | // license that can be found in the LICENSE file. | ||||||
|  | 
 | ||||||
|  | /* | ||||||
|  | Package context stores values shared during a request lifetime. | ||||||
|  | 
 | ||||||
|  | For example, a router can set variables extracted from the URL and later | ||||||
|  | application handlers can access those values, or it can be used to store | ||||||
|  | sessions values to be saved at the end of a request. There are several | ||||||
|  | others common uses. | ||||||
|  | 
 | ||||||
|  | The idea was posted by Brad Fitzpatrick to the go-nuts mailing list: | ||||||
|  | 
 | ||||||
|  | 	http://groups.google.com/group/golang-nuts/msg/e2d679d303aa5d53 | ||||||
|  | 
 | ||||||
|  | Here's the basic usage: first define the keys that you will need. The key | ||||||
|  | type is interface{} so a key can be of any type that supports equality. | ||||||
|  | Here we define a key using a custom int type to avoid name collisions: | ||||||
|  | 
 | ||||||
|  | 	package foo | ||||||
|  | 
 | ||||||
|  | 	import ( | ||||||
|  | 		"github.com/gorilla/context" | ||||||
|  | 	) | ||||||
|  | 
 | ||||||
|  | 	type key int | ||||||
|  | 
 | ||||||
|  | 	const MyKey key = 0 | ||||||
|  | 
 | ||||||
|  | Then set a variable. Variables are bound to an http.Request object, so you | ||||||
|  | need a request instance to set a value: | ||||||
|  | 
 | ||||||
|  | 	context.Set(r, MyKey, "bar") | ||||||
|  | 
 | ||||||
|  | The application can later access the variable using the same key you provided: | ||||||
|  | 
 | ||||||
|  | 	func MyHandler(w http.ResponseWriter, r *http.Request) { | ||||||
|  | 		// val is "bar". | ||||||
|  | 		val := context.Get(r, foo.MyKey) | ||||||
|  | 
 | ||||||
|  | 		// returns ("bar", true) | ||||||
|  | 		val, ok := context.GetOk(r, foo.MyKey) | ||||||
|  | 		// ... | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | And that's all about the basic usage. We discuss some other ideas below. | ||||||
|  | 
 | ||||||
|  | Any type can be stored in the context. To enforce a given type, make the key | ||||||
|  | private and wrap Get() and Set() to accept and return values of a specific | ||||||
|  | type: | ||||||
|  | 
 | ||||||
|  | 	type key int | ||||||
|  | 
 | ||||||
|  | 	const mykey key = 0 | ||||||
|  | 
 | ||||||
|  | 	// GetMyKey returns a value for this package from the request values. | ||||||
|  | 	func GetMyKey(r *http.Request) SomeType { | ||||||
|  | 		if rv := context.Get(r, mykey); rv != nil { | ||||||
|  | 			return rv.(SomeType) | ||||||
|  | 		} | ||||||
|  | 		return nil | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	// SetMyKey sets a value for this package in the request values. | ||||||
|  | 	func SetMyKey(r *http.Request, val SomeType) { | ||||||
|  | 		context.Set(r, mykey, val) | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | Variables must be cleared at the end of a request, to remove all values | ||||||
|  | that were stored. This can be done in an http.Handler, after a request was | ||||||
|  | served. Just call Clear() passing the request: | ||||||
|  | 
 | ||||||
|  | 	context.Clear(r) | ||||||
|  | 
 | ||||||
|  | ...or use ClearHandler(), which conveniently wraps an http.Handler to clear | ||||||
|  | variables at the end of a request lifetime. | ||||||
|  | 
 | ||||||
|  | The Routers from the packages gorilla/mux and gorilla/pat call Clear() | ||||||
|  | so if you are using either of them you don't need to clear the context manually. | ||||||
|  | */ | ||||||
|  | package context | ||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user