Use the same workspace URI in Executor.__init__ (#443)

* Make sure we're using the same workspace

* create_store -> fromdescriptor

* classmethod -> cls variable

* Cache descriptor name

* join -> format

* Update Store docs
This commit is contained in:
Yan
2017-08-10 15:07:53 -04:00
committed by GitHub
parent e78ae8904e
commit 36a58810f9
2 changed files with 51 additions and 31 deletions

View File

@@ -53,12 +53,35 @@ class PickleSerializer(StateSerializer):
class Store(object):
"""
A Store can save arbitrary keys/values (including states) and file streams. Used for generating
output, and state saving and loading.
A `Store` can save arbitrary keys/values (including states) and file streams.
Used for generating output, state saving and state loading.
Implement either save_value/load_value in subclasses, or save_stream/load_stream, or both.
In subclasses:
* Implement either save_value/load_value, or save_stream/load_stream, or both.
* Define a `store_type` class variable of type str.
* This is used as a prefix for a store descriptor
"""
@classmethod
def fromdescriptor(cls, desc):
"""
Create a :class:`~manticore.core.workspace.Store` instance depending on the descriptor.
Valid descriptors:
* fs:<path>
* redis:<hostname>:<port>
* mem:
:param str desc: Store descriptor
:return: Store instance
"""
type_, uri = ('fs', None) if desc is None else desc.split(':', 1)
for subclass in cls.__subclasses__():
if subclass.store_type == type_:
return subclass(uri)
raise NotImplementedError("Storage type '{0}' not supported.".format(type_))
def __init__(self, uri, state_serialization_method='pickle'):
assert self.__class__ != Store, "The Store class can not be instantiated (create a subclass)"
@@ -162,6 +185,8 @@ class FilesystemStore(Store):
"""
A directory-backed Manticore workspace
"""
store_type = 'fs'
def __init__(self, uri=None):
"""
:param uri: The path to on-disk workspace, or None.
@@ -225,11 +250,12 @@ class MemoryStore(Store):
NOTE: This is mostly used for experimentation and testing funcionality.
Can not be used with multiple workers!
"""
store_type = 'mem'
#TODO(yan): Once we get a global config store, check it to make sure
# we're executing in a single-worker or test environment.
def __init__(self):
def __init__(self, uri=None):
self._data = {}
super(MemoryStore, self).__init__(None)
@@ -249,6 +275,8 @@ class RedisStore(Store):
"""
A redis-backed Manticore workspace
"""
store_type = 'redis'
def __init__(self, uri=None):
"""
:param uri: A url for redis
@@ -288,30 +316,6 @@ class RedisStore(Store):
return self._client.keys(glob_str)
def _create_store(desc):
"""
Create a :class:`~manticore.core.workspace.Store` instance depending on the descriptor.
Valid descriptors:
fs:<path>
redis:<hostname>:<port>
mem:
:param str desc: Store descriptor
:return: Store instance
"""
type_, uri = ('fs', None) if desc is None else desc.split(':', 1)
if type_ == 'fs':
return FilesystemStore(uri)
elif type_ == 'redis':
return RedisStore(uri)
elif type_ == 'mem':
return MemoryStore()
else:
raise NotImplementedError("Storage type '{0}' not supported.".format(type_))
# This is copied from Executor to not create a dependency on the naming of the lock field
def sync(f):
""" Synchronization decorator. """
@@ -330,7 +334,7 @@ class Workspace(object):
"""
def __init__(self, lock, desc=None):
self._store = _create_store(desc)
self._store = Store.fromdescriptor(desc)
self._serializer = PickleSerializer()
self._last_id = manager.Value('i', 0)
self._lock = lock
@@ -401,7 +405,8 @@ class ManticoreOutput(object):
:param desc: A descriptor ('type:uri') of where to write output.
"""
self._named_key_prefix = 'test'
self._store = _create_store(desc)
self._descriptor = desc
self._store = Store.fromdescriptor(desc)
self._last_id = 0
self._id_gen = manager.Value('i', self._last_id)
self._lock = manager.Condition(manager.RLock())
@@ -410,6 +415,21 @@ class ManticoreOutput(object):
def uri(self):
return self._store.uri
@property
def descriptor(self):
"""
Return a descriptor that created this workspace. Descriptors are of the
format <type>:<uri>, where type signifies the medium. For example,
fs:/tmp/workspace
redis:127.0.0.1:6379
:rtype: str
"""
if self._descriptor is None:
self._descriptor = '{}:{}'.format(self._store.store_type, self._store.uri)
return self._descriptor
@sync
def _increment_id(self):
self._last_id = self._id_gen.value

View File

@@ -708,7 +708,7 @@ class Manticore(object):
self._output = ManticoreOutput(ws_path)
self._executor = Executor(initial_state,
workspace=ws_path,
workspace=self._output.descriptor,
policy=self._policy,
context=self.context)