Mercurial > personal > weather-server
annotate weather_server/logfile.py @ 34:8d3f32455575
Bump version.
author | Paul Fisher <paul@pfish.zone> |
---|---|
date | Sat, 12 Jun 2021 20:24:30 +0000 |
parents | 9bc3687e1e5e |
children |
rev | line source |
---|---|
0
efe7a1eff167
Create initial logger for weather server.
Paul Fisher <paul@pfish.zone>
parents:
diff
changeset
|
1 """The part which handles writing things out and reading things in from CSV. |
efe7a1eff167
Create initial logger for weather server.
Paul Fisher <paul@pfish.zone>
parents:
diff
changeset
|
2 """ |
efe7a1eff167
Create initial logger for weather server.
Paul Fisher <paul@pfish.zone>
parents:
diff
changeset
|
3 |
31
9bc3687e1e5e
logfile: Add an index, and don't keep everything in RAM.
Paul Fisher <paul@pfish.zone>
parents:
24
diff
changeset
|
4 import attr |
9bc3687e1e5e
logfile: Add an index, and don't keep everything in RAM.
Paul Fisher <paul@pfish.zone>
parents:
24
diff
changeset
|
5 import collections |
21
beb42c835c52
Make weather server handle arbitrary data:
Paul Fisher <paul@pfish.zone>
parents:
0
diff
changeset
|
6 import concurrent.futures as futures |
beb42c835c52
Make weather server handle arbitrary data:
Paul Fisher <paul@pfish.zone>
parents:
0
diff
changeset
|
7 import contextlib |
0
efe7a1eff167
Create initial logger for weather server.
Paul Fisher <paul@pfish.zone>
parents:
diff
changeset
|
8 import fcntl |
efe7a1eff167
Create initial logger for weather server.
Paul Fisher <paul@pfish.zone>
parents:
diff
changeset
|
9 import os |
21
beb42c835c52
Make weather server handle arbitrary data:
Paul Fisher <paul@pfish.zone>
parents:
0
diff
changeset
|
10 import queue |
0
efe7a1eff167
Create initial logger for weather server.
Paul Fisher <paul@pfish.zone>
parents:
diff
changeset
|
11 import threading |
efe7a1eff167
Create initial logger for weather server.
Paul Fisher <paul@pfish.zone>
parents:
diff
changeset
|
12 import typing as t |
efe7a1eff167
Create initial logger for weather server.
Paul Fisher <paul@pfish.zone>
parents:
diff
changeset
|
13 |
efe7a1eff167
Create initial logger for weather server.
Paul Fisher <paul@pfish.zone>
parents:
diff
changeset
|
14 import bson |
efe7a1eff167
Create initial logger for weather server.
Paul Fisher <paul@pfish.zone>
parents:
diff
changeset
|
15 |
efe7a1eff167
Create initial logger for weather server.
Paul Fisher <paul@pfish.zone>
parents:
diff
changeset
|
16 from . import common |
21
beb42c835c52
Make weather server handle arbitrary data:
Paul Fisher <paul@pfish.zone>
parents:
0
diff
changeset
|
17 |
beb42c835c52
Make weather server handle arbitrary data:
Paul Fisher <paul@pfish.zone>
parents:
0
diff
changeset
|
18 |
31
9bc3687e1e5e
logfile: Add an index, and don't keep everything in RAM.
Paul Fisher <paul@pfish.zone>
parents:
24
diff
changeset
|
19 # The number of entries to keep in memory without reading from disk. |
9bc3687e1e5e
logfile: Add an index, and don't keep everything in RAM.
Paul Fisher <paul@pfish.zone>
parents:
24
diff
changeset
|
20 CACHED_ENTRIES = 16384 |
9bc3687e1e5e
logfile: Add an index, and don't keep everything in RAM.
Paul Fisher <paul@pfish.zone>
parents:
24
diff
changeset
|
21 |
9bc3687e1e5e
logfile: Add an index, and don't keep everything in RAM.
Paul Fisher <paul@pfish.zone>
parents:
24
diff
changeset
|
22 # How many entries to read before creating a new index entry. |
9bc3687e1e5e
logfile: Add an index, and don't keep everything in RAM.
Paul Fisher <paul@pfish.zone>
parents:
24
diff
changeset
|
23 INDEX_GAP = 4096 |
9bc3687e1e5e
logfile: Add an index, and don't keep everything in RAM.
Paul Fisher <paul@pfish.zone>
parents:
24
diff
changeset
|
24 |
9bc3687e1e5e
logfile: Add an index, and don't keep everything in RAM.
Paul Fisher <paul@pfish.zone>
parents:
24
diff
changeset
|
25 |
21
beb42c835c52
Make weather server handle arbitrary data:
Paul Fisher <paul@pfish.zone>
parents:
0
diff
changeset
|
26 class _WriteRequest: |
0
efe7a1eff167
Create initial logger for weather server.
Paul Fisher <paul@pfish.zone>
parents:
diff
changeset
|
27 |
21
beb42c835c52
Make weather server handle arbitrary data:
Paul Fisher <paul@pfish.zone>
parents:
0
diff
changeset
|
28 def __init__(self, entries: t.Iterable[t.Dict[str, t.Any]]): |
beb42c835c52
Make weather server handle arbitrary data:
Paul Fisher <paul@pfish.zone>
parents:
0
diff
changeset
|
29 """Creates a request to write the given data to the log.""" |
beb42c835c52
Make weather server handle arbitrary data:
Paul Fisher <paul@pfish.zone>
parents:
0
diff
changeset
|
30 # The data to be written. We take ownership of all the dicts! |
beb42c835c52
Make weather server handle arbitrary data:
Paul Fisher <paul@pfish.zone>
parents:
0
diff
changeset
|
31 self.entries = entries |
beb42c835c52
Make weather server handle arbitrary data:
Paul Fisher <paul@pfish.zone>
parents:
0
diff
changeset
|
32 # Once written, a future that will resolve to None if successful. |
beb42c835c52
Make weather server handle arbitrary data:
Paul Fisher <paul@pfish.zone>
parents:
0
diff
changeset
|
33 self.future = futures.Future() |
beb42c835c52
Make weather server handle arbitrary data:
Paul Fisher <paul@pfish.zone>
parents:
0
diff
changeset
|
34 |
beb42c835c52
Make weather server handle arbitrary data:
Paul Fisher <paul@pfish.zone>
parents:
0
diff
changeset
|
35 |
beb42c835c52
Make weather server handle arbitrary data:
Paul Fisher <paul@pfish.zone>
parents:
0
diff
changeset
|
36 class _ReadRequest: |
beb42c835c52
Make weather server handle arbitrary data:
Paul Fisher <paul@pfish.zone>
parents:
0
diff
changeset
|
37 |
beb42c835c52
Make weather server handle arbitrary data:
Paul Fisher <paul@pfish.zone>
parents:
0
diff
changeset
|
38 def __init__(self): |
beb42c835c52
Make weather server handle arbitrary data:
Paul Fisher <paul@pfish.zone>
parents:
0
diff
changeset
|
39 # The future that will be set with the log's contnets. |
beb42c835c52
Make weather server handle arbitrary data:
Paul Fisher <paul@pfish.zone>
parents:
0
diff
changeset
|
40 self.future = futures.Future() |
31
9bc3687e1e5e
logfile: Add an index, and don't keep everything in RAM.
Paul Fisher <paul@pfish.zone>
parents:
24
diff
changeset
|
41 # TODO(pfish): Make it possible to read from a starting point. |
21
beb42c835c52
Make weather server handle arbitrary data:
Paul Fisher <paul@pfish.zone>
parents:
0
diff
changeset
|
42 |
beb42c835c52
Make weather server handle arbitrary data:
Paul Fisher <paul@pfish.zone>
parents:
0
diff
changeset
|
43 |
24
20c8ec56e447
logfile: Pull logfile thread out of Logger.
Paul Fisher <paul@pfish.zone>
parents:
21
diff
changeset
|
44 # Poison pill to tell a logger thread to stop. |
20c8ec56e447
logfile: Pull logfile thread out of Logger.
Paul Fisher <paul@pfish.zone>
parents:
21
diff
changeset
|
45 _POISON = object() |
20c8ec56e447
logfile: Pull logfile thread out of Logger.
Paul Fisher <paul@pfish.zone>
parents:
21
diff
changeset
|
46 |
0
efe7a1eff167
Create initial logger for weather server.
Paul Fisher <paul@pfish.zone>
parents:
diff
changeset
|
47 |
efe7a1eff167
Create initial logger for weather server.
Paul Fisher <paul@pfish.zone>
parents:
diff
changeset
|
48 class Logger: |
24
20c8ec56e447
logfile: Pull logfile thread out of Logger.
Paul Fisher <paul@pfish.zone>
parents:
21
diff
changeset
|
49 """Logger which handles reading/writing one temperature log file.""" |
0
efe7a1eff167
Create initial logger for weather server.
Paul Fisher <paul@pfish.zone>
parents:
diff
changeset
|
50 |
31
9bc3687e1e5e
logfile: Add an index, and don't keep everything in RAM.
Paul Fisher <paul@pfish.zone>
parents:
24
diff
changeset
|
51 _file: t.BinaryIO |
9bc3687e1e5e
logfile: Add an index, and don't keep everything in RAM.
Paul Fisher <paul@pfish.zone>
parents:
24
diff
changeset
|
52 _index_file: t.BinaryIO |
9bc3687e1e5e
logfile: Add an index, and don't keep everything in RAM.
Paul Fisher <paul@pfish.zone>
parents:
24
diff
changeset
|
53 |
9bc3687e1e5e
logfile: Add an index, and don't keep everything in RAM.
Paul Fisher <paul@pfish.zone>
parents:
24
diff
changeset
|
54 def __init__( |
9bc3687e1e5e
logfile: Add an index, and don't keep everything in RAM.
Paul Fisher <paul@pfish.zone>
parents:
24
diff
changeset
|
55 self, |
9bc3687e1e5e
logfile: Add an index, and don't keep everything in RAM.
Paul Fisher <paul@pfish.zone>
parents:
24
diff
changeset
|
56 filename: str, |
9bc3687e1e5e
logfile: Add an index, and don't keep everything in RAM.
Paul Fisher <paul@pfish.zone>
parents:
24
diff
changeset
|
57 *, |
9bc3687e1e5e
logfile: Add an index, and don't keep everything in RAM.
Paul Fisher <paul@pfish.zone>
parents:
24
diff
changeset
|
58 sample_field: str, |
9bc3687e1e5e
logfile: Add an index, and don't keep everything in RAM.
Paul Fisher <paul@pfish.zone>
parents:
24
diff
changeset
|
59 cached_entries: int = CACHED_ENTRIES, |
9bc3687e1e5e
logfile: Add an index, and don't keep everything in RAM.
Paul Fisher <paul@pfish.zone>
parents:
24
diff
changeset
|
60 index_gap: int = INDEX_GAP): |
24
20c8ec56e447
logfile: Pull logfile thread out of Logger.
Paul Fisher <paul@pfish.zone>
parents:
21
diff
changeset
|
61 """Creates a new Logger for the given file. |
20c8ec56e447
logfile: Pull logfile thread out of Logger.
Paul Fisher <paul@pfish.zone>
parents:
21
diff
changeset
|
62 |
20c8ec56e447
logfile: Pull logfile thread out of Logger.
Paul Fisher <paul@pfish.zone>
parents:
21
diff
changeset
|
63 Args: |
20c8ec56e447
logfile: Pull logfile thread out of Logger.
Paul Fisher <paul@pfish.zone>
parents:
21
diff
changeset
|
64 filename: The filename to open, or create if not already there. |
20c8ec56e447
logfile: Pull logfile thread out of Logger.
Paul Fisher <paul@pfish.zone>
parents:
21
diff
changeset
|
65 sample_field: The field name to use as the strictly-increasing |
20c8ec56e447
logfile: Pull logfile thread out of Logger.
Paul Fisher <paul@pfish.zone>
parents:
21
diff
changeset
|
66 value to ensure that no duplicate writes occur. |
20c8ec56e447
logfile: Pull logfile thread out of Logger.
Paul Fisher <paul@pfish.zone>
parents:
21
diff
changeset
|
67 """ |
31
9bc3687e1e5e
logfile: Add an index, and don't keep everything in RAM.
Paul Fisher <paul@pfish.zone>
parents:
24
diff
changeset
|
68 |
9bc3687e1e5e
logfile: Add an index, and don't keep everything in RAM.
Paul Fisher <paul@pfish.zone>
parents:
24
diff
changeset
|
69 self._filename = filename |
9bc3687e1e5e
logfile: Add an index, and don't keep everything in RAM.
Paul Fisher <paul@pfish.zone>
parents:
24
diff
changeset
|
70 self._cached_entries = cached_entries |
9bc3687e1e5e
logfile: Add an index, and don't keep everything in RAM.
Paul Fisher <paul@pfish.zone>
parents:
24
diff
changeset
|
71 self._index_gap = index_gap |
9bc3687e1e5e
logfile: Add an index, and don't keep everything in RAM.
Paul Fisher <paul@pfish.zone>
parents:
24
diff
changeset
|
72 |
21
beb42c835c52
Make weather server handle arbitrary data:
Paul Fisher <paul@pfish.zone>
parents:
0
diff
changeset
|
73 self._queue = queue.SimpleQueue() |
31
9bc3687e1e5e
logfile: Add an index, and don't keep everything in RAM.
Paul Fisher <paul@pfish.zone>
parents:
24
diff
changeset
|
74 self._sample_field = sample_field |
9bc3687e1e5e
logfile: Add an index, and don't keep everything in RAM.
Paul Fisher <paul@pfish.zone>
parents:
24
diff
changeset
|
75 |
9bc3687e1e5e
logfile: Add an index, and don't keep everything in RAM.
Paul Fisher <paul@pfish.zone>
parents:
24
diff
changeset
|
76 self._start_future = futures.Future() |
9bc3687e1e5e
logfile: Add an index, and don't keep everything in RAM.
Paul Fisher <paul@pfish.zone>
parents:
24
diff
changeset
|
77 self._thread = threading.Thread( |
24
20c8ec56e447
logfile: Pull logfile thread out of Logger.
Paul Fisher <paul@pfish.zone>
parents:
21
diff
changeset
|
78 name=f'{filename!r} writer thread', |
31
9bc3687e1e5e
logfile: Add an index, and don't keep everything in RAM.
Paul Fisher <paul@pfish.zone>
parents:
24
diff
changeset
|
79 target=self._writer_thread, |
24
20c8ec56e447
logfile: Pull logfile thread out of Logger.
Paul Fisher <paul@pfish.zone>
parents:
21
diff
changeset
|
80 daemon=True) |
31
9bc3687e1e5e
logfile: Add an index, and don't keep everything in RAM.
Paul Fisher <paul@pfish.zone>
parents:
24
diff
changeset
|
81 self._thread.start() |
9bc3687e1e5e
logfile: Add an index, and don't keep everything in RAM.
Paul Fisher <paul@pfish.zone>
parents:
24
diff
changeset
|
82 |
9bc3687e1e5e
logfile: Add an index, and don't keep everything in RAM.
Paul Fisher <paul@pfish.zone>
parents:
24
diff
changeset
|
83 self._data = collections.deque(maxlen=self._cached_entries) |
9bc3687e1e5e
logfile: Add an index, and don't keep everything in RAM.
Paul Fisher <paul@pfish.zone>
parents:
24
diff
changeset
|
84 self._index: t.List[IndexEntry] = [] |
9bc3687e1e5e
logfile: Add an index, and don't keep everything in RAM.
Paul Fisher <paul@pfish.zone>
parents:
24
diff
changeset
|
85 self._message_count = 0 |
9bc3687e1e5e
logfile: Add an index, and don't keep everything in RAM.
Paul Fisher <paul@pfish.zone>
parents:
24
diff
changeset
|
86 self._start_future.result() |
21
beb42c835c52
Make weather server handle arbitrary data:
Paul Fisher <paul@pfish.zone>
parents:
0
diff
changeset
|
87 |
beb42c835c52
Make weather server handle arbitrary data:
Paul Fisher <paul@pfish.zone>
parents:
0
diff
changeset
|
88 @property |
31
9bc3687e1e5e
logfile: Add an index, and don't keep everything in RAM.
Paul Fisher <paul@pfish.zone>
parents:
24
diff
changeset
|
89 def cached_data(self) -> t.Tuple[t.Dict[str, t.Any], ...]: |
21
beb42c835c52
Make weather server handle arbitrary data:
Paul Fisher <paul@pfish.zone>
parents:
0
diff
changeset
|
90 req = _ReadRequest() |
beb42c835c52
Make weather server handle arbitrary data:
Paul Fisher <paul@pfish.zone>
parents:
0
diff
changeset
|
91 self._queue.put(req) |
beb42c835c52
Make weather server handle arbitrary data:
Paul Fisher <paul@pfish.zone>
parents:
0
diff
changeset
|
92 return req.future.result() |
beb42c835c52
Make weather server handle arbitrary data:
Paul Fisher <paul@pfish.zone>
parents:
0
diff
changeset
|
93 |
beb42c835c52
Make weather server handle arbitrary data:
Paul Fisher <paul@pfish.zone>
parents:
0
diff
changeset
|
94 def write_rows(self, entries: t.Iterable[t.Dict[str, t.Any]]): |
beb42c835c52
Make weather server handle arbitrary data:
Paul Fisher <paul@pfish.zone>
parents:
0
diff
changeset
|
95 req = _WriteRequest(entries) |
beb42c835c52
Make weather server handle arbitrary data:
Paul Fisher <paul@pfish.zone>
parents:
0
diff
changeset
|
96 self._queue.put(req) |
beb42c835c52
Make weather server handle arbitrary data:
Paul Fisher <paul@pfish.zone>
parents:
0
diff
changeset
|
97 return req.future.result() |
beb42c835c52
Make weather server handle arbitrary data:
Paul Fisher <paul@pfish.zone>
parents:
0
diff
changeset
|
98 |
31
9bc3687e1e5e
logfile: Add an index, and don't keep everything in RAM.
Paul Fisher <paul@pfish.zone>
parents:
24
diff
changeset
|
99 def _writer_thread(self) -> None: |
9bc3687e1e5e
logfile: Add an index, and don't keep everything in RAM.
Paul Fisher <paul@pfish.zone>
parents:
24
diff
changeset
|
100 try: |
9bc3687e1e5e
logfile: Add an index, and don't keep everything in RAM.
Paul Fisher <paul@pfish.zone>
parents:
24
diff
changeset
|
101 self._file = _open_or_create(self._filename) |
9bc3687e1e5e
logfile: Add an index, and don't keep everything in RAM.
Paul Fisher <paul@pfish.zone>
parents:
24
diff
changeset
|
102 self._index_file = _open_or_create(_index_filename(self._filename)) |
9bc3687e1e5e
logfile: Add an index, and don't keep everything in RAM.
Paul Fisher <paul@pfish.zone>
parents:
24
diff
changeset
|
103 except BaseException as e: |
9bc3687e1e5e
logfile: Add an index, and don't keep everything in RAM.
Paul Fisher <paul@pfish.zone>
parents:
24
diff
changeset
|
104 self._start_future.set_exception(e) |
9bc3687e1e5e
logfile: Add an index, and don't keep everything in RAM.
Paul Fisher <paul@pfish.zone>
parents:
24
diff
changeset
|
105 return |
9bc3687e1e5e
logfile: Add an index, and don't keep everything in RAM.
Paul Fisher <paul@pfish.zone>
parents:
24
diff
changeset
|
106 self._start_future.set_result(None) |
9bc3687e1e5e
logfile: Add an index, and don't keep everything in RAM.
Paul Fisher <paul@pfish.zone>
parents:
24
diff
changeset
|
107 |
9bc3687e1e5e
logfile: Add an index, and don't keep everything in RAM.
Paul Fisher <paul@pfish.zone>
parents:
24
diff
changeset
|
108 with self._file, self._index_file: |
9bc3687e1e5e
logfile: Add an index, and don't keep everything in RAM.
Paul Fisher <paul@pfish.zone>
parents:
24
diff
changeset
|
109 running = True |
9bc3687e1e5e
logfile: Add an index, and don't keep everything in RAM.
Paul Fisher <paul@pfish.zone>
parents:
24
diff
changeset
|
110 while running: |
9bc3687e1e5e
logfile: Add an index, and don't keep everything in RAM.
Paul Fisher <paul@pfish.zone>
parents:
24
diff
changeset
|
111 item = self._queue.get() |
9bc3687e1e5e
logfile: Add an index, and don't keep everything in RAM.
Paul Fisher <paul@pfish.zone>
parents:
24
diff
changeset
|
112 if item is _POISON: |
9bc3687e1e5e
logfile: Add an index, and don't keep everything in RAM.
Paul Fisher <paul@pfish.zone>
parents:
24
diff
changeset
|
113 # None is the poison pill that makes us stop. |
9bc3687e1e5e
logfile: Add an index, and don't keep everything in RAM.
Paul Fisher <paul@pfish.zone>
parents:
24
diff
changeset
|
114 running = False |
9bc3687e1e5e
logfile: Add an index, and don't keep everything in RAM.
Paul Fisher <paul@pfish.zone>
parents:
24
diff
changeset
|
115 elif isinstance(item, _ReadRequest): |
9bc3687e1e5e
logfile: Add an index, and don't keep everything in RAM.
Paul Fisher <paul@pfish.zone>
parents:
24
diff
changeset
|
116 if not item.future.set_running_or_notify_cancel(): |
9bc3687e1e5e
logfile: Add an index, and don't keep everything in RAM.
Paul Fisher <paul@pfish.zone>
parents:
24
diff
changeset
|
117 continue |
9bc3687e1e5e
logfile: Add an index, and don't keep everything in RAM.
Paul Fisher <paul@pfish.zone>
parents:
24
diff
changeset
|
118 with _file_lock(self._file, fcntl.LOCK_SH): |
9bc3687e1e5e
logfile: Add an index, and don't keep everything in RAM.
Paul Fisher <paul@pfish.zone>
parents:
24
diff
changeset
|
119 try: |
9bc3687e1e5e
logfile: Add an index, and don't keep everything in RAM.
Paul Fisher <paul@pfish.zone>
parents:
24
diff
changeset
|
120 self._catch_up() |
9bc3687e1e5e
logfile: Add an index, and don't keep everything in RAM.
Paul Fisher <paul@pfish.zone>
parents:
24
diff
changeset
|
121 except BaseException as x: |
9bc3687e1e5e
logfile: Add an index, and don't keep everything in RAM.
Paul Fisher <paul@pfish.zone>
parents:
24
diff
changeset
|
122 item.future.set_exception(x) |
9bc3687e1e5e
logfile: Add an index, and don't keep everything in RAM.
Paul Fisher <paul@pfish.zone>
parents:
24
diff
changeset
|
123 else: |
9bc3687e1e5e
logfile: Add an index, and don't keep everything in RAM.
Paul Fisher <paul@pfish.zone>
parents:
24
diff
changeset
|
124 item.future.set_result(tuple(self._data)) |
9bc3687e1e5e
logfile: Add an index, and don't keep everything in RAM.
Paul Fisher <paul@pfish.zone>
parents:
24
diff
changeset
|
125 elif isinstance(item, _WriteRequest): |
9bc3687e1e5e
logfile: Add an index, and don't keep everything in RAM.
Paul Fisher <paul@pfish.zone>
parents:
24
diff
changeset
|
126 if not item.future.set_running_or_notify_cancel(): |
9bc3687e1e5e
logfile: Add an index, and don't keep everything in RAM.
Paul Fisher <paul@pfish.zone>
parents:
24
diff
changeset
|
127 continue |
9bc3687e1e5e
logfile: Add an index, and don't keep everything in RAM.
Paul Fisher <paul@pfish.zone>
parents:
24
diff
changeset
|
128 try: |
9bc3687e1e5e
logfile: Add an index, and don't keep everything in RAM.
Paul Fisher <paul@pfish.zone>
parents:
24
diff
changeset
|
129 with _file_lock(self._file, fcntl.LOCK_EX): |
9bc3687e1e5e
logfile: Add an index, and don't keep everything in RAM.
Paul Fisher <paul@pfish.zone>
parents:
24
diff
changeset
|
130 self._catch_up() |
9bc3687e1e5e
logfile: Add an index, and don't keep everything in RAM.
Paul Fisher <paul@pfish.zone>
parents:
24
diff
changeset
|
131 current_ptr = self._file.tell() |
9bc3687e1e5e
logfile: Add an index, and don't keep everything in RAM.
Paul Fisher <paul@pfish.zone>
parents:
24
diff
changeset
|
132 self._file.truncate(current_ptr) |
9bc3687e1e5e
logfile: Add an index, and don't keep everything in RAM.
Paul Fisher <paul@pfish.zone>
parents:
24
diff
changeset
|
133 if not self._data: |
9bc3687e1e5e
logfile: Add an index, and don't keep everything in RAM.
Paul Fisher <paul@pfish.zone>
parents:
24
diff
changeset
|
134 prev_key = None |
9bc3687e1e5e
logfile: Add an index, and don't keep everything in RAM.
Paul Fisher <paul@pfish.zone>
parents:
24
diff
changeset
|
135 else: |
9bc3687e1e5e
logfile: Add an index, and don't keep everything in RAM.
Paul Fisher <paul@pfish.zone>
parents:
24
diff
changeset
|
136 prev_key = self._data[-1][self._sample_field] |
9bc3687e1e5e
logfile: Add an index, and don't keep everything in RAM.
Paul Fisher <paul@pfish.zone>
parents:
24
diff
changeset
|
137 for entry in item.entries: |
9bc3687e1e5e
logfile: Add an index, and don't keep everything in RAM.
Paul Fisher <paul@pfish.zone>
parents:
24
diff
changeset
|
138 entry_key = entry[self._sample_field] |
9bc3687e1e5e
logfile: Add an index, and don't keep everything in RAM.
Paul Fisher <paul@pfish.zone>
parents:
24
diff
changeset
|
139 if prev_key is None or prev_key < entry_key: |
9bc3687e1e5e
logfile: Add an index, and don't keep everything in RAM.
Paul Fisher <paul@pfish.zone>
parents:
24
diff
changeset
|
140 self._data.append(entry) |
9bc3687e1e5e
logfile: Add an index, and don't keep everything in RAM.
Paul Fisher <paul@pfish.zone>
parents:
24
diff
changeset
|
141 self._file.write(common.bson_encode(entry)) |
9bc3687e1e5e
logfile: Add an index, and don't keep everything in RAM.
Paul Fisher <paul@pfish.zone>
parents:
24
diff
changeset
|
142 prev_key = entry_key |
9bc3687e1e5e
logfile: Add an index, and don't keep everything in RAM.
Paul Fisher <paul@pfish.zone>
parents:
24
diff
changeset
|
143 self._file.flush() |
9bc3687e1e5e
logfile: Add an index, and don't keep everything in RAM.
Paul Fisher <paul@pfish.zone>
parents:
24
diff
changeset
|
144 self._update_index() |
9bc3687e1e5e
logfile: Add an index, and don't keep everything in RAM.
Paul Fisher <paul@pfish.zone>
parents:
24
diff
changeset
|
145 except BaseException as x: |
9bc3687e1e5e
logfile: Add an index, and don't keep everything in RAM.
Paul Fisher <paul@pfish.zone>
parents:
24
diff
changeset
|
146 item.future.set_exception(x) |
9bc3687e1e5e
logfile: Add an index, and don't keep everything in RAM.
Paul Fisher <paul@pfish.zone>
parents:
24
diff
changeset
|
147 else: |
9bc3687e1e5e
logfile: Add an index, and don't keep everything in RAM.
Paul Fisher <paul@pfish.zone>
parents:
24
diff
changeset
|
148 item.future.set_result(None) |
9bc3687e1e5e
logfile: Add an index, and don't keep everything in RAM.
Paul Fisher <paul@pfish.zone>
parents:
24
diff
changeset
|
149 else: |
9bc3687e1e5e
logfile: Add an index, and don't keep everything in RAM.
Paul Fisher <paul@pfish.zone>
parents:
24
diff
changeset
|
150 raise AssertionError( |
9bc3687e1e5e
logfile: Add an index, and don't keep everything in RAM.
Paul Fisher <paul@pfish.zone>
parents:
24
diff
changeset
|
151 f'Unexpected item {item!r} in the queue') |
9bc3687e1e5e
logfile: Add an index, and don't keep everything in RAM.
Paul Fisher <paul@pfish.zone>
parents:
24
diff
changeset
|
152 |
9bc3687e1e5e
logfile: Add an index, and don't keep everything in RAM.
Paul Fisher <paul@pfish.zone>
parents:
24
diff
changeset
|
153 def _catch_up(self) -> None: |
9bc3687e1e5e
logfile: Add an index, and don't keep everything in RAM.
Paul Fisher <paul@pfish.zone>
parents:
24
diff
changeset
|
154 # Preconditions: |
9bc3687e1e5e
logfile: Add an index, and don't keep everything in RAM.
Paul Fisher <paul@pfish.zone>
parents:
24
diff
changeset
|
155 # - At least a read lock is held. |
9bc3687e1e5e
logfile: Add an index, and don't keep everything in RAM.
Paul Fisher <paul@pfish.zone>
parents:
24
diff
changeset
|
156 # - File pointer is at the end of the last-read entry. |
9bc3687e1e5e
logfile: Add an index, and don't keep everything in RAM.
Paul Fisher <paul@pfish.zone>
parents:
24
diff
changeset
|
157 self._catch_up_index() |
9bc3687e1e5e
logfile: Add an index, and don't keep everything in RAM.
Paul Fisher <paul@pfish.zone>
parents:
24
diff
changeset
|
158 if self._index: |
9bc3687e1e5e
logfile: Add an index, and don't keep everything in RAM.
Paul Fisher <paul@pfish.zone>
parents:
24
diff
changeset
|
159 # Since we have an index, use it to find a starting place. |
9bc3687e1e5e
logfile: Add an index, and don't keep everything in RAM.
Paul Fisher <paul@pfish.zone>
parents:
24
diff
changeset
|
160 last_idx = self._index[-1] |
9bc3687e1e5e
logfile: Add an index, and don't keep everything in RAM.
Paul Fisher <paul@pfish.zone>
parents:
24
diff
changeset
|
161 # Figure out, based on the number of entries we want to keep |
9bc3687e1e5e
logfile: Add an index, and don't keep everything in RAM.
Paul Fisher <paul@pfish.zone>
parents:
24
diff
changeset
|
162 # in memory, where we should start reading from. |
9bc3687e1e5e
logfile: Add an index, and don't keep everything in RAM.
Paul Fisher <paul@pfish.zone>
parents:
24
diff
changeset
|
163 read_start_count = max( |
9bc3687e1e5e
logfile: Add an index, and don't keep everything in RAM.
Paul Fisher <paul@pfish.zone>
parents:
24
diff
changeset
|
164 0, last_idx.entry_count - self._cached_entries) |
9bc3687e1e5e
logfile: Add an index, and don't keep everything in RAM.
Paul Fisher <paul@pfish.zone>
parents:
24
diff
changeset
|
165 if self._message_count < read_start_count: |
9bc3687e1e5e
logfile: Add an index, and don't keep everything in RAM.
Paul Fisher <paul@pfish.zone>
parents:
24
diff
changeset
|
166 # If we've already read past that starting point, we're OK. |
9bc3687e1e5e
logfile: Add an index, and don't keep everything in RAM.
Paul Fisher <paul@pfish.zone>
parents:
24
diff
changeset
|
167 for idx_entry in self._index: |
9bc3687e1e5e
logfile: Add an index, and don't keep everything in RAM.
Paul Fisher <paul@pfish.zone>
parents:
24
diff
changeset
|
168 if read_start_count <= idx_entry.entry_count: |
9bc3687e1e5e
logfile: Add an index, and don't keep everything in RAM.
Paul Fisher <paul@pfish.zone>
parents:
24
diff
changeset
|
169 break |
9bc3687e1e5e
logfile: Add an index, and don't keep everything in RAM.
Paul Fisher <paul@pfish.zone>
parents:
24
diff
changeset
|
170 starting_point = idx_entry |
9bc3687e1e5e
logfile: Add an index, and don't keep everything in RAM.
Paul Fisher <paul@pfish.zone>
parents:
24
diff
changeset
|
171 self._data.clear() |
9bc3687e1e5e
logfile: Add an index, and don't keep everything in RAM.
Paul Fisher <paul@pfish.zone>
parents:
24
diff
changeset
|
172 self._file.seek(starting_point.byte, os.SEEK_SET) |
9bc3687e1e5e
logfile: Add an index, and don't keep everything in RAM.
Paul Fisher <paul@pfish.zone>
parents:
24
diff
changeset
|
173 self._message_count = starting_point.entry_count |
9bc3687e1e5e
logfile: Add an index, and don't keep everything in RAM.
Paul Fisher <paul@pfish.zone>
parents:
24
diff
changeset
|
174 pointer = self._file.tell() |
9bc3687e1e5e
logfile: Add an index, and don't keep everything in RAM.
Paul Fisher <paul@pfish.zone>
parents:
24
diff
changeset
|
175 try: |
9bc3687e1e5e
logfile: Add an index, and don't keep everything in RAM.
Paul Fisher <paul@pfish.zone>
parents:
24
diff
changeset
|
176 items = bson.decode_file_iter( |
9bc3687e1e5e
logfile: Add an index, and don't keep everything in RAM.
Paul Fisher <paul@pfish.zone>
parents:
24
diff
changeset
|
177 self._file, codec_options=common.BSON_OPTIONS) |
9bc3687e1e5e
logfile: Add an index, and don't keep everything in RAM.
Paul Fisher <paul@pfish.zone>
parents:
24
diff
changeset
|
178 for item in items: |
9bc3687e1e5e
logfile: Add an index, and don't keep everything in RAM.
Paul Fisher <paul@pfish.zone>
parents:
24
diff
changeset
|
179 pointer = self._file.tell() |
9bc3687e1e5e
logfile: Add an index, and don't keep everything in RAM.
Paul Fisher <paul@pfish.zone>
parents:
24
diff
changeset
|
180 self._data.append(item) |
9bc3687e1e5e
logfile: Add an index, and don't keep everything in RAM.
Paul Fisher <paul@pfish.zone>
parents:
24
diff
changeset
|
181 self._message_count += 1 |
9bc3687e1e5e
logfile: Add an index, and don't keep everything in RAM.
Paul Fisher <paul@pfish.zone>
parents:
24
diff
changeset
|
182 except bson.InvalidBSON: |
9bc3687e1e5e
logfile: Add an index, and don't keep everything in RAM.
Paul Fisher <paul@pfish.zone>
parents:
24
diff
changeset
|
183 pass # We have reached the last valid document. Bail. |
9bc3687e1e5e
logfile: Add an index, and don't keep everything in RAM.
Paul Fisher <paul@pfish.zone>
parents:
24
diff
changeset
|
184 # Seek back to immediately after the end of the last valid doc. |
9bc3687e1e5e
logfile: Add an index, and don't keep everything in RAM.
Paul Fisher <paul@pfish.zone>
parents:
24
diff
changeset
|
185 self._file.seek(pointer, os.SEEK_SET) |
9bc3687e1e5e
logfile: Add an index, and don't keep everything in RAM.
Paul Fisher <paul@pfish.zone>
parents:
24
diff
changeset
|
186 |
9bc3687e1e5e
logfile: Add an index, and don't keep everything in RAM.
Paul Fisher <paul@pfish.zone>
parents:
24
diff
changeset
|
187 def _update_index(self) -> None: |
9bc3687e1e5e
logfile: Add an index, and don't keep everything in RAM.
Paul Fisher <paul@pfish.zone>
parents:
24
diff
changeset
|
188 # Preconditions: |
9bc3687e1e5e
logfile: Add an index, and don't keep everything in RAM.
Paul Fisher <paul@pfish.zone>
parents:
24
diff
changeset
|
189 # - File pointer is at the end of the last-written message. |
9bc3687e1e5e
logfile: Add an index, and don't keep everything in RAM.
Paul Fisher <paul@pfish.zone>
parents:
24
diff
changeset
|
190 # - Index pointer is at the last-read index value. |
9bc3687e1e5e
logfile: Add an index, and don't keep everything in RAM.
Paul Fisher <paul@pfish.zone>
parents:
24
diff
changeset
|
191 # - Exclusive lock is held. |
9bc3687e1e5e
logfile: Add an index, and don't keep everything in RAM.
Paul Fisher <paul@pfish.zone>
parents:
24
diff
changeset
|
192 with _dup_file(self._file) as update_fp: |
9bc3687e1e5e
logfile: Add an index, and don't keep everything in RAM.
Paul Fisher <paul@pfish.zone>
parents:
24
diff
changeset
|
193 if self._index: |
9bc3687e1e5e
logfile: Add an index, and don't keep everything in RAM.
Paul Fisher <paul@pfish.zone>
parents:
24
diff
changeset
|
194 last_idx = self._index[-1] |
9bc3687e1e5e
logfile: Add an index, and don't keep everything in RAM.
Paul Fisher <paul@pfish.zone>
parents:
24
diff
changeset
|
195 update_fp.seek(last_idx.byte) |
9bc3687e1e5e
logfile: Add an index, and don't keep everything in RAM.
Paul Fisher <paul@pfish.zone>
parents:
24
diff
changeset
|
196 current_count = last_idx.entry_count |
9bc3687e1e5e
logfile: Add an index, and don't keep everything in RAM.
Paul Fisher <paul@pfish.zone>
parents:
24
diff
changeset
|
197 decoder = bson.decode_file_iter( |
9bc3687e1e5e
logfile: Add an index, and don't keep everything in RAM.
Paul Fisher <paul@pfish.zone>
parents:
24
diff
changeset
|
198 update_fp, codec_options=common.BSON_OPTIONS) |
9bc3687e1e5e
logfile: Add an index, and don't keep everything in RAM.
Paul Fisher <paul@pfish.zone>
parents:
24
diff
changeset
|
199 try: |
9bc3687e1e5e
logfile: Add an index, and don't keep everything in RAM.
Paul Fisher <paul@pfish.zone>
parents:
24
diff
changeset
|
200 # Skip the current index entry. |
9bc3687e1e5e
logfile: Add an index, and don't keep everything in RAM.
Paul Fisher <paul@pfish.zone>
parents:
24
diff
changeset
|
201 next(decoder) |
9bc3687e1e5e
logfile: Add an index, and don't keep everything in RAM.
Paul Fisher <paul@pfish.zone>
parents:
24
diff
changeset
|
202 current_count += 1 |
9bc3687e1e5e
logfile: Add an index, and don't keep everything in RAM.
Paul Fisher <paul@pfish.zone>
parents:
24
diff
changeset
|
203 current_byte = update_fp.tell() |
9bc3687e1e5e
logfile: Add an index, and don't keep everything in RAM.
Paul Fisher <paul@pfish.zone>
parents:
24
diff
changeset
|
204 except StopIteration: |
9bc3687e1e5e
logfile: Add an index, and don't keep everything in RAM.
Paul Fisher <paul@pfish.zone>
parents:
24
diff
changeset
|
205 # If there are no more entries, don't update the index. |
9bc3687e1e5e
logfile: Add an index, and don't keep everything in RAM.
Paul Fisher <paul@pfish.zone>
parents:
24
diff
changeset
|
206 return |
9bc3687e1e5e
logfile: Add an index, and don't keep everything in RAM.
Paul Fisher <paul@pfish.zone>
parents:
24
diff
changeset
|
207 else: |
9bc3687e1e5e
logfile: Add an index, and don't keep everything in RAM.
Paul Fisher <paul@pfish.zone>
parents:
24
diff
changeset
|
208 current_byte = 0 |
9bc3687e1e5e
logfile: Add an index, and don't keep everything in RAM.
Paul Fisher <paul@pfish.zone>
parents:
24
diff
changeset
|
209 update_fp.seek(current_byte, os.SEEK_SET) |
9bc3687e1e5e
logfile: Add an index, and don't keep everything in RAM.
Paul Fisher <paul@pfish.zone>
parents:
24
diff
changeset
|
210 current_count = 0 |
9bc3687e1e5e
logfile: Add an index, and don't keep everything in RAM.
Paul Fisher <paul@pfish.zone>
parents:
24
diff
changeset
|
211 entries = bson.decode_file_iter( |
9bc3687e1e5e
logfile: Add an index, and don't keep everything in RAM.
Paul Fisher <paul@pfish.zone>
parents:
24
diff
changeset
|
212 update_fp, codec_options=common.BSON_OPTIONS) |
9bc3687e1e5e
logfile: Add an index, and don't keep everything in RAM.
Paul Fisher <paul@pfish.zone>
parents:
24
diff
changeset
|
213 for entry in entries: |
9bc3687e1e5e
logfile: Add an index, and don't keep everything in RAM.
Paul Fisher <paul@pfish.zone>
parents:
24
diff
changeset
|
214 if current_count % self._index_gap == 0: |
9bc3687e1e5e
logfile: Add an index, and don't keep everything in RAM.
Paul Fisher <paul@pfish.zone>
parents:
24
diff
changeset
|
215 idx_entry = IndexEntry( |
9bc3687e1e5e
logfile: Add an index, and don't keep everything in RAM.
Paul Fisher <paul@pfish.zone>
parents:
24
diff
changeset
|
216 entry_count=current_count, |
9bc3687e1e5e
logfile: Add an index, and don't keep everything in RAM.
Paul Fisher <paul@pfish.zone>
parents:
24
diff
changeset
|
217 entry_key=entry[self._sample_field], |
9bc3687e1e5e
logfile: Add an index, and don't keep everything in RAM.
Paul Fisher <paul@pfish.zone>
parents:
24
diff
changeset
|
218 byte=current_byte) |
9bc3687e1e5e
logfile: Add an index, and don't keep everything in RAM.
Paul Fisher <paul@pfish.zone>
parents:
24
diff
changeset
|
219 self._index.append(idx_entry) |
9bc3687e1e5e
logfile: Add an index, and don't keep everything in RAM.
Paul Fisher <paul@pfish.zone>
parents:
24
diff
changeset
|
220 self._index_file.truncate() |
9bc3687e1e5e
logfile: Add an index, and don't keep everything in RAM.
Paul Fisher <paul@pfish.zone>
parents:
24
diff
changeset
|
221 self._index_file.write( |
9bc3687e1e5e
logfile: Add an index, and don't keep everything in RAM.
Paul Fisher <paul@pfish.zone>
parents:
24
diff
changeset
|
222 common.bson_encode(idx_entry.to_dict())) |
9bc3687e1e5e
logfile: Add an index, and don't keep everything in RAM.
Paul Fisher <paul@pfish.zone>
parents:
24
diff
changeset
|
223 current_count += 1 |
9bc3687e1e5e
logfile: Add an index, and don't keep everything in RAM.
Paul Fisher <paul@pfish.zone>
parents:
24
diff
changeset
|
224 current_byte = update_fp.tell() |
9bc3687e1e5e
logfile: Add an index, and don't keep everything in RAM.
Paul Fisher <paul@pfish.zone>
parents:
24
diff
changeset
|
225 self._index_file.flush() |
9bc3687e1e5e
logfile: Add an index, and don't keep everything in RAM.
Paul Fisher <paul@pfish.zone>
parents:
24
diff
changeset
|
226 |
9bc3687e1e5e
logfile: Add an index, and don't keep everything in RAM.
Paul Fisher <paul@pfish.zone>
parents:
24
diff
changeset
|
227 def _catch_up_index(self) -> None: |
9bc3687e1e5e
logfile: Add an index, and don't keep everything in RAM.
Paul Fisher <paul@pfish.zone>
parents:
24
diff
changeset
|
228 # Preconditions: |
9bc3687e1e5e
logfile: Add an index, and don't keep everything in RAM.
Paul Fisher <paul@pfish.zone>
parents:
24
diff
changeset
|
229 # - At least a read lock is held. |
9bc3687e1e5e
logfile: Add an index, and don't keep everything in RAM.
Paul Fisher <paul@pfish.zone>
parents:
24
diff
changeset
|
230 pointer = self._index_file.tell() |
9bc3687e1e5e
logfile: Add an index, and don't keep everything in RAM.
Paul Fisher <paul@pfish.zone>
parents:
24
diff
changeset
|
231 try: |
9bc3687e1e5e
logfile: Add an index, and don't keep everything in RAM.
Paul Fisher <paul@pfish.zone>
parents:
24
diff
changeset
|
232 index_entries = bson.decode_file_iter( |
9bc3687e1e5e
logfile: Add an index, and don't keep everything in RAM.
Paul Fisher <paul@pfish.zone>
parents:
24
diff
changeset
|
233 self._index_file, codec_options=common.BSON_OPTIONS) |
9bc3687e1e5e
logfile: Add an index, and don't keep everything in RAM.
Paul Fisher <paul@pfish.zone>
parents:
24
diff
changeset
|
234 for entry_dict in index_entries: |
9bc3687e1e5e
logfile: Add an index, and don't keep everything in RAM.
Paul Fisher <paul@pfish.zone>
parents:
24
diff
changeset
|
235 entry = IndexEntry.from_dict(entry_dict) |
9bc3687e1e5e
logfile: Add an index, and don't keep everything in RAM.
Paul Fisher <paul@pfish.zone>
parents:
24
diff
changeset
|
236 self._index.append(entry) |
9bc3687e1e5e
logfile: Add an index, and don't keep everything in RAM.
Paul Fisher <paul@pfish.zone>
parents:
24
diff
changeset
|
237 pointer = self._index_file.tell() |
9bc3687e1e5e
logfile: Add an index, and don't keep everything in RAM.
Paul Fisher <paul@pfish.zone>
parents:
24
diff
changeset
|
238 except bson.InvalidBSON: |
9bc3687e1e5e
logfile: Add an index, and don't keep everything in RAM.
Paul Fisher <paul@pfish.zone>
parents:
24
diff
changeset
|
239 pass # We have reached the last valid BSON document. Bail. |
9bc3687e1e5e
logfile: Add an index, and don't keep everything in RAM.
Paul Fisher <paul@pfish.zone>
parents:
24
diff
changeset
|
240 self._index_file.seek(pointer, os.SEEK_SET) |
9bc3687e1e5e
logfile: Add an index, and don't keep everything in RAM.
Paul Fisher <paul@pfish.zone>
parents:
24
diff
changeset
|
241 |
9bc3687e1e5e
logfile: Add an index, and don't keep everything in RAM.
Paul Fisher <paul@pfish.zone>
parents:
24
diff
changeset
|
242 def __del__(self) -> None: |
24
20c8ec56e447
logfile: Pull logfile thread out of Logger.
Paul Fisher <paul@pfish.zone>
parents:
21
diff
changeset
|
243 self.close() |
21
beb42c835c52
Make weather server handle arbitrary data:
Paul Fisher <paul@pfish.zone>
parents:
0
diff
changeset
|
244 |
31
9bc3687e1e5e
logfile: Add an index, and don't keep everything in RAM.
Paul Fisher <paul@pfish.zone>
parents:
24
diff
changeset
|
245 def close(self) -> None: |
24
20c8ec56e447
logfile: Pull logfile thread out of Logger.
Paul Fisher <paul@pfish.zone>
parents:
21
diff
changeset
|
246 self._queue.put(_POISON) |
31
9bc3687e1e5e
logfile: Add an index, and don't keep everything in RAM.
Paul Fisher <paul@pfish.zone>
parents:
24
diff
changeset
|
247 self._thread.join() |
0
efe7a1eff167
Create initial logger for weather server.
Paul Fisher <paul@pfish.zone>
parents:
diff
changeset
|
248 |
24
20c8ec56e447
logfile: Pull logfile thread out of Logger.
Paul Fisher <paul@pfish.zone>
parents:
21
diff
changeset
|
249 |
31
9bc3687e1e5e
logfile: Add an index, and don't keep everything in RAM.
Paul Fisher <paul@pfish.zone>
parents:
24
diff
changeset
|
250 def _index_filename(filename: str) -> str: |
9bc3687e1e5e
logfile: Add an index, and don't keep everything in RAM.
Paul Fisher <paul@pfish.zone>
parents:
24
diff
changeset
|
251 return filename + '.index.bson' |
24
20c8ec56e447
logfile: Pull logfile thread out of Logger.
Paul Fisher <paul@pfish.zone>
parents:
21
diff
changeset
|
252 |
20c8ec56e447
logfile: Pull logfile thread out of Logger.
Paul Fisher <paul@pfish.zone>
parents:
21
diff
changeset
|
253 |
20c8ec56e447
logfile: Pull logfile thread out of Logger.
Paul Fisher <paul@pfish.zone>
parents:
21
diff
changeset
|
254 @contextlib.contextmanager |
20c8ec56e447
logfile: Pull logfile thread out of Logger.
Paul Fisher <paul@pfish.zone>
parents:
21
diff
changeset
|
255 def _file_lock(file: t.BinaryIO, operation: int) -> t.Iterator[None]: |
20c8ec56e447
logfile: Pull logfile thread out of Logger.
Paul Fisher <paul@pfish.zone>
parents:
21
diff
changeset
|
256 assert operation in (fcntl.LOCK_SH, fcntl.LOCK_EX), 'Invalid operation.' |
20c8ec56e447
logfile: Pull logfile thread out of Logger.
Paul Fisher <paul@pfish.zone>
parents:
21
diff
changeset
|
257 fcntl.flock(file, operation) |
20c8ec56e447
logfile: Pull logfile thread out of Logger.
Paul Fisher <paul@pfish.zone>
parents:
21
diff
changeset
|
258 try: |
20c8ec56e447
logfile: Pull logfile thread out of Logger.
Paul Fisher <paul@pfish.zone>
parents:
21
diff
changeset
|
259 yield |
20c8ec56e447
logfile: Pull logfile thread out of Logger.
Paul Fisher <paul@pfish.zone>
parents:
21
diff
changeset
|
260 finally: |
20c8ec56e447
logfile: Pull logfile thread out of Logger.
Paul Fisher <paul@pfish.zone>
parents:
21
diff
changeset
|
261 fcntl.flock(file, fcntl.LOCK_UN) |
20c8ec56e447
logfile: Pull logfile thread out of Logger.
Paul Fisher <paul@pfish.zone>
parents:
21
diff
changeset
|
262 |
20c8ec56e447
logfile: Pull logfile thread out of Logger.
Paul Fisher <paul@pfish.zone>
parents:
21
diff
changeset
|
263 |
20c8ec56e447
logfile: Pull logfile thread out of Logger.
Paul Fisher <paul@pfish.zone>
parents:
21
diff
changeset
|
264 def _size(file: t.BinaryIO) -> int: |
20c8ec56e447
logfile: Pull logfile thread out of Logger.
Paul Fisher <paul@pfish.zone>
parents:
21
diff
changeset
|
265 return os.stat(file.fileno()).st_size |
20c8ec56e447
logfile: Pull logfile thread out of Logger.
Paul Fisher <paul@pfish.zone>
parents:
21
diff
changeset
|
266 |
21
beb42c835c52
Make weather server handle arbitrary data:
Paul Fisher <paul@pfish.zone>
parents:
0
diff
changeset
|
267 |
31
9bc3687e1e5e
logfile: Add an index, and don't keep everything in RAM.
Paul Fisher <paul@pfish.zone>
parents:
24
diff
changeset
|
268 T = t.TypeVar('T') |
9bc3687e1e5e
logfile: Add an index, and don't keep everything in RAM.
Paul Fisher <paul@pfish.zone>
parents:
24
diff
changeset
|
269 |
9bc3687e1e5e
logfile: Add an index, and don't keep everything in RAM.
Paul Fisher <paul@pfish.zone>
parents:
24
diff
changeset
|
270 |
9bc3687e1e5e
logfile: Add an index, and don't keep everything in RAM.
Paul Fisher <paul@pfish.zone>
parents:
24
diff
changeset
|
271 @attr.s(auto_attribs=True, frozen=True, slots=True) |
9bc3687e1e5e
logfile: Add an index, and don't keep everything in RAM.
Paul Fisher <paul@pfish.zone>
parents:
24
diff
changeset
|
272 class IndexEntry: |
9bc3687e1e5e
logfile: Add an index, and don't keep everything in RAM.
Paul Fisher <paul@pfish.zone>
parents:
24
diff
changeset
|
273 entry_count: int |
9bc3687e1e5e
logfile: Add an index, and don't keep everything in RAM.
Paul Fisher <paul@pfish.zone>
parents:
24
diff
changeset
|
274 entry_key: object |
9bc3687e1e5e
logfile: Add an index, and don't keep everything in RAM.
Paul Fisher <paul@pfish.zone>
parents:
24
diff
changeset
|
275 byte: int |
9bc3687e1e5e
logfile: Add an index, and don't keep everything in RAM.
Paul Fisher <paul@pfish.zone>
parents:
24
diff
changeset
|
276 |
9bc3687e1e5e
logfile: Add an index, and don't keep everything in RAM.
Paul Fisher <paul@pfish.zone>
parents:
24
diff
changeset
|
277 @classmethod |
9bc3687e1e5e
logfile: Add an index, and don't keep everything in RAM.
Paul Fisher <paul@pfish.zone>
parents:
24
diff
changeset
|
278 def from_dict(cls: t.Type[T], d: t.Dict[str, t.Any]) -> T: |
9bc3687e1e5e
logfile: Add an index, and don't keep everything in RAM.
Paul Fisher <paul@pfish.zone>
parents:
24
diff
changeset
|
279 return cls(**{f.name: d[f.name] for f in attr.fields(cls)}) |
9bc3687e1e5e
logfile: Add an index, and don't keep everything in RAM.
Paul Fisher <paul@pfish.zone>
parents:
24
diff
changeset
|
280 |
9bc3687e1e5e
logfile: Add an index, and don't keep everything in RAM.
Paul Fisher <paul@pfish.zone>
parents:
24
diff
changeset
|
281 def to_dict(self) -> t.Dict[str, object]: |
9bc3687e1e5e
logfile: Add an index, and don't keep everything in RAM.
Paul Fisher <paul@pfish.zone>
parents:
24
diff
changeset
|
282 return attr.asdict(self, recurse=False) |
21
beb42c835c52
Make weather server handle arbitrary data:
Paul Fisher <paul@pfish.zone>
parents:
0
diff
changeset
|
283 |
0
efe7a1eff167
Create initial logger for weather server.
Paul Fisher <paul@pfish.zone>
parents:
diff
changeset
|
284 |
efe7a1eff167
Create initial logger for weather server.
Paul Fisher <paul@pfish.zone>
parents:
diff
changeset
|
285 def _open_or_create(path: str) -> t.BinaryIO: |
efe7a1eff167
Create initial logger for weather server.
Paul Fisher <paul@pfish.zone>
parents:
diff
changeset
|
286 while True: |
efe7a1eff167
Create initial logger for weather server.
Paul Fisher <paul@pfish.zone>
parents:
diff
changeset
|
287 try: |
efe7a1eff167
Create initial logger for weather server.
Paul Fisher <paul@pfish.zone>
parents:
diff
changeset
|
288 return open(path, 'r+b') |
efe7a1eff167
Create initial logger for weather server.
Paul Fisher <paul@pfish.zone>
parents:
diff
changeset
|
289 except FileNotFoundError: |
efe7a1eff167
Create initial logger for weather server.
Paul Fisher <paul@pfish.zone>
parents:
diff
changeset
|
290 pass |
efe7a1eff167
Create initial logger for weather server.
Paul Fisher <paul@pfish.zone>
parents:
diff
changeset
|
291 try: |
efe7a1eff167
Create initial logger for weather server.
Paul Fisher <paul@pfish.zone>
parents:
diff
changeset
|
292 return open(path, 'x+b') |
efe7a1eff167
Create initial logger for weather server.
Paul Fisher <paul@pfish.zone>
parents:
diff
changeset
|
293 except FileExistsError: |
efe7a1eff167
Create initial logger for weather server.
Paul Fisher <paul@pfish.zone>
parents:
diff
changeset
|
294 pass |
31
9bc3687e1e5e
logfile: Add an index, and don't keep everything in RAM.
Paul Fisher <paul@pfish.zone>
parents:
24
diff
changeset
|
295 |
9bc3687e1e5e
logfile: Add an index, and don't keep everything in RAM.
Paul Fisher <paul@pfish.zone>
parents:
24
diff
changeset
|
296 |
9bc3687e1e5e
logfile: Add an index, and don't keep everything in RAM.
Paul Fisher <paul@pfish.zone>
parents:
24
diff
changeset
|
297 def _dup_file(file: t.BinaryIO) -> t.BinaryIO: |
9bc3687e1e5e
logfile: Add an index, and don't keep everything in RAM.
Paul Fisher <paul@pfish.zone>
parents:
24
diff
changeset
|
298 duplicate = os.dup(file.fileno()) |
9bc3687e1e5e
logfile: Add an index, and don't keep everything in RAM.
Paul Fisher <paul@pfish.zone>
parents:
24
diff
changeset
|
299 return os.fdopen(duplicate, 'r+b') |