OLD | NEW |
1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 package dscache | 5 package dscache |
6 | 6 |
7 import ( | 7 import ( |
8 "bytes" | 8 "bytes" |
9 "crypto/sha1" | 9 "crypto/sha1" |
10 "encoding/base64" | 10 "encoding/base64" |
(...skipping 20 matching lines...) Expand all Loading... |
31 // infinite. This is #seconds instead of time.Duration, because memcache | 31 // infinite. This is #seconds instead of time.Duration, because memcache |
32 // truncates expiration to the second, which means a sub-second amount w
ould | 32 // truncates expiration to the second, which means a sub-second amount w
ould |
33 // actually truncate to an infinite timeout. | 33 // actually truncate to an infinite timeout. |
34 CacheTimeSeconds = int64((time.Hour * 24).Seconds()) | 34 CacheTimeSeconds = int64((time.Hour * 24).Seconds()) |
35 | 35 |
36 // CompressionThreshold is the number of bytes of entity value after whi
ch | 36 // CompressionThreshold is the number of bytes of entity value after whi
ch |
37 // compression kicks in. | 37 // compression kicks in. |
38 CompressionThreshold = 860 | 38 CompressionThreshold = 860 |
39 | 39 |
40 // DefaultShards is the default number of key sharding to do. | 40 // DefaultShards is the default number of key sharding to do. |
41 » DefaultShards int = 1 | 41 » DefaultShards = 1 |
42 | 42 |
43 » // DefaultEnable indicates whether or not caching is globally enabled or | 43 » // DefaultEnabled indicates whether or not caching is globally enabled o
r |
44 // disabled by default. Can still be overridden by CacheEnableMeta. | 44 // disabled by default. Can still be overridden by CacheEnableMeta. |
45 DefaultEnabled = true | 45 DefaultEnabled = true |
46 ) | 46 ) |
47 | 47 |
48 const ( | 48 const ( |
| 49 // MemcacheVersion will be incremented in the event that the in-memcache |
| 50 // representation of the cache data is modified. |
49 MemcacheVersion = "1" | 51 MemcacheVersion = "1" |
50 | 52 |
51 // KeyFormat is the format string used to generate memcache keys. It's | 53 // KeyFormat is the format string used to generate memcache keys. It's |
52 // gae:<version>:<shard#>:<base64_std_nopad(sha1(datastore.Key))> | 54 // gae:<version>:<shard#>:<base64_std_nopad(sha1(datastore.Key))> |
53 » KeyFormat = "gae:" + MemcacheVersion + ":%x:%s" | 55 » KeyFormat = "gae:" + MemcacheVersion + ":%x:%s" |
| 56 |
| 57 » // Sha1B64Padding is the number of padding characters a base64 encoding
of |
| 58 » // a sha1 has. |
54 Sha1B64Padding = 1 | 59 Sha1B64Padding = 1 |
55 Sha1B64Size = 28 - Sha1B64Padding | |
56 | 60 |
57 » MaxShards = 256 | 61 » // MaxShards is the maximum number of shards a single entity can have. |
58 » MaxShardsLen = len("ff") | 62 » MaxShards = 256 |
| 63 |
| 64 » // MaxShardsLen is the number of characters in the key the shard field |
| 65 » // occupies. |
| 66 » MaxShardsLen = len("ff") |
| 67 |
| 68 » // InternalGAEPadding is the estimated internal padding size that GAE ta
kes |
| 69 » // per memcache line. |
| 70 » // https://cloud.google.com/appengine/docs/go/memcache/#Go_Limits |
59 InternalGAEPadding = 96 | 71 InternalGAEPadding = 96 |
60 ValueSizeLimit = (1000 * 1000) - InternalGAEPadding - MaxShardsLen | |
61 | 72 |
62 » CacheEnableMeta = "dscache.enable" | 73 » // ValueSizeLimit is the maximum encoded size a datastore key+entry may |
| 74 » // occupy. If a datastore entity is too large, it will have an indefinit
e |
| 75 » // lock which will cause all clients to fetch it from the datastore. |
| 76 » ValueSizeLimit = (1000 * 1000) - InternalGAEPadding - MaxShardsLen |
| 77 |
| 78 » // CacheEnableMeta is the gae metadata key name for whether or not dscac
he |
| 79 » // is enabled for an entity type at all. |
| 80 » CacheEnableMeta = "dscache.enable" |
| 81 |
| 82 » // CacheExpirationMeta is the gae metadata key name for the default |
| 83 » // expiration time (in seconds) for an entity type. |
63 CacheExpirationMeta = "dscache.expiration" | 84 CacheExpirationMeta = "dscache.expiration" |
64 | 85 |
65 // NonceUint32s is the number of 32 bit uints to use in the 'lock' nonce
. | 86 // NonceUint32s is the number of 32 bit uints to use in the 'lock' nonce
. |
66 NonceUint32s = 2 | 87 NonceUint32s = 2 |
67 | 88 |
68 // GlobalEnabledCheckInterval is how frequently IsGloballyEnabled should
check | 89 // GlobalEnabledCheckInterval is how frequently IsGloballyEnabled should
check |
69 // the globalEnabled datastore entry. | 90 // the globalEnabled datastore entry. |
70 GlobalEnabledCheckInterval = 5 * time.Minute | 91 GlobalEnabledCheckInterval = 5 * time.Minute |
71 ) | 92 ) |
72 | 93 |
73 // internalValueSizeLimit is a var for testing purposes. | 94 // internalValueSizeLimit is a var for testing purposes. |
74 var internalValueSizeLimit = ValueSizeLimit | 95 var internalValueSizeLimit = ValueSizeLimit |
75 | 96 |
| 97 // CompressionType is the type of compression a single memcache entry has. |
76 type CompressionType byte | 98 type CompressionType byte |
77 | 99 |
| 100 // Types of compression. ZlibCompression uses "compress/zlib". |
78 const ( | 101 const ( |
79 NoCompression CompressionType = iota | 102 NoCompression CompressionType = iota |
80 ZlibCompression | 103 ZlibCompression |
81 ) | 104 ) |
82 | 105 |
83 func (c CompressionType) String() string { | 106 func (c CompressionType) String() string { |
84 switch c { | 107 switch c { |
85 case NoCompression: | 108 case NoCompression: |
86 return "NoCompression" | 109 return "NoCompression" |
87 case ZlibCompression: | 110 case ZlibCompression: |
88 return "ZlibCompression" | 111 return "ZlibCompression" |
89 default: | 112 default: |
90 return fmt.Sprintf("UNKNOWN_CompressionType(%d)", c) | 113 return fmt.Sprintf("UNKNOWN_CompressionType(%d)", c) |
91 } | 114 } |
92 } | 115 } |
93 | 116 |
94 // FlagValue is used to indicate if a memcache entry currently contains an | 117 // FlagValue is used to indicate if a memcache entry currently contains an |
95 // item or a lock. | 118 // item or a lock. |
96 type FlagValue uint32 | 119 type FlagValue uint32 |
97 | 120 |
| 121 // States for a memcache entry. ItemUNKNOWN exists to distinguish the default |
| 122 // zero state from a valid state, but shouldn't ever be observed in memcache. . |
98 const ( | 123 const ( |
99 ItemUKNONWN FlagValue = iota | 124 ItemUKNONWN FlagValue = iota |
100 ItemHasData | 125 ItemHasData |
101 ItemHasLock | 126 ItemHasLock |
102 ) | 127 ) |
103 | 128 |
104 func MakeMemcacheKey(shard int, k datastore.Key) string { | 129 // MakeMemcacheKey generates a memcache key for the given datastore Key. This |
| 130 // is useful for debugging. |
| 131 func MakeMemcacheKey(shard int, k *datastore.Key) string { |
105 return fmt.Sprintf(KeyFormat, shard, HashKey(k)) | 132 return fmt.Sprintf(KeyFormat, shard, HashKey(k)) |
106 } | 133 } |
107 | 134 |
108 func HashKey(k datastore.Key) string { | 135 // HashKey generates just the hashed portion of the MemcacheKey. |
| 136 func HashKey(k *datastore.Key) string { |
109 dgst := sha1.Sum(serialize.ToBytes(k)) | 137 dgst := sha1.Sum(serialize.ToBytes(k)) |
110 buf := bytes.Buffer{} | 138 buf := bytes.Buffer{} |
111 enc := base64.NewEncoder(base64.StdEncoding, &buf) | 139 enc := base64.NewEncoder(base64.StdEncoding, &buf) |
112 _, _ = enc.Write(dgst[:]) | 140 _, _ = enc.Write(dgst[:]) |
113 enc.Close() | 141 enc.Close() |
114 return buf.String()[:buf.Len()-Sha1B64Padding] | 142 return buf.String()[:buf.Len()-Sha1B64Padding] |
115 } | 143 } |
OLD | NEW |