mirror of
https://github.com/thegeeklab/ansible-later.git
synced 2024-11-26 23:00:36 +00:00
113 lines
3.4 KiB
Python
113 lines
3.4 KiB
Python
|
# Copyright (C) 2010, 2011 Sebastian Thiel (byronimo@gmail.com) and contributors
|
||
|
#
|
||
|
# This module is part of GitDB and is released under
|
||
|
# the New BSD License: http://www.opensource.org/licenses/bsd-license.php
|
||
|
"""Contains the MemoryDatabase implementation"""
|
||
|
from gitdb.db.loose import LooseObjectDB
|
||
|
from gitdb.db.base import (
|
||
|
ObjectDBR,
|
||
|
ObjectDBW
|
||
|
)
|
||
|
|
||
|
from gitdb.base import (
|
||
|
OStream,
|
||
|
IStream,
|
||
|
)
|
||
|
|
||
|
from gitdb.exc import (
|
||
|
BadObject,
|
||
|
UnsupportedOperation
|
||
|
)
|
||
|
|
||
|
from gitdb.stream import (
|
||
|
ZippedStoreShaWriter,
|
||
|
DecompressMemMapReader,
|
||
|
)
|
||
|
|
||
|
from io import BytesIO
|
||
|
|
||
|
__all__ = ("MemoryDB", )
|
||
|
|
||
|
|
||
|
class MemoryDB(ObjectDBR, ObjectDBW):
|
||
|
|
||
|
"""A memory database stores everything to memory, providing fast IO and object
|
||
|
retrieval. It should be used to buffer results and obtain SHAs before writing
|
||
|
it to the actual physical storage, as it allows to query whether object already
|
||
|
exists in the target storage before introducing actual IO"""
|
||
|
|
||
|
def __init__(self):
|
||
|
super(MemoryDB, self).__init__()
|
||
|
self._db = LooseObjectDB("path/doesnt/matter")
|
||
|
|
||
|
# maps 20 byte shas to their OStream objects
|
||
|
self._cache = dict()
|
||
|
|
||
|
def set_ostream(self, stream):
|
||
|
raise UnsupportedOperation("MemoryDB's always stream into memory")
|
||
|
|
||
|
def store(self, istream):
|
||
|
zstream = ZippedStoreShaWriter()
|
||
|
self._db.set_ostream(zstream)
|
||
|
|
||
|
istream = self._db.store(istream)
|
||
|
zstream.close() # close to flush
|
||
|
zstream.seek(0)
|
||
|
|
||
|
# don't provide a size, the stream is written in object format, hence the
|
||
|
# header needs decompression
|
||
|
decomp_stream = DecompressMemMapReader(zstream.getvalue(), close_on_deletion=False)
|
||
|
self._cache[istream.binsha] = OStream(istream.binsha, istream.type, istream.size, decomp_stream)
|
||
|
|
||
|
return istream
|
||
|
|
||
|
def has_object(self, sha):
|
||
|
return sha in self._cache
|
||
|
|
||
|
def info(self, sha):
|
||
|
# we always return streams, which are infos as well
|
||
|
return self.stream(sha)
|
||
|
|
||
|
def stream(self, sha):
|
||
|
try:
|
||
|
ostream = self._cache[sha]
|
||
|
# rewind stream for the next one to read
|
||
|
ostream.stream.seek(0)
|
||
|
return ostream
|
||
|
except KeyError:
|
||
|
raise BadObject(sha)
|
||
|
# END exception handling
|
||
|
|
||
|
def size(self):
|
||
|
return len(self._cache)
|
||
|
|
||
|
def sha_iter(self):
|
||
|
try:
|
||
|
return self._cache.iterkeys()
|
||
|
except AttributeError:
|
||
|
return self._cache.keys()
|
||
|
|
||
|
#{ Interface
|
||
|
def stream_copy(self, sha_iter, odb):
|
||
|
"""Copy the streams as identified by sha's yielded by sha_iter into the given odb
|
||
|
The streams will be copied directly
|
||
|
**Note:** the object will only be written if it did not exist in the target db
|
||
|
:return: amount of streams actually copied into odb. If smaller than the amount
|
||
|
of input shas, one or more objects did already exist in odb"""
|
||
|
count = 0
|
||
|
for sha in sha_iter:
|
||
|
if odb.has_object(sha):
|
||
|
continue
|
||
|
# END check object existence
|
||
|
|
||
|
ostream = self.stream(sha)
|
||
|
# compressed data including header
|
||
|
sio = BytesIO(ostream.stream.data())
|
||
|
istream = IStream(ostream.type, ostream.size, sio, sha)
|
||
|
|
||
|
odb.store(istream)
|
||
|
count += 1
|
||
|
# END for each sha
|
||
|
return count
|
||
|
#} END interface
|