filestorage.py 1.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566
  1. #!/usr/bin/python
  2. # -*- coding: utf-8 -*-
  3. import cPickle as pickle
  4. import logging
  5. import os
  6. import shutil
  7. from .basestorage import BaseStorage
  8. class FileStorage(BaseStorage):
  9. """Provides file-based persistency for BaseStorage"""
  10. def __init__(self, storage_dir):
  11. self.logger = logging.getLogger('Storage')
  12. self.storage_dir = storage_dir
  13. self.logger.debug('Using storage at \'{0}\''.format(storage_dir))
  14. self.storage_filename = os.path.join(storage_dir, 'storage.dat')
  15. self.storage_file = None
  16. def open(self):
  17. self.storage_file = open(self.storage_filename, 'a+b')
  18. loaded_data = {}
  19. try:
  20. self.storage_file.seek(0, os.SEEK_SET)
  21. loaded_data = pickle.load(self.storage_file)
  22. except EOFError:
  23. self.logger.warn(
  24. 'The storage file was empty.' +
  25. 'Assuming this is the first start with this storage directory.')
  26. except Exception as err:
  27. self.logger.error(
  28. 'Loading the storage failed. Please resolve the error ' +
  29. 'and/or remove the storage file \'%s\': %s',
  30. self.storage_filename,
  31. str(err),
  32. )
  33. raise err
  34. self.logger.info('Opened storage with %d entries.', len(loaded_data))
  35. self.init_data(loaded_data)
  36. def save(self):
  37. if self.storage_file is None:
  38. return
  39. self.storage_file.seek(0, os.SEEK_SET)
  40. self.storage_file.truncate()
  41. pickle.dump(self.data, self.storage_file, protocol=2)
  42. self.storage_file.flush()
  43. # make an auto-backup of the just-written file
  44. shutil.copyfile(
  45. self.storage_filename,
  46. self.storage_filename + '.autobackup')
  47. def close(self):
  48. self.save()
  49. self.storage_file.close()
  50. self.storage_file = None
  51. BaseStorage.close(self)