Commit 7cba67db authored by Alain Takoudjou's avatar Alain Takoudjou

slapos.grid.promise: prevent json file corruption while updating data

history and statistics files are sometimes corrupted because of invalid json
We now use json.dump to write the entire file at once. Probably this will consume
more resources.
parent 1386dba9
......@@ -41,6 +41,7 @@ import traceback
import psutil
import inspect
import hashlib
import errno
from datetime import datetime
from multiprocessing import Process, Queue as MQueue
from six.moves import queue, reload_module
......@@ -458,12 +459,20 @@ class PromiseLauncher(object):
state_dict.pop('path', '')
state_dict.pop('type', '')
state_dict["status"] = "ERROR" if result.item.hasFailed() else "OK"
history_dict = {
"date": time.time(),
"data": [state_dict]
}
if not os.path.exists(history_file) or not os.stat(history_file).st_size:
with open(history_file, 'w') as f:
f.write("""{
"date": %s,
"data": %s}""" % (time.time(), json.dumps([state_dict])))
try:
with open(history_file) as f:
history_dict = json.load(f)
except OSError as e:
if e.errno != errno.ENOENT:
raise
except ValueError:
# Broken json, use default history_dict
pass
else:
previous_state_list = previous_state_dict.get(result.name, None)
if previous_state_list is not None:
......@@ -473,36 +482,38 @@ class PromiseLauncher(object):
current_sum == checksum:
# Only save the changes and not the same info
return
state_dict.pop('title', '')
state_dict.pop('name', '')
with open (history_file, mode="r+") as f:
f.seek(0,2)
f.seek(f.tell() -2)
f.write('%s}' % ',{}]'.format(json.dumps(state_dict)))
history_dict['data'].append(state_dict)
with open (history_file, mode="w") as f:
json.dump(history_dict, f)
def _saveStatisticsData(self, stat_file_path, date, success, error):
# csv-like document for success/error statictics
if not os.path.exists(stat_file_path) or os.stat(stat_file_path).st_size == 0:
with open(stat_file_path, 'w') as fstat:
fstat.write("""{
"date": %s,
"data": ["Date, Success, Error, Warning"]}""" % time.time())
stat_dict = {
"date": time.time(),
"data": ["Date, Success, Error, Warning"]
}
try:
with open(stat_file_path) as f:
stat_dict = json.load(f)
except OSError as e:
if e.errno != errno.ENOENT:
raise
except ValueError:
# Broken json, we use default
pass
current_state = '%s, %s, %s, %s' % (
date,
success,
error,
'')
# append to file
# XXX this is bad, it is getting everywhere.
if current_state:
with open (stat_file_path, mode="r+") as fstat:
fstat.seek(0,2)
position = fstat.tell() -2
fstat.seek(position)
fstat.write('%s}' % ',"{}"]'.format(current_state))
stat_dict['data'].append(current_state)
with open (stat_file_path, mode="w") as f:
json.dump(stat_dict, f)
def _loadPromiseResult(self, promise_title):
promise_output_file = os.path.join(
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment