diff options
Diffstat (limited to 'vendor/github.com/go-macaron/cache')
-rw-r--r-- | vendor/github.com/go-macaron/cache/LICENSE | 191 | ||||
-rw-r--r-- | vendor/github.com/go-macaron/cache/README.md | 20 | ||||
-rw-r--r-- | vendor/github.com/go-macaron/cache/cache.go | 122 | ||||
-rw-r--r-- | vendor/github.com/go-macaron/cache/file.go | 208 | ||||
-rw-r--r-- | vendor/github.com/go-macaron/cache/memcache/memcache.go | 92 | ||||
-rw-r--r-- | vendor/github.com/go-macaron/cache/memcache/memcache.goconvey | 1 | ||||
-rw-r--r-- | vendor/github.com/go-macaron/cache/memory.go | 179 | ||||
-rw-r--r-- | vendor/github.com/go-macaron/cache/redis/redis.go | 178 | ||||
-rw-r--r-- | vendor/github.com/go-macaron/cache/redis/redis.goconvey | 1 | ||||
-rw-r--r-- | vendor/github.com/go-macaron/cache/utils.go | 84 |
10 files changed, 1076 insertions, 0 deletions
diff --git a/vendor/github.com/go-macaron/cache/LICENSE b/vendor/github.com/go-macaron/cache/LICENSE new file mode 100644 index 00000000..8405e89a --- /dev/null +++ b/vendor/github.com/go-macaron/cache/LICENSE @@ -0,0 +1,191 @@ +Apache License +Version 2.0, January 2004 +http://www.apache.org/licenses/ + +TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + +1. Definitions. + +"License" shall mean the terms and conditions for use, reproduction, and +distribution as defined by Sections 1 through 9 of this document. + +"Licensor" shall mean the copyright owner or entity authorized by the copyright +owner that is granting the License. + +"Legal Entity" shall mean the union of the acting entity and all other entities +that control, are controlled by, or are under common control with that entity. +For the purposes of this definition, "control" means (i) the power, direct or +indirect, to cause the direction or management of such entity, whether by +contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the +outstanding shares, or (iii) beneficial ownership of such entity. + +"You" (or "Your") shall mean an individual or Legal Entity exercising +permissions granted by this License. + +"Source" form shall mean the preferred form for making modifications, including +but not limited to software source code, documentation source, and configuration +files. + +"Object" form shall mean any form resulting from mechanical transformation or +translation of a Source form, including but not limited to compiled object code, +generated documentation, and conversions to other media types. + +"Work" shall mean the work of authorship, whether in Source or Object form, made +available under the License, as indicated by a copyright notice that is included +in or attached to the work (an example is provided in the Appendix below). + +"Derivative Works" shall mean any work, whether in Source or Object form, that +is based on (or derived from) the Work and for which the editorial revisions, +annotations, elaborations, or other modifications represent, as a whole, an +original work of authorship. For the purposes of this License, Derivative Works +shall not include works that remain separable from, or merely link (or bind by +name) to the interfaces of, the Work and Derivative Works thereof. + +"Contribution" shall mean any work of authorship, including the original version +of the Work and any modifications or additions to that Work or Derivative Works +thereof, that is intentionally submitted to Licensor for inclusion in the Work +by the copyright owner or by an individual or Legal Entity authorized to submit +on behalf of the copyright owner. For the purposes of this definition, +"submitted" means any form of electronic, verbal, or written communication sent +to the Licensor or its representatives, including but not limited to +communication on electronic mailing lists, source code control systems, and +issue tracking systems that are managed by, or on behalf of, the Licensor for +the purpose of discussing and improving the Work, but excluding communication +that is conspicuously marked or otherwise designated in writing by the copyright +owner as "Not a Contribution." + +"Contributor" shall mean Licensor and any individual or Legal Entity on behalf +of whom a Contribution has been received by Licensor and subsequently +incorporated within the Work. + +2. Grant of Copyright License. + +Subject to the terms and conditions of this License, each Contributor hereby +grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, +irrevocable copyright license to reproduce, prepare Derivative Works of, +publicly display, publicly perform, sublicense, and distribute the Work and such +Derivative Works in Source or Object form. + +3. Grant of Patent License. + +Subject to the terms and conditions of this License, each Contributor hereby +grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, +irrevocable (except as stated in this section) patent license to make, have +made, use, offer to sell, sell, import, and otherwise transfer the Work, where +such license applies only to those patent claims licensable by such Contributor +that are necessarily infringed by their Contribution(s) alone or by combination +of their Contribution(s) with the Work to which such Contribution(s) was +submitted. If You institute patent litigation against any entity (including a +cross-claim or counterclaim in a lawsuit) alleging that the Work or a +Contribution incorporated within the Work constitutes direct or contributory +patent infringement, then any patent licenses granted to You under this License +for that Work shall terminate as of the date such litigation is filed. + +4. Redistribution. + +You may reproduce and distribute copies of the Work or Derivative Works thereof +in any medium, with or without modifications, and in Source or Object form, +provided that You meet the following conditions: + +You must give any other recipients of the Work or Derivative Works a copy of +this License; and +You must cause any modified files to carry prominent notices stating that You +changed the files; and +You must retain, in the Source form of any Derivative Works that You distribute, +all copyright, patent, trademark, and attribution notices from the Source form +of the Work, excluding those notices that do not pertain to any part of the +Derivative Works; and +If the Work includes a "NOTICE" text file as part of its distribution, then any +Derivative Works that You distribute must include a readable copy of the +attribution notices contained within such NOTICE file, excluding those notices +that do not pertain to any part of the Derivative Works, in at least one of the +following places: within a NOTICE text file distributed as part of the +Derivative Works; within the Source form or documentation, if provided along +with the Derivative Works; or, within a display generated by the Derivative +Works, if and wherever such third-party notices normally appear. The contents of +the NOTICE file are for informational purposes only and do not modify the +License. You may add Your own attribution notices within Derivative Works that +You distribute, alongside or as an addendum to the NOTICE text from the Work, +provided that such additional attribution notices cannot be construed as +modifying the License. +You may add Your own copyright statement to Your modifications and may provide +additional or different license terms and conditions for use, reproduction, or +distribution of Your modifications, or for any such Derivative Works as a whole, +provided Your use, reproduction, and distribution of the Work otherwise complies +with the conditions stated in this License. + +5. Submission of Contributions. + +Unless You explicitly state otherwise, any Contribution intentionally submitted +for inclusion in the Work by You to the Licensor shall be under the terms and +conditions of this License, without any additional terms or conditions. +Notwithstanding the above, nothing herein shall supersede or modify the terms of +any separate license agreement you may have executed with Licensor regarding +such Contributions. + +6. Trademarks. + +This License does not grant permission to use the trade names, trademarks, +service marks, or product names of the Licensor, except as required for +reasonable and customary use in describing the origin of the Work and +reproducing the content of the NOTICE file. + +7. Disclaimer of Warranty. + +Unless required by applicable law or agreed to in writing, Licensor provides the +Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, +including, without limitation, any warranties or conditions of TITLE, +NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are +solely responsible for determining the appropriateness of using or +redistributing the Work and assume any risks associated with Your exercise of +permissions under this License. + +8. Limitation of Liability. + +In no event and under no legal theory, whether in tort (including negligence), +contract, or otherwise, unless required by applicable law (such as deliberate +and grossly negligent acts) or agreed to in writing, shall any Contributor be +liable to You for damages, including any direct, indirect, special, incidental, +or consequential damages of any character arising as a result of this License or +out of the use or inability to use the Work (including but not limited to +damages for loss of goodwill, work stoppage, computer failure or malfunction, or +any and all other commercial damages or losses), even if such Contributor has +been advised of the possibility of such damages. + +9. Accepting Warranty or Additional Liability. + +While redistributing the Work or Derivative Works thereof, You may choose to +offer, and charge a fee for, acceptance of support, warranty, indemnity, or +other liability obligations and/or rights consistent with this License. However, +in accepting such obligations, You may act only on Your own behalf and on Your +sole responsibility, not on behalf of any other Contributor, and only if You +agree to indemnify, defend, and hold each Contributor harmless for any liability +incurred by, or claims asserted against, such Contributor by reason of your +accepting any such warranty or additional liability. + +END OF TERMS AND CONDITIONS + +APPENDIX: How to apply the Apache License to your work + +To apply the Apache License to your work, attach the following boilerplate +notice, with the fields enclosed by brackets "[]" replaced with your own +identifying information. (Don't include the brackets!) The text should be +enclosed in the appropriate comment syntax for the file format. We also +recommend that a file or class name and description of purpose be included on +the same "printed page" as the copyright notice for easier identification within +third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed 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.
\ No newline at end of file diff --git a/vendor/github.com/go-macaron/cache/README.md b/vendor/github.com/go-macaron/cache/README.md new file mode 100644 index 00000000..d27aa93b --- /dev/null +++ b/vendor/github.com/go-macaron/cache/README.md @@ -0,0 +1,20 @@ +# cache [](https://travis-ci.org/go-macaron/cache) [](http://gocover.io/github.com/go-macaron/cache) + +Middleware cache provides cache management for [Macaron](https://github.com/go-macaron/macaron). It can use many cache adapters, including memory, file, Redis, Memcache, PostgreSQL, MySQL, Ledis and Nodb. + +### Installation + + go get github.com/go-macaron/cache + +## Getting Help + +- [API Reference](https://gowalker.org/github.com/go-macaron/cache) +- [Documentation](http://go-macaron.com/docs/middlewares/cache) + +## Credits + +This package is a modified version of [beego/cache](https://github.com/astaxie/beego/tree/master/cache). + +## License + +This project is under the Apache License, Version 2.0. See the [LICENSE](LICENSE) file for the full license text.
\ No newline at end of file diff --git a/vendor/github.com/go-macaron/cache/cache.go b/vendor/github.com/go-macaron/cache/cache.go new file mode 100644 index 00000000..7742a324 --- /dev/null +++ b/vendor/github.com/go-macaron/cache/cache.go @@ -0,0 +1,122 @@ +// Copyright 2013 Beego Authors +// Copyright 2014 The Macaron Authors +// +// Licensed 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. + +// Package cache is a middleware that provides the cache management of Macaron. +package cache + +import ( + "fmt" + + "gopkg.in/macaron.v1" +) + +const _VERSION = "0.3.0" + +func Version() string { + return _VERSION +} + +// Cache is the interface that operates the cache data. +type Cache interface { + // Put puts value into cache with key and expire time. + Put(key string, val interface{}, timeout int64) error + // Get gets cached value by given key. + Get(key string) interface{} + // Delete deletes cached value by given key. + Delete(key string) error + // Incr increases cached int-type value by given key as a counter. + Incr(key string) error + // Decr decreases cached int-type value by given key as a counter. + Decr(key string) error + // IsExist returns true if cached value exists. + IsExist(key string) bool + // Flush deletes all cached data. + Flush() error + // StartAndGC starts GC routine based on config string settings. + StartAndGC(opt Options) error +} + +// Options represents a struct for specifying configuration options for the cache middleware. +type Options struct { + // Name of adapter. Default is "memory". + Adapter string + // Adapter configuration, it's corresponding to adapter. + AdapterConfig string + // GC interval time in seconds. Default is 60. + Interval int + // Occupy entire database. Default is false. + OccupyMode bool + // Configuration section name. Default is "cache". + Section string +} + +func prepareOptions(options []Options) Options { + var opt Options + if len(options) > 0 { + opt = options[0] + } + if len(opt.Section) == 0 { + opt.Section = "cache" + } + sec := macaron.Config().Section(opt.Section) + + if len(opt.Adapter) == 0 { + opt.Adapter = sec.Key("ADAPTER").MustString("memory") + } + if opt.Interval == 0 { + opt.Interval = sec.Key("INTERVAL").MustInt(60) + } + if len(opt.AdapterConfig) == 0 { + opt.AdapterConfig = sec.Key("ADAPTER_CONFIG").MustString("data/caches") + } + + return opt +} + +// NewCacher creates and returns a new cacher by given adapter name and configuration. +// It panics when given adapter isn't registered and starts GC automatically. +func NewCacher(name string, opt Options) (Cache, error) { + adapter, ok := adapters[name] + if !ok { + return nil, fmt.Errorf("cache: unknown adapter '%s'(forgot to import?)", name) + } + return adapter, adapter.StartAndGC(opt) +} + +// Cacher is a middleware that maps a cache.Cache service into the Macaron handler chain. +// An single variadic cache.Options struct can be optionally provided to configure. +func Cacher(options ...Options) macaron.Handler { + opt := prepareOptions(options) + cache, err := NewCacher(opt.Adapter, opt) + if err != nil { + panic(err) + } + return func(ctx *macaron.Context) { + ctx.Map(cache) + } +} + +var adapters = make(map[string]Cache) + +// Register registers a adapter. +func Register(name string, adapter Cache) { + if adapter == nil { + panic("cache: cannot register adapter with nil value") + } + if _, dup := adapters[name]; dup { + panic(fmt.Errorf("cache: cannot register adapter '%s' twice", name)) + } + adapters[name] = adapter +} diff --git a/vendor/github.com/go-macaron/cache/file.go b/vendor/github.com/go-macaron/cache/file.go new file mode 100644 index 00000000..d9a33dcf --- /dev/null +++ b/vendor/github.com/go-macaron/cache/file.go @@ -0,0 +1,208 @@ +// Copyright 2013 Beego Authors +// Copyright 2014 The Macaron Authors +// +// Licensed 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. + +package cache + +import ( + "crypto/md5" + "encoding/hex" + "fmt" + "io/ioutil" + "log" + "os" + "path/filepath" + "sync" + "time" + + "github.com/Unknwon/com" + "gopkg.in/macaron.v1" +) + +// Item represents a cache item. +type Item struct { + Val interface{} + Created int64 + Expire int64 +} + +func (item *Item) hasExpired() bool { + return item.Expire > 0 && + (time.Now().Unix()-item.Created) >= item.Expire +} + +// FileCacher represents a file cache adapter implementation. +type FileCacher struct { + lock sync.Mutex + rootPath string + interval int // GC interval. +} + +// NewFileCacher creates and returns a new file cacher. +func NewFileCacher() *FileCacher { + return &FileCacher{} +} + +func (c *FileCacher) filepath(key string) string { + m := md5.Sum([]byte(key)) + hash := hex.EncodeToString(m[:]) + return filepath.Join(c.rootPath, string(hash[0]), string(hash[1]), hash) +} + +// Put puts value into cache with key and expire time. +// If expired is 0, it will not be deleted by GC. +func (c *FileCacher) Put(key string, val interface{}, expire int64) error { + filename := c.filepath(key) + item := &Item{val, time.Now().Unix(), expire} + data, err := EncodeGob(item) + if err != nil { + return err + } + + os.MkdirAll(filepath.Dir(filename), os.ModePerm) + return ioutil.WriteFile(filename, data, os.ModePerm) +} + +func (c *FileCacher) read(key string) (*Item, error) { + filename := c.filepath(key) + + data, err := ioutil.ReadFile(filename) + if err != nil { + return nil, err + } + + item := new(Item) + return item, DecodeGob(data, item) +} + +// Get gets cached value by given key. +func (c *FileCacher) Get(key string) interface{} { + item, err := c.read(key) + if err != nil { + return nil + } + + if item.hasExpired() { + os.Remove(c.filepath(key)) + return nil + } + return item.Val +} + +// Delete deletes cached value by given key. +func (c *FileCacher) Delete(key string) error { + return os.Remove(c.filepath(key)) +} + +// Incr increases cached int-type value by given key as a counter. +func (c *FileCacher) Incr(key string) error { + item, err := c.read(key) + if err != nil { + return err + } + + item.Val, err = Incr(item.Val) + if err != nil { + return err + } + + return c.Put(key, item.Val, item.Expire) +} + +// Decrease cached int value. +func (c *FileCacher) Decr(key string) error { + item, err := c.read(key) + if err != nil { + return err + } + + item.Val, err = Decr(item.Val) + if err != nil { + return err + } + + return c.Put(key, item.Val, item.Expire) +} + +// IsExist returns true if cached value exists. +func (c *FileCacher) IsExist(key string) bool { + return com.IsExist(c.filepath(key)) +} + +// Flush deletes all cached data. +func (c *FileCacher) Flush() error { + return os.RemoveAll(c.rootPath) +} + +func (c *FileCacher) startGC() { + c.lock.Lock() + defer c.lock.Unlock() + + if c.interval < 1 { + return + } + + if err := filepath.Walk(c.rootPath, func(path string, fi os.FileInfo, err error) error { + if err != nil { + return fmt.Errorf("Walk: %v", err) + } + + if fi.IsDir() { + return nil + } + + data, err := ioutil.ReadFile(path) + if err != nil && !os.IsNotExist(err) { + fmt.Errorf("ReadFile: %v", err) + } + + item := new(Item) + if err = DecodeGob(data, item); err != nil { + return err + } + if item.hasExpired() { + if err = os.Remove(path); err != nil && !os.IsNotExist(err) { + return fmt.Errorf("Remove: %v", err) + } + } + return nil + }); err != nil { + log.Printf("error garbage collecting cache files: %v", err) + } + + time.AfterFunc(time.Duration(c.interval)*time.Second, func() { c.startGC() }) +} + +// StartAndGC starts GC routine based on config string settings. +func (c *FileCacher) StartAndGC(opt Options) error { + c.lock.Lock() + c.rootPath = opt.AdapterConfig + c.interval = opt.Interval + + if !filepath.IsAbs(c.rootPath) { + c.rootPath = filepath.Join(macaron.Root, c.rootPath) + } + c.lock.Unlock() + + if err := os.MkdirAll(c.rootPath, os.ModePerm); err != nil { + return err + } + + go c.startGC() + return nil +} + +func init() { + Register("file", NewFileCacher()) +} diff --git a/vendor/github.com/go-macaron/cache/memcache/memcache.go b/vendor/github.com/go-macaron/cache/memcache/memcache.go new file mode 100644 index 00000000..f8a99097 --- /dev/null +++ b/vendor/github.com/go-macaron/cache/memcache/memcache.go @@ -0,0 +1,92 @@ +// Copyright 2013 Beego Authors +// Copyright 2014 The Macaron Authors +// +// Licensed 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. + +package cache + +import ( + "strings" + + "github.com/Unknwon/com" + "github.com/bradfitz/gomemcache/memcache" + + "github.com/go-macaron/cache" +) + +// MemcacheCacher represents a memcache cache adapter implementation. +type MemcacheCacher struct { + c *memcache.Client +} + +func NewItem(key string, data []byte, expire int32) *memcache.Item { + return &memcache.Item{ + Key: key, + Value: data, + Expiration: expire, + } +} + +// Put puts value into cache with key and expire time. +// If expired is 0, it lives forever. +func (c *MemcacheCacher) Put(key string, val interface{}, expire int64) error { + return c.c.Set(NewItem(key, []byte(com.ToStr(val)), int32(expire))) +} + +// Get gets cached value by given key. +func (c *MemcacheCacher) Get(key string) interface{} { + item, err := c.c.Get(key) + if err != nil { + return nil + } + return string(item.Value) +} + +// Delete deletes cached value by given key. +func (c *MemcacheCacher) Delete(key string) error { + return c.c.Delete(key) +} + +// Incr increases cached int-type value by given key as a counter. +func (c *MemcacheCacher) Incr(key string) error { + _, err := c.c.Increment(key, 1) + return err +} + +// Decr decreases cached int-type value by given key as a counter. +func (c *MemcacheCacher) Decr(key string) error { + _, err := c.c.Decrement(key, 1) + return err +} + +// IsExist returns true if cached value exists. +func (c *MemcacheCacher) IsExist(key string) bool { + _, err := c.c.Get(key) + return err == nil +} + +// Flush deletes all cached data. +func (c *MemcacheCacher) Flush() error { + return c.c.FlushAll() +} + +// StartAndGC starts GC routine based on config string settings. +// AdapterConfig: 127.0.0.1:9090;127.0.0.1:9091 +func (c *MemcacheCacher) StartAndGC(opt cache.Options) error { + c.c = memcache.New(strings.Split(opt.AdapterConfig, ";")...) + return nil +} + +func init() { + cache.Register("memcache", &MemcacheCacher{}) +} diff --git a/vendor/github.com/go-macaron/cache/memcache/memcache.goconvey b/vendor/github.com/go-macaron/cache/memcache/memcache.goconvey new file mode 100644 index 00000000..8485e986 --- /dev/null +++ b/vendor/github.com/go-macaron/cache/memcache/memcache.goconvey @@ -0,0 +1 @@ +ignore
\ No newline at end of file diff --git a/vendor/github.com/go-macaron/cache/memory.go b/vendor/github.com/go-macaron/cache/memory.go new file mode 100644 index 00000000..2d5a8fac --- /dev/null +++ b/vendor/github.com/go-macaron/cache/memory.go @@ -0,0 +1,179 @@ +// Copyright 2013 Beego Authors +// Copyright 2014 The Macaron Authors +// +// Licensed 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. + +package cache + +import ( + "errors" + "sync" + "time" +) + +// MemoryItem represents a memory cache item. +type MemoryItem struct { + val interface{} + created int64 + expire int64 +} + +func (item *MemoryItem) hasExpired() bool { + return item.expire > 0 && + (time.Now().Unix()-item.created) >= item.expire +} + +// MemoryCacher represents a memory cache adapter implementation. +type MemoryCacher struct { + lock sync.RWMutex + items map[string]*MemoryItem + interval int // GC interval. +} + +// NewMemoryCacher creates and returns a new memory cacher. +func NewMemoryCacher() *MemoryCacher { + return &MemoryCacher{items: make(map[string]*MemoryItem)} +} + +// Put puts value into cache with key and expire time. +// If expired is 0, it will be deleted by next GC operation. +func (c *MemoryCacher) Put(key string, val interface{}, expire int64) error { + c.lock.Lock() + defer c.lock.Unlock() + + c.items[key] = &MemoryItem{ + val: val, + created: time.Now().Unix(), + expire: expire, + } + return nil +} + +// Get gets cached value by given key. +func (c *MemoryCacher) Get(key string) interface{} { + c.lock.RLock() + defer c.lock.RUnlock() + + item, ok := c.items[key] + if !ok { + return nil + } + if item.hasExpired() { + go c.Delete(key) + return nil + } + return item.val +} + +// Delete deletes cached value by given key. +func (c *MemoryCacher) Delete(key string) error { + c.lock.Lock() + defer c.lock.Unlock() + + delete(c.items, key) + return nil +} + +// Incr increases cached int-type value by given key as a counter. +func (c *MemoryCacher) Incr(key string) (err error) { + c.lock.RLock() + defer c.lock.RUnlock() + + item, ok := c.items[key] + if !ok { + return errors.New("key not exist") + } + item.val, err = Incr(item.val) + return err +} + +// Decr decreases cached int-type value by given key as a counter. +func (c *MemoryCacher) Decr(key string) (err error) { + c.lock.RLock() + defer c.lock.RUnlock() + + item, ok := c.items[key] + if !ok { + return errors.New("key not exist") + } + + item.val, err = Decr(item.val) + return err +} + +// IsExist returns true if cached value exists. +func (c *MemoryCacher) IsExist(key string) bool { + c.lock.RLock() + defer c.lock.RUnlock() + + _, ok := c.items[key] + return ok +} + +// Flush deletes all cached data. +func (c *MemoryCacher) Flush() error { + c.lock.Lock() + defer c.lock.Unlock() + + c.items = make(map[string]*MemoryItem) + return nil +} + +func (c *MemoryCacher) checkRawExpiration(key string) { + item, ok := c.items[key] + if !ok { + return + } + + if item.hasExpired() { + delete(c.items, key) + } +} + +func (c *MemoryCacher) checkExpiration(key string) { + c.lock.Lock() + defer c.lock.Unlock() + + c.checkRawExpiration(key) +} + +func (c *MemoryCacher) startGC() { + c.lock.Lock() + defer c.lock.Unlock() + + if c.interval < 1 { + return + } + + if c.items != nil { + for key, _ := range c.items { + c.checkRawExpiration(key) + } + } + + time.AfterFunc(time.Duration(c.interval)*time.Second, func() { c.startGC() }) +} + +// StartAndGC starts GC routine based on config string settings. +func (c *MemoryCacher) StartAndGC(opt Options) error { + c.lock.Lock() + c.interval = opt.Interval + c.lock.Unlock() + + go c.startGC() + return nil +} + +func init() { + Register("memory", NewMemoryCacher()) +} diff --git a/vendor/github.com/go-macaron/cache/redis/redis.go b/vendor/github.com/go-macaron/cache/redis/redis.go new file mode 100644 index 00000000..5b59fbd2 --- /dev/null +++ b/vendor/github.com/go-macaron/cache/redis/redis.go @@ -0,0 +1,178 @@ +// Copyright 2013 Beego Authors +// Copyright 2014 The Macaron Authors +// +// Licensed 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. + +package cache + +import ( + "fmt" + "strings" + "time" + + "github.com/Unknwon/com" + "gopkg.in/ini.v1" + "gopkg.in/redis.v2" + + "github.com/go-macaron/cache" +) + +// RedisCacher represents a redis cache adapter implementation. +type RedisCacher struct { + c *redis.Client + prefix string + hsetName string + occupyMode bool +} + +// Put puts value into cache with key and expire time. +// If expired is 0, it lives forever. +func (c *RedisCacher) Put(key string, val interface{}, expire int64) error { + key = c.prefix + key + if expire == 0 { + if err := c.c.Set(key, com.ToStr(val)).Err(); err != nil { + return err + } + } else { + dur, err := time.ParseDuration(com.ToStr(expire) + "s") + if err != nil { + return err + } + if err = c.c.SetEx(key, dur, com.ToStr(val)).Err(); err != nil { + return err + } + } + + if c.occupyMode { + return nil + } + return c.c.HSet(c.hsetName, key, "0").Err() +} + +// Get gets cached value by given key. +func (c *RedisCacher) Get(key string) interface{} { + val, err := c.c.Get(c.prefix + key).Result() + if err != nil { + return nil + } + return val +} + +// Delete deletes cached value by given key. +func (c *RedisCacher) Delete(key string) error { + key = c.prefix + key + if err := c.c.Del(key).Err(); err != nil { + return err + } + + if c.occupyMode { + return nil + } + return c.c.HDel(c.hsetName, key).Err() +} + +// Incr increases cached int-type value by given key as a counter. +func (c *RedisCacher) Incr(key string) error { + if !c.IsExist(key) { + return fmt.Errorf("key '%s' not exist", key) + } + return c.c.Incr(c.prefix + key).Err() +} + +// Decr decreases cached int-type value by given key as a counter. +func (c *RedisCacher) Decr(key string) error { + if !c.IsExist(key) { + return fmt.Errorf("key '%s' not exist", key) + } + return c.c.Decr(c.prefix + key).Err() +} + +// IsExist returns true if cached value exists. +func (c *RedisCacher) IsExist(key string) bool { + if c.c.Exists(c.prefix + key).Val() { + return true + } + + if !c.occupyMode { + c.c.HDel(c.hsetName, c.prefix+key) + } + return false +} + +// Flush deletes all cached data. +func (c *RedisCacher) Flush() error { + if c.occupyMode { + return c.c.FlushDb().Err() + } + + keys, err := c.c.HKeys(c.hsetName).Result() + if err != nil { + return err + } + if err = c.c.Del(keys...).Err(); err != nil { + return err + } + return c.c.Del(c.hsetName).Err() +} + +// StartAndGC starts GC routine based on config string settings. +// AdapterConfig: network=tcp,addr=:6379,password=macaron,db=0,pool_size=100,idle_timeout=180,hset_name=MacaronCache,prefix=cache: +func (c *RedisCacher) StartAndGC(opts cache.Options) error { + c.hsetName = "MacaronCache" + c.occupyMode = opts.OccupyMode + + cfg, err := ini.Load([]byte(strings.Replace(opts.AdapterConfig, ",", "\n", -1))) + if err != nil { + return err + } + + opt := &redis.Options{ + Network: "tcp", + } + for k, v := range cfg.Section("").KeysHash() { + switch k { + case "network": + opt.Network = v + case "addr": + opt.Addr = v + case "password": + opt.Password = v + case "db": + opt.DB = com.StrTo(v).MustInt64() + case "pool_size": + opt.PoolSize = com.StrTo(v).MustInt() + case "idle_timeout": + opt.IdleTimeout, err = time.ParseDuration(v + "s") + if err != nil { + return fmt.Errorf("error parsing idle timeout: %v", err) + } + case "hset_name": + c.hsetName = v + case "prefix": + c.prefix = v + default: + return fmt.Errorf("session/redis: unsupported option '%s'", k) + } + } + + c.c = redis.NewClient(opt) + if err = c.c.Ping().Err(); err != nil { + return err + } + + return nil +} + +func init() { + cache.Register("redis", &RedisCacher{}) +} diff --git a/vendor/github.com/go-macaron/cache/redis/redis.goconvey b/vendor/github.com/go-macaron/cache/redis/redis.goconvey new file mode 100644 index 00000000..8485e986 --- /dev/null +++ b/vendor/github.com/go-macaron/cache/redis/redis.goconvey @@ -0,0 +1 @@ +ignore
\ No newline at end of file diff --git a/vendor/github.com/go-macaron/cache/utils.go b/vendor/github.com/go-macaron/cache/utils.go new file mode 100644 index 00000000..734fb6f4 --- /dev/null +++ b/vendor/github.com/go-macaron/cache/utils.go @@ -0,0 +1,84 @@ +// Copyright 2014 The Macaron Authors +// +// Licensed 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. + +package cache + +import ( + "bytes" + "encoding/gob" + "errors" +) + +func EncodeGob(item *Item) ([]byte, error) { + buf := bytes.NewBuffer(nil) + err := gob.NewEncoder(buf).Encode(item) + return buf.Bytes(), err +} + +func DecodeGob(data []byte, out *Item) error { + buf := bytes.NewBuffer(data) + return gob.NewDecoder(buf).Decode(&out) +} + +func Incr(val interface{}) (interface{}, error) { + switch val.(type) { + case int: + val = val.(int) + 1 + case int32: + val = val.(int32) + 1 + case int64: + val = val.(int64) + 1 + case uint: + val = val.(uint) + 1 + case uint32: + val = val.(uint32) + 1 + case uint64: + val = val.(uint64) + 1 + default: + return val, errors.New("item value is not int-type") + } + return val, nil +} + +func Decr(val interface{}) (interface{}, error) { + switch val.(type) { + case int: + val = val.(int) - 1 + case int32: + val = val.(int32) - 1 + case int64: + val = val.(int64) - 1 + case uint: + if val.(uint) > 0 { + val = val.(uint) - 1 + } else { + return val, errors.New("item value is less than 0") + } + case uint32: + if val.(uint32) > 0 { + val = val.(uint32) - 1 + } else { + return val, errors.New("item value is less than 0") + } + case uint64: + if val.(uint64) > 0 { + val = val.(uint64) - 1 + } else { + return val, errors.New("item value is less than 0") + } + default: + return val, errors.New("item value is not int-type") + } + return val, nil +} |