Browse Source

introduce base class for storage

The base class will contain logical data access functions,
the subclass will handle the persisting layer.
Helge Jung 9 years ago
parent
commit
f6149fb812
3 changed files with 54 additions and 5 deletions
  1. 35 0
      ffstatus/basestorage.py
  2. 1 1
      ffstatus/server.py
  3. 18 4
      ffstatus/storage.py

+ 35 - 0
ffstatus/basestorage.py

@@ -0,0 +1,35 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+
+from __future__ import print_function, unicode_literals
+
+class BaseStorage(object):
+    """
+    Provides operations on the storage data.
+    This class gets subclassed to actually write the data
+    to a file, database, whatever.
+    """
+
+    data = None
+
+    def open(self):
+        """
+        When overridden in a subclass,
+        closes the persistent storage.
+        """
+        pass
+
+    def save(self):
+        """
+        When overriden in a subclass,
+        stores the data to a persistent storage.
+        """
+        pass
+
+    def close(self):
+        """
+        When overridden in a subclass,
+        closes the persistent storage.
+        """
+        pass
+

+ 1 - 1
ffstatus/server.py

@@ -625,7 +625,7 @@ class ApiServer(ThreadingMixIn, HTTPServer):
         return 'ApiServer on {0}'.format(self.server_address)
 
 if __name__ == '__main__':
-    dummystorage = Storage()
+    dummystorage = ffstatus.basestorage.BaseStorage()
     server = ApiServer(('0.0.0.0', 8888), dummystorage)
 
     print("Server:", str(server))

+ 18 - 4
ffstatus/storage.py

@@ -5,31 +5,44 @@ import cPickle as pickle
 import logging
 import os
 
-class Storage:
-    data = None
+from .basestorage import BaseStorage
+
+class Storage(BaseStorage):
+    """Provides file-based persistency for BaseStorage"""
 
     def __init__(self, storage_dir):
         self.logger = logging.getLogger('Storage')
         self.storage_dir = storage_dir
 
         self.logger.debug('Using storage at \'{0}\''.format(storage_dir))
-        self.storage_file = open(os.path.join(storage_dir, 'storage.dat'), 'a+b')
+        self.storage_filename = os.path.join(storage_dir, 'storage.dat')
+
+        self.storage_file = None
+
+    def open(self):
+        self.storage_file = open(self.storage_filename, 'a+b')
         try:
             self.storage_file.seek(0, os.SEEK_SET)
             self.data = pickle.load(self.storage_file)
+
         except EOFError:
             self.logger.warn('The storage file was empty. I\'ll assume this is the first start with this storage directory.')
+
         except Exception as err:
             self.logger.error('Loading the storage failed. Please resolve the error and/or remove the storage file \'{0}\': {1}'.format(
-                os.path.join(storage_dir, self.storage_file.name),
+                self.storage_filename,
                 str(err),
             ))
             raise err
+
         if self.data is None:
             self.data = {}
         self.logger.info('Opened storage with ' + str(len(self.data)) + ' entries.')
 
     def save(self):
+        if self.storage_file is None:
+            return
+
         self.storage_file.seek(0, os.SEEK_SET)
         self.storage_file.truncate()
         pickle.dump(self.data, self.storage_file, protocol=2)
@@ -38,4 +51,5 @@ class Storage:
     def close(self):
         self.save()
         self.storage_file.close()
+        self.storage_file = None
         self.data = None