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:
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user