mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-09-26 02:07:36 +00:00
Implement batch transaction support. See #1475.
This commit is contained in:
@@ -39,6 +39,10 @@ class Transaction:
|
|||||||
def __init__(self, ifc_file):
|
def __init__(self, ifc_file):
|
||||||
self.file = ifc_file
|
self.file = ifc_file
|
||||||
self.operations = []
|
self.operations = []
|
||||||
|
self.is_batched = False
|
||||||
|
self.batch_delete_index = 0
|
||||||
|
self.batch_delete_ids = set()
|
||||||
|
self.batch_inverses = []
|
||||||
|
|
||||||
def serialise_entity_instance(self, element):
|
def serialise_entity_instance(self, element):
|
||||||
info = element.get_info()
|
info = element.get_info()
|
||||||
@@ -52,6 +56,21 @@ class Transaction:
|
|||||||
def unserialise_value(self, element, value):
|
def unserialise_value(self, element, value):
|
||||||
return element.walk(lambda v: isinstance(v, dict), lambda v: self.file.by_id(v["id"]), value)
|
return element.walk(lambda v: isinstance(v, dict), lambda v: self.file.by_id(v["id"]), value)
|
||||||
|
|
||||||
|
def batch(self):
|
||||||
|
self.is_batched = True
|
||||||
|
self.batch_delete_index = len(self.operations)
|
||||||
|
self.batch_delete_ids = set()
|
||||||
|
self.batch_inverses = []
|
||||||
|
|
||||||
|
def unbatch(self):
|
||||||
|
for inverses in self.batch_inverses:
|
||||||
|
if inverses:
|
||||||
|
self.operations.insert(self.batch_delete_index, {"action": "batch_delete", "inverses": inverses})
|
||||||
|
self.is_batched = False
|
||||||
|
self.batch_delete_index = 0
|
||||||
|
self.batch_delete_ids = set()
|
||||||
|
self.batch_inverses = []
|
||||||
|
|
||||||
def store_create(self, element):
|
def store_create(self, element):
|
||||||
self.operations.append({"action": "create", "value": self.serialise_entity_instance(element)})
|
self.operations.append({"action": "create", "value": self.serialise_entity_instance(element)})
|
||||||
|
|
||||||
@@ -67,6 +86,18 @@ class Transaction:
|
|||||||
)
|
)
|
||||||
|
|
||||||
def store_delete(self, element):
|
def store_delete(self, element):
|
||||||
|
inverses = {}
|
||||||
|
if self.is_batched:
|
||||||
|
if element.id() not in self.batch_delete_ids:
|
||||||
|
self.batch_inverses.append(self.get_element_inverses(element))
|
||||||
|
self.batch_delete_ids.add(element.id())
|
||||||
|
else:
|
||||||
|
inverses = self.get_element_inverses(element)
|
||||||
|
self.operations.append(
|
||||||
|
{"action": "delete", "inverses": inverses, "value": self.serialise_entity_instance(element)}
|
||||||
|
)
|
||||||
|
|
||||||
|
def get_element_inverses(self, element):
|
||||||
inverses = {}
|
inverses = {}
|
||||||
for inverse in self.file.get_inverse(element):
|
for inverse in self.file.get_inverse(element):
|
||||||
inverse_references = []
|
inverse_references = []
|
||||||
@@ -74,9 +105,7 @@ class Transaction:
|
|||||||
if self.has_element_reference(attribute, element):
|
if self.has_element_reference(attribute, element):
|
||||||
inverse_references.append((i, self.serialise_value(inverse, attribute)))
|
inverse_references.append((i, self.serialise_value(inverse, attribute)))
|
||||||
inverses[inverse.id()] = inverse_references
|
inverses[inverse.id()] = inverse_references
|
||||||
self.operations.append(
|
return inverses
|
||||||
{"action": "delete", "inverses": inverses, "value": self.serialise_entity_instance(element)}
|
|
||||||
)
|
|
||||||
|
|
||||||
def has_element_reference(self, value, element):
|
def has_element_reference(self, value, element):
|
||||||
if isinstance(value, (tuple, list)):
|
if isinstance(value, (tuple, list)):
|
||||||
@@ -111,6 +140,11 @@ class Transaction:
|
|||||||
inverse = self.file.by_id(inverse_id)
|
inverse = self.file.by_id(inverse_id)
|
||||||
for index, value in data:
|
for index, value in data:
|
||||||
inverse[index] = self.unserialise_value(inverse, value)
|
inverse[index] = self.unserialise_value(inverse, value)
|
||||||
|
elif operation["action"] == "batch_delete":
|
||||||
|
for inverse_id, data in operation["inverses"].items():
|
||||||
|
inverse = self.file.by_id(inverse_id)
|
||||||
|
for index, value in data:
|
||||||
|
inverse[index] = self.unserialise_value(inverse, value)
|
||||||
|
|
||||||
def commit(self):
|
def commit(self):
|
||||||
for operation in self.operations:
|
for operation in self.operations:
|
||||||
@@ -128,6 +162,8 @@ class Transaction:
|
|||||||
elif operation["action"] == "delete":
|
elif operation["action"] == "delete":
|
||||||
element = self.file.by_id(operation["value"]["id"])
|
element = self.file.by_id(operation["value"]["id"])
|
||||||
self.file.remove(element)
|
self.file.remove(element)
|
||||||
|
elif operation["action"] == "batch_delete":
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
class file(object):
|
class file(object):
|
||||||
@@ -223,8 +259,13 @@ class file(object):
|
|||||||
self.wrapped_data.add(e.wrapped_data, eid)
|
self.wrapped_data.add(e.wrapped_data, eid)
|
||||||
e.wrapped_data.this.disown()
|
e.wrapped_data.this.disown()
|
||||||
attrs = list(enumerate(args)) + [(e.wrapped_data.get_argument_index(name), arg) for name, arg in kwargs.items()]
|
attrs = list(enumerate(args)) + [(e.wrapped_data.get_argument_index(name), arg) for name, arg in kwargs.items()]
|
||||||
|
if attrs:
|
||||||
|
transaction = self.transaction
|
||||||
|
self.transaction = None
|
||||||
for idx, arg in attrs:
|
for idx, arg in attrs:
|
||||||
e[idx] = arg
|
e[idx] = arg
|
||||||
|
if attrs:
|
||||||
|
self.transaction = transaction
|
||||||
if self.transaction:
|
if self.transaction:
|
||||||
self.transaction.store_create(e)
|
self.transaction.store_create(e)
|
||||||
return e
|
return e
|
||||||
@@ -325,10 +366,14 @@ class file(object):
|
|||||||
|
|
||||||
def batch(self):
|
def batch(self):
|
||||||
"""Low-level mechanism to speed up deletion of large subgraphs"""
|
"""Low-level mechanism to speed up deletion of large subgraphs"""
|
||||||
|
if self.transaction:
|
||||||
|
self.transaction.batch()
|
||||||
return self.wrapped_data.batch()
|
return self.wrapped_data.batch()
|
||||||
|
|
||||||
def unbatch(self):
|
def unbatch(self):
|
||||||
"""Low-level mechanism to speed up deletion of large subgraphs"""
|
"""Low-level mechanism to speed up deletion of large subgraphs"""
|
||||||
|
if self.transaction:
|
||||||
|
self.transaction.unbatch()
|
||||||
return self.wrapped_data.unbatch()
|
return self.wrapped_data.unbatch()
|
||||||
|
|
||||||
def __iter__(self):
|
def __iter__(self):
|
||||||
|
|||||||
Reference in New Issue
Block a user