key.go 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400
  1. // Copyright 2011 Google Inc. All rights reserved.
  2. // Use of this source code is governed by the Apache 2.0
  3. // license that can be found in the LICENSE file.
  4. package datastore
  5. import (
  6. "bytes"
  7. "context"
  8. "encoding/base64"
  9. "encoding/gob"
  10. "errors"
  11. "fmt"
  12. "strconv"
  13. "strings"
  14. "github.com/golang/protobuf/proto"
  15. "google.golang.org/appengine/internal"
  16. pb "google.golang.org/appengine/internal/datastore"
  17. )
  18. type KeyRangeCollisionError struct {
  19. start int64
  20. end int64
  21. }
  22. func (e *KeyRangeCollisionError) Error() string {
  23. return fmt.Sprintf("datastore: Collision when attempting to allocate range [%d, %d]",
  24. e.start, e.end)
  25. }
  26. type KeyRangeContentionError struct {
  27. start int64
  28. end int64
  29. }
  30. func (e *KeyRangeContentionError) Error() string {
  31. return fmt.Sprintf("datastore: Contention when attempting to allocate range [%d, %d]",
  32. e.start, e.end)
  33. }
  34. // Key represents the datastore key for a stored entity, and is immutable.
  35. type Key struct {
  36. kind string
  37. stringID string
  38. intID int64
  39. parent *Key
  40. appID string
  41. namespace string
  42. }
  43. // Kind returns the key's kind (also known as entity type).
  44. func (k *Key) Kind() string {
  45. return k.kind
  46. }
  47. // StringID returns the key's string ID (also known as an entity name or key
  48. // name), which may be "".
  49. func (k *Key) StringID() string {
  50. return k.stringID
  51. }
  52. // IntID returns the key's integer ID, which may be 0.
  53. func (k *Key) IntID() int64 {
  54. return k.intID
  55. }
  56. // Parent returns the key's parent key, which may be nil.
  57. func (k *Key) Parent() *Key {
  58. return k.parent
  59. }
  60. // AppID returns the key's application ID.
  61. func (k *Key) AppID() string {
  62. return k.appID
  63. }
  64. // Namespace returns the key's namespace.
  65. func (k *Key) Namespace() string {
  66. return k.namespace
  67. }
  68. // Incomplete returns whether the key does not refer to a stored entity.
  69. // In particular, whether the key has a zero StringID and a zero IntID.
  70. func (k *Key) Incomplete() bool {
  71. return k.stringID == "" && k.intID == 0
  72. }
  73. // valid returns whether the key is valid.
  74. func (k *Key) valid() bool {
  75. if k == nil {
  76. return false
  77. }
  78. for ; k != nil; k = k.parent {
  79. if k.kind == "" || k.appID == "" {
  80. return false
  81. }
  82. if k.stringID != "" && k.intID != 0 {
  83. return false
  84. }
  85. if k.parent != nil {
  86. if k.parent.Incomplete() {
  87. return false
  88. }
  89. if k.parent.appID != k.appID || k.parent.namespace != k.namespace {
  90. return false
  91. }
  92. }
  93. }
  94. return true
  95. }
  96. // Equal returns whether two keys are equal.
  97. func (k *Key) Equal(o *Key) bool {
  98. for k != nil && o != nil {
  99. if k.kind != o.kind || k.stringID != o.stringID || k.intID != o.intID || k.appID != o.appID || k.namespace != o.namespace {
  100. return false
  101. }
  102. k, o = k.parent, o.parent
  103. }
  104. return k == o
  105. }
  106. // root returns the furthest ancestor of a key, which may be itself.
  107. func (k *Key) root() *Key {
  108. for k.parent != nil {
  109. k = k.parent
  110. }
  111. return k
  112. }
  113. // marshal marshals the key's string representation to the buffer.
  114. func (k *Key) marshal(b *bytes.Buffer) {
  115. if k.parent != nil {
  116. k.parent.marshal(b)
  117. }
  118. b.WriteByte('/')
  119. b.WriteString(k.kind)
  120. b.WriteByte(',')
  121. if k.stringID != "" {
  122. b.WriteString(k.stringID)
  123. } else {
  124. b.WriteString(strconv.FormatInt(k.intID, 10))
  125. }
  126. }
  127. // String returns a string representation of the key.
  128. func (k *Key) String() string {
  129. if k == nil {
  130. return ""
  131. }
  132. b := bytes.NewBuffer(make([]byte, 0, 512))
  133. k.marshal(b)
  134. return b.String()
  135. }
  136. type gobKey struct {
  137. Kind string
  138. StringID string
  139. IntID int64
  140. Parent *gobKey
  141. AppID string
  142. Namespace string
  143. }
  144. func keyToGobKey(k *Key) *gobKey {
  145. if k == nil {
  146. return nil
  147. }
  148. return &gobKey{
  149. Kind: k.kind,
  150. StringID: k.stringID,
  151. IntID: k.intID,
  152. Parent: keyToGobKey(k.parent),
  153. AppID: k.appID,
  154. Namespace: k.namespace,
  155. }
  156. }
  157. func gobKeyToKey(gk *gobKey) *Key {
  158. if gk == nil {
  159. return nil
  160. }
  161. return &Key{
  162. kind: gk.Kind,
  163. stringID: gk.StringID,
  164. intID: gk.IntID,
  165. parent: gobKeyToKey(gk.Parent),
  166. appID: gk.AppID,
  167. namespace: gk.Namespace,
  168. }
  169. }
  170. func (k *Key) GobEncode() ([]byte, error) {
  171. buf := new(bytes.Buffer)
  172. if err := gob.NewEncoder(buf).Encode(keyToGobKey(k)); err != nil {
  173. return nil, err
  174. }
  175. return buf.Bytes(), nil
  176. }
  177. func (k *Key) GobDecode(buf []byte) error {
  178. gk := new(gobKey)
  179. if err := gob.NewDecoder(bytes.NewBuffer(buf)).Decode(gk); err != nil {
  180. return err
  181. }
  182. *k = *gobKeyToKey(gk)
  183. return nil
  184. }
  185. func (k *Key) MarshalJSON() ([]byte, error) {
  186. return []byte(`"` + k.Encode() + `"`), nil
  187. }
  188. func (k *Key) UnmarshalJSON(buf []byte) error {
  189. if len(buf) < 2 || buf[0] != '"' || buf[len(buf)-1] != '"' {
  190. return errors.New("datastore: bad JSON key")
  191. }
  192. k2, err := DecodeKey(string(buf[1 : len(buf)-1]))
  193. if err != nil {
  194. return err
  195. }
  196. *k = *k2
  197. return nil
  198. }
  199. // Encode returns an opaque representation of the key
  200. // suitable for use in HTML and URLs.
  201. // This is compatible with the Python and Java runtimes.
  202. func (k *Key) Encode() string {
  203. ref := keyToProto("", k)
  204. b, err := proto.Marshal(ref)
  205. if err != nil {
  206. panic(err)
  207. }
  208. // Trailing padding is stripped.
  209. return strings.TrimRight(base64.URLEncoding.EncodeToString(b), "=")
  210. }
  211. // DecodeKey decodes a key from the opaque representation returned by Encode.
  212. func DecodeKey(encoded string) (*Key, error) {
  213. // Re-add padding.
  214. if m := len(encoded) % 4; m != 0 {
  215. encoded += strings.Repeat("=", 4-m)
  216. }
  217. b, err := base64.URLEncoding.DecodeString(encoded)
  218. if err != nil {
  219. return nil, err
  220. }
  221. ref := new(pb.Reference)
  222. if err := proto.Unmarshal(b, ref); err != nil {
  223. // Couldn't decode it as an App Engine key, try decoding it as a key encoded by cloud.google.com/go/datastore.
  224. if k := decodeCloudKey(encoded); k != nil {
  225. return k, nil
  226. }
  227. return nil, err
  228. }
  229. return protoToKey(ref)
  230. }
  231. // NewIncompleteKey creates a new incomplete key.
  232. // kind cannot be empty.
  233. func NewIncompleteKey(c context.Context, kind string, parent *Key) *Key {
  234. return NewKey(c, kind, "", 0, parent)
  235. }
  236. // NewKey creates a new key.
  237. // kind cannot be empty.
  238. // Either one or both of stringID and intID must be zero. If both are zero,
  239. // the key returned is incomplete.
  240. // parent must either be a complete key or nil.
  241. func NewKey(c context.Context, kind, stringID string, intID int64, parent *Key) *Key {
  242. // If there's a parent key, use its namespace.
  243. // Otherwise, use any namespace attached to the context.
  244. var namespace string
  245. if parent != nil {
  246. namespace = parent.namespace
  247. } else {
  248. namespace = internal.NamespaceFromContext(c)
  249. }
  250. return &Key{
  251. kind: kind,
  252. stringID: stringID,
  253. intID: intID,
  254. parent: parent,
  255. appID: internal.FullyQualifiedAppID(c),
  256. namespace: namespace,
  257. }
  258. }
  259. // AllocateIDs returns a range of n integer IDs with the given kind and parent
  260. // combination. kind cannot be empty; parent may be nil. The IDs in the range
  261. // returned will not be used by the datastore's automatic ID sequence generator
  262. // and may be used with NewKey without conflict.
  263. //
  264. // The range is inclusive at the low end and exclusive at the high end. In
  265. // other words, valid intIDs x satisfy low <= x && x < high.
  266. //
  267. // If no error is returned, low + n == high.
  268. func AllocateIDs(c context.Context, kind string, parent *Key, n int) (low, high int64, err error) {
  269. if kind == "" {
  270. return 0, 0, errors.New("datastore: AllocateIDs given an empty kind")
  271. }
  272. if n < 0 {
  273. return 0, 0, fmt.Errorf("datastore: AllocateIDs given a negative count: %d", n)
  274. }
  275. if n == 0 {
  276. return 0, 0, nil
  277. }
  278. req := &pb.AllocateIdsRequest{
  279. ModelKey: keyToProto("", NewIncompleteKey(c, kind, parent)),
  280. Size: proto.Int64(int64(n)),
  281. }
  282. res := &pb.AllocateIdsResponse{}
  283. if err := internal.Call(c, "datastore_v3", "AllocateIds", req, res); err != nil {
  284. return 0, 0, err
  285. }
  286. // The protobuf is inclusive at both ends. Idiomatic Go (e.g. slices, for loops)
  287. // is inclusive at the low end and exclusive at the high end, so we add 1.
  288. low = res.GetStart()
  289. high = res.GetEnd() + 1
  290. if low+int64(n) != high {
  291. return 0, 0, fmt.Errorf("datastore: internal error: could not allocate %d IDs", n)
  292. }
  293. return low, high, nil
  294. }
  295. // AllocateIDRange allocates a range of IDs with specific endpoints.
  296. // The range is inclusive at both the low and high end. Once these IDs have been
  297. // allocated, you can manually assign them to newly created entities.
  298. //
  299. // The Datastore's automatic ID allocator never assigns a key that has already
  300. // been allocated (either through automatic ID allocation or through an explicit
  301. // AllocateIDs call). As a result, entities written to the given key range will
  302. // never be overwritten. However, writing entities with manually assigned keys in
  303. // this range may overwrite existing entities (or new entities written by a separate
  304. // request), depending on the error returned.
  305. //
  306. // Use this only if you have an existing numeric ID range that you want to reserve
  307. // (for example, bulk loading entities that already have IDs). If you don't care
  308. // about which IDs you receive, use AllocateIDs instead.
  309. //
  310. // AllocateIDRange returns nil if the range is successfully allocated. If one or more
  311. // entities with an ID in the given range already exist, it returns a KeyRangeCollisionError.
  312. // If the Datastore has already cached IDs in this range (e.g. from a previous call to
  313. // AllocateIDRange), it returns a KeyRangeContentionError. Errors of other types indicate
  314. // problems with arguments or an error returned directly from the Datastore.
  315. func AllocateIDRange(c context.Context, kind string, parent *Key, start, end int64) (err error) {
  316. if kind == "" {
  317. return errors.New("datastore: AllocateIDRange given an empty kind")
  318. }
  319. if start < 1 || end < 1 {
  320. return errors.New("datastore: AllocateIDRange start and end must both be greater than 0")
  321. }
  322. if start > end {
  323. return errors.New("datastore: AllocateIDRange start must be before end")
  324. }
  325. req := &pb.AllocateIdsRequest{
  326. ModelKey: keyToProto("", NewIncompleteKey(c, kind, parent)),
  327. Max: proto.Int64(end),
  328. }
  329. res := &pb.AllocateIdsResponse{}
  330. if err := internal.Call(c, "datastore_v3", "AllocateIds", req, res); err != nil {
  331. return err
  332. }
  333. // Check for collisions, i.e. existing entities with IDs in this range.
  334. // We could do this before the allocation, but we'd still have to do it
  335. // afterward as well to catch the race condition where an entity is inserted
  336. // after that initial check but before the allocation. Skip the up-front check
  337. // and just do it once.
  338. q := NewQuery(kind).Filter("__key__ >=", NewKey(c, kind, "", start, parent)).
  339. Filter("__key__ <=", NewKey(c, kind, "", end, parent)).KeysOnly().Limit(1)
  340. keys, err := q.GetAll(c, nil)
  341. if err != nil {
  342. return err
  343. }
  344. if len(keys) != 0 {
  345. return &KeyRangeCollisionError{start: start, end: end}
  346. }
  347. // Check for a race condition, i.e. cases where the datastore may have
  348. // cached ID batches that contain IDs in this range.
  349. if start < res.GetStart() {
  350. return &KeyRangeContentionError{start: start, end: end}
  351. }
  352. return nil
  353. }