15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# Copyright (c) 2012 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import blob_reference_store as datastore 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)from blob_reference_store import BlobReferenceStore 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)from appengine_wrappers import blobstore 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)from appengine_wrappers import files 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)BLOBSTORE_GITHUB = 'BlobstoreGithub' 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)# TODO(kalman): Re-write this class. 13f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)# - It uses BlobReader which is a synchronous method. We should be creating 14f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)# multiple async fetches, one for each partition, then exposing a Future 15f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)# interface which stitches them together. 16f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)# - It's very hard to reuse. 17f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class AppEngineBlobstore(object): 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) """A wrapper around the blobstore API, which stores the blob keys in 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) datastore. 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) """ 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) def __init__(self): 23ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch self._datastore = BlobReferenceStore() 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) def Set(self, key, blob, namespace): 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) """Add a blob to the blobstore. |version| is used as part of the key so 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) multiple blobs with the same name can be differentiated. 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) """ 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) key = namespace + '.' + key 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) filename = files.blobstore.create() 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) with files.open(filename, 'a') as f: 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) f.write(blob) 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) files.finalize(filename) 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) blob_key = files.blobstore.get_blob_key(filename) 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) self._datastore.Set(datastore.BLOB_REFERENCE_BLOBSTORE, key, blob_key) 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) def Get(self, key, namespace): 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) """Get a blob with version |version|. 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) """ 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) key = namespace + '.' + key 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) blob_key = self._datastore.Get(datastore.BLOB_REFERENCE_BLOBSTORE, key) 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if blob_key is None: 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return None 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) blob_reader = blobstore.BlobReader(blob_key) 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return blob_reader.read() 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) def Delete(self, key, namespace): 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) """Delete the blob with version |version| if it is found. 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) """ 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) key = namespace + '.' + key 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) blob_key = self._datastore.Delete(datastore.BLOB_REFERENCE_BLOBSTORE, key) 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if blob_key is None: 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) blob_key.delete() 55