Pārlūkot izejas kodu

persistence: use a background thread, so that mining is not limited by i/o performance

Malte Kraus 8 gadi atpakaļ
vecāks
revīzija
93a9b4789e
2 mainītis faili ar 42 papildinājumiem un 8 dzēšanām
  1. 1 0
      doc/index.rst
  2. 41 8
      src/persistence.py

+ 1 - 0
doc/index.rst

@@ -36,6 +36,7 @@ Source Code Documentation
     src.proof_of_work
     src.protocol
     src.transaction
+    src.persistence
 
 Tests
 *****

+ 41 - 8
src/persistence.py

@@ -1,19 +1,33 @@
+""" Functionality for storing and retrieving the miner state on disk. """
+
 import json
 import os
 import os.path
 import tempfile
+from threading import Condition, Thread
 
 
 class Persistence:
+    """
+    Functionality for storing and retrieving the miner state on disk.
+
+    :param path: The path to the storage location. """#TODO
+    """:param chainbuilder: The chainbuilder to persist.
+    """
     def __init__(self, path: str, chainbuilder: 'ChainBuilder'):
         self.chainbuilder = chainbuilder
         self.proto = chainbuilder.protocol
         self.path = path
+        self._store_cond = Condition()
+        self._store_data = None
 
         chainbuilder.chain_change_handlers.append(self.store)
         self._loading = False
 
+        Thread(target=self._store_thread, daemon=True).start()
+
     def load(self):
+        """ Loads data from disk. """
         self._loading = True
         try:
             with open(self.path, "r") as f:
@@ -28,6 +42,11 @@ class Persistence:
             self._loading = False
 
     def store(self):
+        """
+        Asynchronously stores current data to disk.
+
+        Used as an event handler in the chainbuilder.
+        """
         if self._loading:
             return
 
@@ -36,11 +55,25 @@ class Persistence:
             "transactions": [t.to_json_compatible() for t in self.chainbuilder.unconfirmed_transactions.values()],
             "peers": [list(peer.peer_addr) for peer in self.proto.peers if peer.is_connected and peer.peer_addr is not None],
         }
-        with tempfile.NamedTemporaryFile(dir=os.path.dirname(self.path), delete=False, mode="w") as f:
-            try:
-                json.dump(obj, f, indent=4)
-                f.close()
-                os.rename(f.name, self.path)
-            except Exception as e:
-                os.unlink(f.name)
-                raise e
+        with self._store_cond:
+            self._store_data = obj
+            self._store_cond.notify()
+
+    def _store_thread(self):
+        while True:
+            with self._store_cond:
+                while self._store_data is None:
+                    self._store_cond.wait()
+                obj = self._store_data
+                self._store_data = None
+
+            with tempfile.NamedTemporaryFile(dir=os.path.dirname(self.path), delete=False, mode="w") as f:
+                try:
+                    json.dump(obj, f, indent=4)
+                    f.close()
+                    os.rename(f.name, self.path)
+                except Exception as e:
+                    os.unlink(f.name)
+                    raise e
+
+from .chainbuilder import ChainBuilder