Added lock file writing and checking. CURA-2449

This commit is contained in:
Jack Ha 2016-10-09 11:54:34 +02:00
parent ab23637f3b
commit 8b0d6e974a

View file

@ -49,11 +49,44 @@ from PyQt5.QtGui import QColor, QIcon
from PyQt5.QtWidgets import QMessageBox from PyQt5.QtWidgets import QMessageBox
from PyQt5.QtQml import qmlRegisterUncreatableType, qmlRegisterSingletonType, qmlRegisterType from PyQt5.QtQml import qmlRegisterUncreatableType, qmlRegisterSingletonType, qmlRegisterType
from contextlib import contextmanager
import sys import sys
import os.path import os.path
import numpy import numpy
import copy import copy
import urllib import urllib
import os
import time
CONFIG_LOCK_FILENAME = "cura.lock"
## Contextmanager to create a lock file and remove it afterwards.
@contextmanager
def lockFile(filename):
try:
with open(filename, 'w') as lock_file:
lock_file.write("Lock file - Cura is currently writing")
except:
Logger.log("e", "Could not create lock file [%s]" % filename)
yield
try:
if os.path.exists(filename):
os.remove(filename)
except:
Logger.log("e", "Could not delete lock file [%s]" % filename)
## Wait for a lock file to disappear
# the maximum allowable age is settable; if the file is too old, it will be ignored too
def waitFileDisappear(filename, max_age_seconds=10, msg=""):
now = time.time()
while os.path.exists(filename) and now < os.path.getmtime(filename) + max_age_seconds and now > os.path.getmtime(filename):
if msg:
Logger.log("d", msg)
time.sleep(1)
now = time.time()
numpy.seterr(all="ignore") numpy.seterr(all="ignore")
@ -201,6 +234,11 @@ class CuraApplication(QtApplication):
empty_quality_changes_container.addMetaDataEntry("type", "quality_changes") empty_quality_changes_container.addMetaDataEntry("type", "quality_changes")
ContainerRegistry.getInstance().addContainer(empty_quality_changes_container) ContainerRegistry.getInstance().addContainer(empty_quality_changes_container)
# Set the filename to create if cura is writing in the config dir.
self._config_lock_filename = os.path.join(Resources.getConfigStoragePath(), CONFIG_LOCK_FILENAME)
# Lock file check: if (another) Cura is writing in the Config dir, one may not be able to read a
# valid set of files. Not entirely fool-proof, but works when you start Cura shortly after shutting down.
waitFileDisappear(self._config_lock_filename, max_age_seconds=10, msg="Waiting for Cura to finish writing in the config dir...")
ContainerRegistry.getInstance().load() ContainerRegistry.getInstance().load()
Preferences.getInstance().addPreference("cura/active_mode", "simple") Preferences.getInstance().addPreference("cura/active_mode", "simple")
@ -308,38 +346,41 @@ class CuraApplication(QtApplication):
if not self._started: # Do not do saving during application start if not self._started: # Do not do saving during application start
return return
for instance in ContainerRegistry.getInstance().findInstanceContainers(): # When starting Cura, we check for the lockFile which is created and deleted here
if not instance.isDirty(): with lockFile(self._config_lock_filename):
continue
try: for instance in ContainerRegistry.getInstance().findInstanceContainers():
data = instance.serialize() if not instance.isDirty():
except NotImplementedError: continue
continue
except Exception:
Logger.logException("e", "An exception occurred when serializing container %s", instance.getId())
continue
mime_type = ContainerRegistry.getMimeTypeForContainer(type(instance)) try:
file_name = urllib.parse.quote_plus(instance.getId()) + "." + mime_type.preferredSuffix data = instance.serialize()
instance_type = instance.getMetaDataEntry("type") except NotImplementedError:
path = None continue
if instance_type == "material": except Exception:
path = Resources.getStoragePath(self.ResourceTypes.MaterialInstanceContainer, file_name) Logger.logException("e", "An exception occurred when serializing container %s", instance.getId())
elif instance_type == "quality" or instance_type == "quality_changes": continue
path = Resources.getStoragePath(self.ResourceTypes.QualityInstanceContainer, file_name)
elif instance_type == "user":
path = Resources.getStoragePath(self.ResourceTypes.UserInstanceContainer, file_name)
elif instance_type == "variant":
path = Resources.getStoragePath(self.ResourceTypes.VariantInstanceContainer, file_name)
if path: mime_type = ContainerRegistry.getMimeTypeForContainer(type(instance))
instance.setPath(path) file_name = urllib.parse.quote_plus(instance.getId()) + "." + mime_type.preferredSuffix
with SaveFile(path, "wt", -1, "utf-8") as f: instance_type = instance.getMetaDataEntry("type")
f.write(data) path = None
if instance_type == "material":
path = Resources.getStoragePath(self.ResourceTypes.MaterialInstanceContainer, file_name)
elif instance_type == "quality" or instance_type == "quality_changes":
path = Resources.getStoragePath(self.ResourceTypes.QualityInstanceContainer, file_name)
elif instance_type == "user":
path = Resources.getStoragePath(self.ResourceTypes.UserInstanceContainer, file_name)
elif instance_type == "variant":
path = Resources.getStoragePath(self.ResourceTypes.VariantInstanceContainer, file_name)
for stack in ContainerRegistry.getInstance().findContainerStacks(): if path:
self.saveStack(stack) instance.setPath(path)
with SaveFile(path, "wt", -1, "utf-8") as f:
f.write(data)
for stack in ContainerRegistry.getInstance().findContainerStacks():
self.saveStack(stack)
def saveStack(self, stack): def saveStack(self, stack):
if not stack.isDirty(): if not stack.isDirty():