1 # Copyright (c) 2012 The Chromium Authors. All rights reserved. 2 # Use of this source code is governed by a BSD-style license that can be 3 # found in the LICENSE file. 4 5 import blob_reference_store as datastore 6 from blob_reference_store import BlobReferenceStore 7 from appengine_wrappers import blobstore 8 from appengine_wrappers import files 9 10 BLOBSTORE_GITHUB = 'BlobstoreGithub' 11 12 # TODO(kalman): Re-write this class. 13 # - It uses BlobReader which is a synchronous method. We should be creating 14 # multiple async fetches, one for each partition, then exposing a Future 15 # interface which stitches them together. 16 # - It's very hard to reuse. 17 18 class AppEngineBlobstore(object): 19 """A wrapper around the blobstore API, which stores the blob keys in 20 datastore. 21 """ 22 def __init__(self): 23 self._datastore = BlobReferenceStore() 24 25 def Set(self, key, blob, namespace): 26 """Add a blob to the blobstore. |version| is used as part of the key so 27 multiple blobs with the same name can be differentiated. 28 """ 29 key = namespace + '.' + key 30 filename = files.blobstore.create() 31 with files.open(filename, 'a') as f: 32 f.write(blob) 33 files.finalize(filename) 34 blob_key = files.blobstore.get_blob_key(filename) 35 self._datastore.Set(datastore.BLOB_REFERENCE_BLOBSTORE, key, blob_key) 36 37 def Get(self, key, namespace): 38 """Get a blob with version |version|. 39 """ 40 key = namespace + '.' + key 41 blob_key = self._datastore.Get(datastore.BLOB_REFERENCE_BLOBSTORE, key) 42 if blob_key is None: 43 return None 44 blob_reader = blobstore.BlobReader(blob_key) 45 return blob_reader.read() 46 47 def Delete(self, key, namespace): 48 """Delete the blob with version |version| if it is found. 49 """ 50 key = namespace + '.' + key 51 blob_key = self._datastore.Delete(datastore.BLOB_REFERENCE_BLOBSTORE, key) 52 if blob_key is None: 53 return 54 blob_key.delete() 55