Made metadata saving for gcode files more error resilient (hopefully that is)
This commit is contained in:
parent
895d077d85
commit
4d2213544e
2 changed files with 55 additions and 3 deletions
|
|
@ -70,6 +70,7 @@ class GcodeManager:
|
|||
self._metadata = {}
|
||||
self._metadataDirty = False
|
||||
self._metadataFile = os.path.join(self._uploadFolder, "metadata.yaml")
|
||||
self._metadataTempFile = os.path.join(self._uploadFolder, "metadata.yaml.tmp")
|
||||
self._metadataFileAccessMutex = threading.Lock()
|
||||
|
||||
self._metadataAnalyzer = MetadataAnalyzer(getPathCallback=self.getAbsolutePath, loadedCallback=self._onMetadataAnalysisFinished)
|
||||
|
|
@ -111,7 +112,7 @@ class GcodeManager:
|
|||
if gcode.extrusionAmount:
|
||||
analysisResult["filament"] = "%.2fm" % (gcode.extrusionAmount / 1000)
|
||||
if gcode.calculateVolumeCm3():
|
||||
analysisResult["filament"] += " / %.2fcm³" % gcode.calculateVolumeCm3()
|
||||
analysisResult["filament"] += " / %.2fcm³" % gcode.calculateVolumeCm3()
|
||||
dirty = True
|
||||
|
||||
if dirty:
|
||||
|
|
@ -134,9 +135,11 @@ class GcodeManager:
|
|||
return
|
||||
|
||||
with self._metadataFileAccessMutex:
|
||||
with open(self._metadataFile, "wb") as f:
|
||||
with open(self._metadataTempFile, "wb") as f:
|
||||
yaml.safe_dump(self._metadata, f, default_flow_style=False, indent=" ", allow_unicode=True)
|
||||
self._metadataDirty = False
|
||||
util.safeRename(self._metadataTempFile, self._metadataFile)
|
||||
|
||||
self._loadMetadata()
|
||||
self._sendUpdateTrigger("gcodeFiles")
|
||||
|
||||
|
|
@ -326,7 +329,7 @@ class GcodeManager:
|
|||
if key == "prints":
|
||||
val = self._metadata[filename][key]
|
||||
formattedLast = None
|
||||
if val["last"] is not None:
|
||||
if "last" in val and val["last"] is not None:
|
||||
formattedLast = {
|
||||
"date": util.getFormattedDateTime(datetime.datetime.fromtimestamp(val["last"]["date"])),
|
||||
"success": val["last"]["success"]
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ import traceback
|
|||
import sys
|
||||
import time
|
||||
import re
|
||||
import tempfile
|
||||
|
||||
from octoprint.settings import settings
|
||||
|
||||
|
|
@ -139,3 +140,51 @@ def findCollisionfreeName(input, extension, existingFilenames):
|
|||
power += 1
|
||||
|
||||
raise ValueError("Can't create a collision free filename")
|
||||
|
||||
|
||||
def safeRename(old, new):
|
||||
"""
|
||||
Safely renames a file.
|
||||
|
||||
On Windows this is achieved by first creating a backup file of the new file (if it
|
||||
already exists), thus moving it, then renaming the old into the new file and finally removing the backup. If
|
||||
anything goes wrong during those steps, the backup (if already there) will be renamed to its old name and thus
|
||||
the operation hopefully result in a no-op.
|
||||
|
||||
On other operating systems the atomic os.rename function will be used instead.
|
||||
|
||||
@param old the path to the old file to be renamed
|
||||
@param new the path to the new file to be created/replaced
|
||||
"""
|
||||
|
||||
if sys.platform == "win32":
|
||||
fh, backup = tempfile.mkstemp()
|
||||
os.close(fh)
|
||||
|
||||
try:
|
||||
if os.path.exists(new):
|
||||
silentRemove(backup)
|
||||
os.rename(new, backup)
|
||||
os.rename(old, new)
|
||||
os.remove(backup)
|
||||
except OSError:
|
||||
# if anything went wrong, try to rename the backup file to its original name
|
||||
if os.path.exists(backup):
|
||||
os.remove(new)
|
||||
os.rename(backup, new)
|
||||
else:
|
||||
# on anything else than windows it's ooooh so much easier...
|
||||
os.rename(old, new)
|
||||
|
||||
|
||||
def silentRemove(file):
|
||||
"""
|
||||
Silently removes a file. Does not raise an error if the file doesn't exist.
|
||||
|
||||
@param file the path of the file to be removed
|
||||
"""
|
||||
|
||||
try:
|
||||
os.remove(file)
|
||||
except OSError:
|
||||
pass
|
||||
|
|
|
|||
Loading…
Reference in a new issue