Workspace reader is now a lot more transactional;

Instead of adding the instance containers on the go, we add them right before serializing the stack.
This enables us to remove them if the stack serialization goes wrong

CURA-1263
This commit is contained in:
Jaime van Kessel 2016-11-22 14:15:12 +01:00
parent 88588454c8
commit 60d2d0d092

View file

@ -144,6 +144,10 @@ class ThreeMFWorkspaceReader(WorkspaceReader):
self._id_mapping = {} self._id_mapping = {}
# We don't add containers right away, but wait right until right before the stack serialization.
# We do this so that if something goes wrong, it's easier to clean up.
containers_to_add = []
# TODO: For the moment we use pretty naive existence checking. If the ID is the same, we assume in quite a few # TODO: For the moment we use pretty naive existence checking. If the ID is the same, we assume in quite a few
# TODO: cases that the container loaded is the same (most notable in materials & definitions). # TODO: cases that the container loaded is the same (most notable in materials & definitions).
# TODO: It might be possible that we need to add smarter checking in the future. # TODO: It might be possible that we need to add smarter checking in the future.
@ -172,7 +176,7 @@ class ThreeMFWorkspaceReader(WorkspaceReader):
if not materials: if not materials:
material_container = xml_material_profile(container_id) material_container = xml_material_profile(container_id)
material_container.deserialize(archive.open(material_container_file).read().decode("utf-8")) material_container.deserialize(archive.open(material_container_file).read().decode("utf-8"))
self._container_registry.addContainer(material_container) containers_to_add.append(material_container)
else: else:
if not materials[0].isReadOnly(): # Only create new materials if they are not read only. if not materials[0].isReadOnly(): # Only create new materials if they are not read only.
if self._resolve_strategies["material"] == "override": if self._resolve_strategies["material"] == "override":
@ -182,7 +186,7 @@ class ThreeMFWorkspaceReader(WorkspaceReader):
# auto created & added. # auto created & added.
material_container = xml_material_profile(self.getNewId(container_id)) material_container = xml_material_profile(self.getNewId(container_id))
material_container.deserialize(archive.open(material_container_file).read().decode("utf-8")) material_container.deserialize(archive.open(material_container_file).read().decode("utf-8"))
self._container_registry.addContainer(material_container) containers_to_add.append(material_container)
material_containers.append(material_container) material_containers.append(material_container)
Logger.log("d", "Workspace loading is checking instance containers...") Logger.log("d", "Workspace loading is checking instance containers...")
@ -201,7 +205,7 @@ class ThreeMFWorkspaceReader(WorkspaceReader):
# Check if quality changes already exists. # Check if quality changes already exists.
user_containers = self._container_registry.findInstanceContainers(id=container_id) user_containers = self._container_registry.findInstanceContainers(id=container_id)
if not user_containers: if not user_containers:
self._container_registry.addContainer(instance_container) containers_to_add.append(instance_container)
else: else:
if self._resolve_strategies["machine"] == "override": if self._resolve_strategies["machine"] == "override":
user_containers[0].deserialize(archive.open(instance_container_file).read().decode("utf-8")) user_containers[0].deserialize(archive.open(instance_container_file).read().decode("utf-8"))
@ -213,7 +217,7 @@ class ThreeMFWorkspaceReader(WorkspaceReader):
instance_container._id = new_id instance_container._id = new_id
instance_container.setName(new_id) instance_container.setName(new_id)
instance_container.setMetaDataEntry("extruder", self.getNewId(extruder_id)) instance_container.setMetaDataEntry("extruder", self.getNewId(extruder_id))
self._container_registry.addContainer(instance_container) containers_to_add.append(instance_container)
machine_id = instance_container.getMetaDataEntry("machine", None) machine_id = instance_container.getMetaDataEntry("machine", None)
if machine_id: if machine_id:
@ -221,13 +225,13 @@ class ThreeMFWorkspaceReader(WorkspaceReader):
instance_container._id = new_id instance_container._id = new_id
instance_container.setName(new_id) instance_container.setName(new_id)
instance_container.setMetaDataEntry("machine", self.getNewId(machine_id)) instance_container.setMetaDataEntry("machine", self.getNewId(machine_id))
self._container_registry.addContainer(instance_container) containers_to_add.append(instance_container)
user_instance_containers.append(instance_container) user_instance_containers.append(instance_container)
elif container_type == "quality_changes": elif container_type == "quality_changes":
# Check if quality changes already exists. # Check if quality changes already exists.
quality_changes = self._container_registry.findInstanceContainers(id = container_id) quality_changes = self._container_registry.findInstanceContainers(id = container_id)
if not quality_changes: if not quality_changes:
self._container_registry.addContainer(instance_container) containers_to_add.append(instance_container)
else: else:
if self._resolve_strategies["quality_changes"] == "override": if self._resolve_strategies["quality_changes"] == "override":
quality_changes[0].deserialize(archive.open(instance_container_file).read().decode("utf-8")) quality_changes[0].deserialize(archive.open(instance_container_file).read().decode("utf-8"))
@ -238,11 +242,17 @@ class ThreeMFWorkspaceReader(WorkspaceReader):
else: else:
continue continue
# Add all the containers right before we try to add / serialize the stack
for container in containers_to_add:
self._container_registry.addContainer(container)
# Get the stack(s) saved in the workspace. # Get the stack(s) saved in the workspace.
Logger.log("d", "Workspace loading is checking stacks containers...") Logger.log("d", "Workspace loading is checking stacks containers...")
container_stack_files = [name for name in cura_file_names if name.endswith(self._container_stack_suffix)] container_stack_files = [name for name in cura_file_names if name.endswith(self._container_stack_suffix)]
global_stack = None global_stack = None
extruder_stacks = [] extruder_stacks = []
container_stacks_added = []
try:
for container_stack_file in container_stack_files: for container_stack_file in container_stack_files:
container_id = self._stripFileToId(container_stack_file) container_id = self._stripFileToId(container_stack_file)
@ -268,6 +278,7 @@ class ThreeMFWorkspaceReader(WorkspaceReader):
if stack.getMetaDataEntry("type") != "extruder_train": if stack.getMetaDataEntry("type") != "extruder_train":
# Only machines need a new name, stacks may be non-unique # Only machines need a new name, stacks may be non-unique
stack.setName(self._container_registry.uniqueName(stack.getName())) stack.setName(self._container_registry.uniqueName(stack.getName()))
container_stacks_added.append(stack)
self._container_registry.addContainer(stack) self._container_registry.addContainer(stack)
else: else:
Logger.log("w", "Resolve strategy of %s for machine is not supported", self._resolve_strategies["machine"]) Logger.log("w", "Resolve strategy of %s for machine is not supported", self._resolve_strategies["machine"])
@ -275,12 +286,23 @@ class ThreeMFWorkspaceReader(WorkspaceReader):
stack = ContainerStack(container_id) stack = ContainerStack(container_id)
# Deserialize stack by converting read data from bytes to string # Deserialize stack by converting read data from bytes to string
stack.deserialize(archive.open(container_stack_file).read().decode("utf-8")) stack.deserialize(archive.open(container_stack_file).read().decode("utf-8"))
container_stacks_added.append(stack)
self._container_registry.addContainer(stack) self._container_registry.addContainer(stack)
if stack.getMetaDataEntry("type") == "extruder_train": if stack.getMetaDataEntry("type") == "extruder_train":
extruder_stacks.append(stack) extruder_stacks.append(stack)
else: else:
global_stack = stack global_stack = stack
except:
Logger.log("W", "We failed to serialize the stack. Trying to clean up.")
# Something went really wrong. Try to remove any data that we added.
for container in containers_to_add:
self._container_registry.getInstance().removeContainer(container.getId())
for container in container_stacks_added:
self._container_registry.getInstance().removeContainer(container.getId())
return None
if self._resolve_strategies["machine"] == "new": if self._resolve_strategies["machine"] == "new":
# A new machine was made, but it was serialized with the wrong user container. Fix that now. # A new machine was made, but it was serialized with the wrong user container. Fix that now.