Mercurial > personal > weather-server
annotate weather_server/logfile.py @ 39:b77c8e7d2742
Use zoneinfo rather than pytz.
author | Paul Fisher <paul@pfish.zone> |
---|---|
date | Tue, 01 Apr 2025 15:54:21 -0400 |
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 collections |
21
beb42c835c52
Make weather server handle arbitrary data:
Paul Fisher <paul@pfish.zone>
parents:
0
diff
changeset
|
5 import concurrent.futures as futures |
beb42c835c52
Make weather server handle arbitrary data:
Paul Fisher <paul@pfish.zone>
parents:
0
diff
changeset
|
6 import contextlib |
0
efe7a1eff167
Create initial logger for weather server.
Paul Fisher <paul@pfish.zone>
parents:
diff
changeset
|
7 import fcntl |
efe7a1eff167
Create initial logger for weather server.
Paul Fisher <paul@pfish.zone>
parents:
diff
changeset
|
8 import os |
21
beb42c835c52
Make weather server handle arbitrary data:
Paul Fisher <paul@pfish.zone>
parents:
0
diff
changeset
|
9 import queue |
0
efe7a1eff167
Create initial logger for weather server.
Paul Fisher <paul@pfish.zone>
parents:
diff
changeset
|
10 import threading |
efe7a1eff167
Create initial logger for weather server.
Paul Fisher <paul@pfish.zone>
parents:
diff
changeset
|
11 import typing as t |
efe7a1eff167
Create initial logger for weather server.
Paul Fisher <paul@pfish.zone>
parents:
diff
changeset
|
12 |
39
b77c8e7d2742
Use zoneinfo rather than pytz.
Paul Fisher <paul@pfish.zone>
parents:
31
diff
changeset
|
13 import attr |
0
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 |
31
9bc3687e1e5e
logfile: Add an index, and don't keep everything in RAM.
Paul Fisher <paul@pfish.zone>
parents:
24
diff
changeset
|
18 # 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
|
19 CACHED_ENTRIES = 16384 |
9bc3687e1e5e
logfile: Add an index, and don't keep everything in RAM.
Paul Fisher <paul@pfish.zone>
parents:
24
diff
changeset
|
20 |
9bc3687e1e5e
logfile: Add an index, and don't keep everything in RAM.
Paul Fisher <paul@pfish.zone>
parents:
24
diff
changeset
|
21 # 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
|
22 INDEX_GAP = 4096 |
9bc3687e1e5e
logfile: Add an index, and don't keep everything in RAM.
Paul Fisher <paul@pfish.zone>
parents:
24
diff
changeset
|
23 |
9bc3687e1e5e
logfile: Add an index, and don't keep everything in RAM.
Paul Fisher <paul@pfish.zone>
parents:
24
diff
changeset
|
24 |
21
beb42c835c52
Make weather server handle arbitrary data:
Paul Fisher <paul@pfish.zone>
parents:
0
diff
changeset
|
25 class _WriteRequest: |
0
efe7a1eff167
Create initial logger for weather server.
Paul Fisher <paul@pfish.zone>
parents:
diff
changeset
|
26 |
21
beb42c835c52
Make weather server handle arbitrary data:
Paul Fisher <paul@pfish.zone>
parents:
0
diff
changeset
|
27 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
|
28 """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
|
29 # 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
|
30 self.entries = entries |
beb42c835c52
Make weather server handle arbitrary data:
Paul Fisher <paul@pfish.zone>
parents:
0
diff
changeset
|
31 # 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
|
32 self.future = futures.Future() |
beb42c835c52
Make weather server handle arbitrary data:
Paul Fisher <paul@pfish.zone>
parents:
0
diff
changeset
|
33 |
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 class _ReadRequest: |
beb42c835c52
Make weather server handle arbitrary data:
Paul Fisher <paul@pfish.zone>
parents:
0
diff
changeset
|
36 |
beb42c835c52
Make weather server handle arbitrary data:
Paul Fisher <paul@pfish.zone>
parents:
0
diff
changeset
|
37 def __init__(self): |
beb42c835c52
Make weather server handle arbitrary data:
Paul Fisher <paul@pfish.zone>
parents:
0
diff
changeset
|
38 # 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
|
39 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
|
40 # 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
|
41 |
beb42c835c52
Make weather server handle arbitrary data:
Paul Fisher <paul@pfish.zone>
parents:
0
diff
changeset
|
42 |
24
20c8ec56e447
logfile: Pull logfile thread out of Logger.
Paul Fisher <paul@pfish.zone>
parents:
21
diff
changeset
|
43 # 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
|
44 _POISON = object() |
20c8ec56e447
logfile: Pull logfile thread out of Logger.
Paul Fisher <paul@pfish.zone>
parents:
21
diff
changeset
|
45 |
0
efe7a1eff167
Create initial logger for weather server.
Paul Fisher <paul@pfish.zone>
parents:
diff
changeset
|
46 |
efe7a1eff167
Create initial logger for weather server.
Paul Fisher <paul@pfish.zone>
parents:
diff
changeset
|
47 class Logger: |
24
20c8ec56e447
logfile: Pull logfile thread out of Logger.
Paul Fisher <paul@pfish.zone>
parents:
21
diff
changeset
|
48 """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
|
49 |
31
9bc3687e1e5e
logfile: Add an index, and don't keep everything in RAM.
Paul Fisher <paul@pfish.zone>
parents:
24
diff
changeset
|
50 _file: t.BinaryIO |
9bc3687e1e5e
logfile: Add an index, and don't keep everything in RAM.
Paul Fisher <paul@pfish.zone>
parents:
24
diff
changeset
|
51 _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
|
52 |
9bc3687e1e5e
logfile: Add an index, and don't keep everything in RAM.
Paul Fisher <paul@pfish.zone>
parents:
24
diff
changeset
|
53 def __init__( |
9bc3687e1e5e
logfile: Add an index, and don't keep everything in RAM.
Paul Fisher <paul@pfish.zone>
parents:
24
diff
changeset
|
54 self, |
9bc3687e1e5e
logfile: Add an index, and don't keep everything in RAM.
Paul Fisher <paul@pfish.zone>
parents:
24
diff
changeset
|
55 filename: str, |
9bc3687e1e5e
logfile: Add an index, and don't keep everything in RAM.
Paul Fisher <paul@pfish.zone>
parents:
24
diff
changeset
|
56 *, |
9bc3687e1e5e
logfile: Add an index, and don't keep everything in RAM.
Paul Fisher <paul@pfish.zone>
parents:
24
diff
changeset
|
57 sample_field: str, |
9bc3687e1e5e
logfile: Add an index, and don't keep everything in RAM.
Paul Fisher <paul@pfish.zone>
parents:
24
diff
changeset
|
58 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
|
59 index_gap: int = INDEX_GAP): |
24
20c8ec56e447
logfile: Pull logfile thread out of Logger.
Paul Fisher <paul@pfish.zone>
parents:
21
diff
changeset
|
60 """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
|
61 |
20c8ec56e447
logfile: Pull logfile thread out of Logger.
Paul Fisher <paul@pfish.zone>
parents:
21
diff
changeset
|
62 Args: |
20c8ec56e447
logfile: Pull logfile thread out of Logger.
Paul Fisher <paul@pfish.zone>
parents:
21
diff
changeset
|
63 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
|
64 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
|
65 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
|
66 """ |
31
9bc3687e1e5e
logfile: Add an index, and don't keep everything in RAM.
Paul Fisher <paul@pfish.zone>
parents:
24
diff
changeset
|
67 |
9bc3687e1e5e
logfile: Add an index, and don't keep everything in RAM.
Paul Fisher <paul@pfish.zone>
parents:
24
diff
changeset
|
68 self._filename = filename |
9bc3687e1e5e
logfile: Add an index, and don't keep everything in RAM.
Paul Fisher <paul@pfish.zone>
parents:
24
diff
changeset
|
69 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
|
70 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
|
71 |
21
beb42c835c52
Make weather server handle arbitrary data:
Paul Fisher <paul@pfish.zone>
parents:
0
diff
changeset
|
72 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
|
73 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
|
74 |
9bc3687e1e5e
logfile: Add an index, and don't keep everything in RAM.
Paul Fisher <paul@pfish.zone>
parents:
24
diff
changeset
|
75 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
|
76 self._thread = threading.Thread( |
24
20c8ec56e447
logfile: Pull logfile thread out of Logger.
Paul Fisher <paul@pfish.zone>
parents:
21
diff
changeset
|
77 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
|
78 target=self._writer_thread, |
24
20c8ec56e447
logfile: Pull logfile thread out of Logger.
Paul Fisher <paul@pfish.zone>
parents:
21
diff
changeset
|
79 daemon=True) |
31
9bc3687e1e5e
logfile: Add an index, and don't keep everything in RAM.
Paul Fisher <paul@pfish.zone>
parents:
24
diff
changeset
|
80 self._thread.start() |
9bc3687e1e5e
logfile: Add an index, and don't keep everything in RAM.
Paul Fisher <paul@pfish.zone>
parents:
24
diff
changeset
|
81 |
9bc3687e1e5e
logfile: Add an index, and don't keep everything in RAM.
Paul Fisher <paul@pfish.zone>
parents:
24
diff
changeset
|
82 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
|
83 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
|
84 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
|
85 self._start_future.result() |
21
beb42c835c52
Make weather server handle arbitrary data:
Paul Fisher <paul@pfish.zone>
parents:
0
diff
changeset
|
86 |
beb42c835c52
Make weather server handle arbitrary data:
Paul Fisher <paul@pfish.zone>
parents:
0
diff
changeset
|
87 @property |
31
9bc3687e1e5e
logfile: Add an index, and don't keep everything in RAM.
Paul Fisher <paul@pfish.zone>
parents:
24
diff
changeset
|
88 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
|
89 req = _ReadRequest() |
beb42c835c52
Make weather server handle arbitrary data:
Paul Fisher <paul@pfish.zone>
parents:
0
diff
changeset
|
90 self._queue.put(req) |
beb42c835c52
Make weather server handle arbitrary data:
Paul Fisher <paul@pfish.zone>
parents:
0
diff
changeset
|
91 return req.future.result() |
beb42c835c52
Make weather server handle arbitrary data:
Paul Fisher <paul@pfish.zone>
parents:
0
diff
changeset
|
92 |
beb42c835c52
Make weather server handle arbitrary data:
Paul Fisher <paul@pfish.zone>
parents:
0
diff
changeset
|
93 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
|
94 req = _WriteRequest(entries) |
beb42c835c52
Make weather server handle arbitrary data:
Paul Fisher <paul@pfish.zone>
parents:
0
diff
changeset
|
95 self._queue.put(req) |
beb42c835c52
Make weather server handle arbitrary data:
Paul Fisher <paul@pfish.zone>
parents:
0
diff
changeset
|
96 return req.future.result() |
beb42c835c52
Make weather server handle arbitrary data:
Paul Fisher <paul@pfish.zone>
parents:
0
diff
changeset
|
97 |
31
9bc3687e1e5e
logfile: Add an index, and don't keep everything in RAM.
Paul Fisher <paul@pfish.zone>
parents:
24
diff
changeset
|
98 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
|
99 try: |
9bc3687e1e5e
logfile: Add an index, and don't keep everything in RAM.
Paul Fisher <paul@pfish.zone>
parents:
24
diff
changeset
|
100 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
|
101 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
|
102 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
|
103 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
|
104 return |
9bc3687e1e5e
logfile: Add an index, and don't keep everything in RAM.
Paul Fisher <paul@pfish.zone>
parents:
24
diff
changeset
|
105 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
|
106 |
9bc3687e1e5e
logfile: Add an index, and don't keep everything in RAM.
Paul Fisher <paul@pfish.zone>
parents:
24
diff
changeset
|
107 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
|
108 running = True |
9bc3687e1e5e
logfile: Add an index, and don't keep everything in RAM.
Paul Fisher <paul@pfish.zone>
parents:
24
diff
changeset
|
109 while running: |
9bc3687e1e5e
logfile: Add an index, and don't keep everything in RAM.
Paul Fisher <paul@pfish.zone>
parents:
24
diff
changeset
|
110 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
|
111 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
|
112 # 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
|
113 running = False |
9bc3687e1e5e
logfile: Add an index, and don't keep everything in RAM.
Paul Fisher <paul@pfish.zone>
parents:
24
diff
changeset
|
114 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
|
115 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
|
116 continue |
9bc3687e1e5e
logfile: Add an index, and don't keep everything in RAM.
Paul Fisher <paul@pfish.zone>
parents:
24
diff
changeset
|
117 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
|
118 try: |
9bc3687e1e5e
logfile: Add an index, and don't keep everything in RAM.
Paul Fisher <paul@pfish.zone>
parents:
24
diff
changeset
|
119 self._catch_up() |
9bc3687e1e5e
logfile: Add an index, and don't keep everything in RAM.
Paul Fisher <paul@pfish.zone>
parents:
24
diff
changeset
|
120 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
|
121 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
|
122 else: |
9bc3687e1e5e
logfile: Add an index, and don't keep everything in RAM.
Paul Fisher <paul@pfish.zone>
parents:
24
diff
changeset
|
123 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
|
124 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
|
125 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
|
126 continue |
9bc3687e1e5e
logfile: Add an index, and don't keep everything in RAM.
Paul Fisher <paul@pfish.zone>
parents:
24
diff
changeset
|
127 try: |
9bc3687e1e5e
logfile: Add an index, and don't keep everything in RAM.
Paul Fisher <paul@pfish.zone>
parents:
24
diff
changeset
|
128 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
|
129 self._catch_up() |
9bc3687e1e5e
logfile: Add an index, and don't keep everything in RAM.
Paul Fisher <paul@pfish.zone>
parents:
24
diff
changeset
|
130 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
|
131 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
|
132 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
|
133 prev_key = None |
9bc3687e1e5e
logfile: Add an index, and don't keep everything in RAM.
Paul Fisher <paul@pfish.zone>
parents:
24
diff
changeset
|
134 else: |
9bc3687e1e5e
logfile: Add an index, and don't keep everything in RAM.
Paul Fisher <paul@pfish.zone>
parents:
24
diff
changeset
|
135 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
|
136 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
|
137 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
|
138 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
|
139 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
|
140 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
|
141 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
|
142 self._file.flush() |
9bc3687e1e5e
logfile: Add an index, and don't keep everything in RAM.
Paul Fisher <paul@pfish.zone>
parents:
24
diff
changeset
|
143 self._update_index() |
9bc3687e1e5e
logfile: Add an index, and don't keep everything in RAM.
Paul Fisher <paul@pfish.zone>
parents:
24
diff
changeset
|
144 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
|
145 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
|
146 else: |
9bc3687e1e5e
logfile: Add an index, and don't keep everything in RAM.
Paul Fisher <paul@pfish.zone>
parents:
24
diff
changeset
|
147 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
|
148 else: |
9bc3687e1e5e
logfile: Add an index, and don't keep everything in RAM.
Paul Fisher <paul@pfish.zone>
parents:
24
diff
changeset
|
149 raise AssertionError( |
9bc3687e1e5e
logfile: Add an index, and don't keep everything in RAM.
Paul Fisher <paul@pfish.zone>
parents:
24
diff
changeset
|
150 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
|
151 |
9bc3687e1e5e
logfile: Add an index, and don't keep everything in RAM.
Paul Fisher <paul@pfish.zone>
parents:
24
diff
changeset
|
152 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
|
153 # Preconditions: |
9bc3687e1e5e
logfile: Add an index, and don't keep everything in RAM.
Paul Fisher <paul@pfish.zone>
parents:
24
diff
changeset
|
154 # - 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
|
155 # - 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
|
156 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
|
157 if self._index: |
9bc3687e1e5e
logfile: Add an index, and don't keep everything in RAM.
Paul Fisher <paul@pfish.zone>
parents:
24
diff
changeset
|
158 # 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
|
159 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
|
160 # 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
|
161 # 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
|
162 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
|
163 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
|
164 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
|
165 # 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
|
166 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
|
167 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
|
168 break |
9bc3687e1e5e
logfile: Add an index, and don't keep everything in RAM.
Paul Fisher <paul@pfish.zone>
parents:
24
diff
changeset
|
169 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
|
170 self._data.clear() |
9bc3687e1e5e
logfile: Add an index, and don't keep everything in RAM.
Paul Fisher <paul@pfish.zone>
parents:
24
diff
changeset
|
171 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
|
172 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
|
173 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
|
174 try: |
9bc3687e1e5e
logfile: Add an index, and don't keep everything in RAM.
Paul Fisher <paul@pfish.zone>
parents:
24
diff
changeset
|
175 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
|
176 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
|
177 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
|
178 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
|
179 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
|
180 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
|
181 except bson.InvalidBSON: |
9bc3687e1e5e
logfile: Add an index, and don't keep everything in RAM.
Paul Fisher <paul@pfish.zone>
parents:
24
diff
changeset
|
182 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
|
183 # 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
|
184 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
|
185 |
9bc3687e1e5e
logfile: Add an index, and don't keep everything in RAM.
Paul Fisher <paul@pfish.zone>
parents:
24
diff
changeset
|
186 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
|
187 # Preconditions: |
9bc3687e1e5e
logfile: Add an index, and don't keep everything in RAM.
Paul Fisher <paul@pfish.zone>
parents:
24
diff
changeset
|
188 # - 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
|
189 # - 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
|
190 # - 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
|
191 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
|
192 if self._index: |
9bc3687e1e5e
logfile: Add an index, and don't keep everything in RAM.
Paul Fisher <paul@pfish.zone>
parents:
24
diff
changeset
|
193 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
|
194 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
|
195 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
|
196 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
|
197 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
|
198 try: |
9bc3687e1e5e
logfile: Add an index, and don't keep everything in RAM.
Paul Fisher <paul@pfish.zone>
parents:
24
diff
changeset
|
199 # 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
|
200 next(decoder) |
9bc3687e1e5e
logfile: Add an index, and don't keep everything in RAM.
Paul Fisher <paul@pfish.zone>
parents:
24
diff
changeset
|
201 current_count += 1 |
9bc3687e1e5e
logfile: Add an index, and don't keep everything in RAM.
Paul Fisher <paul@pfish.zone>
parents:
24
diff
changeset
|
202 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
|
203 except StopIteration: |
9bc3687e1e5e
logfile: Add an index, and don't keep everything in RAM.
Paul Fisher <paul@pfish.zone>
parents:
24
diff
changeset
|
204 # 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
|
205 return |
9bc3687e1e5e
logfile: Add an index, and don't keep everything in RAM.
Paul Fisher <paul@pfish.zone>
parents:
24
diff
changeset
|
206 else: |
9bc3687e1e5e
logfile: Add an index, and don't keep everything in RAM.
Paul Fisher <paul@pfish.zone>
parents:
24
diff
changeset
|
207 current_byte = 0 |
9bc3687e1e5e
logfile: Add an index, and don't keep everything in RAM.
Paul Fisher <paul@pfish.zone>
parents:
24
diff
changeset
|
208 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
|
209 current_count = 0 |
9bc3687e1e5e
logfile: Add an index, and don't keep everything in RAM.
Paul Fisher <paul@pfish.zone>
parents:
24
diff
changeset
|
210 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
|
211 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
|
212 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
|
213 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
|
214 idx_entry = IndexEntry( |
9bc3687e1e5e
logfile: Add an index, and don't keep everything in RAM.
Paul Fisher <paul@pfish.zone>
parents:
24
diff
changeset
|
215 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
|
216 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
|
217 byte=current_byte) |
9bc3687e1e5e
logfile: Add an index, and don't keep everything in RAM.
Paul Fisher <paul@pfish.zone>
parents:
24
diff
changeset
|
218 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
|
219 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
|
220 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
|
221 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
|
222 current_count += 1 |
9bc3687e1e5e
logfile: Add an index, and don't keep everything in RAM.
Paul Fisher <paul@pfish.zone>
parents:
24
diff
changeset
|
223 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
|
224 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
|
225 |
9bc3687e1e5e
logfile: Add an index, and don't keep everything in RAM.
Paul Fisher <paul@pfish.zone>
parents:
24
diff
changeset
|
226 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
|
227 # Preconditions: |
9bc3687e1e5e
logfile: Add an index, and don't keep everything in RAM.
Paul Fisher <paul@pfish.zone>
parents:
24
diff
changeset
|
228 # - 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
|
229 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
|
230 try: |
9bc3687e1e5e
logfile: Add an index, and don't keep everything in RAM.
Paul Fisher <paul@pfish.zone>
parents:
24
diff
changeset
|
231 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
|
232 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
|
233 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
|
234 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
|
235 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
|
236 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
|
237 except bson.InvalidBSON: |
9bc3687e1e5e
logfile: Add an index, and don't keep everything in RAM.
Paul Fisher <paul@pfish.zone>
parents:
24
diff
changeset
|
238 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
|
239 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
|
240 |
9bc3687e1e5e
logfile: Add an index, and don't keep everything in RAM.
Paul Fisher <paul@pfish.zone>
parents:
24
diff
changeset
|
241 def __del__(self) -> None: |
24
20c8ec56e447
logfile: Pull logfile thread out of Logger.
Paul Fisher <paul@pfish.zone>
parents:
21
diff
changeset
|
242 self.close() |
21
beb42c835c52
Make weather server handle arbitrary data:
Paul Fisher <paul@pfish.zone>
parents:
0
diff
changeset
|
243 |
31
9bc3687e1e5e
logfile: Add an index, and don't keep everything in RAM.
Paul Fisher <paul@pfish.zone>
parents:
24
diff
changeset
|
244 def close(self) -> None: |
24
20c8ec56e447
logfile: Pull logfile thread out of Logger.
Paul Fisher <paul@pfish.zone>
parents:
21
diff
changeset
|
245 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
|
246 self._thread.join() |
0
efe7a1eff167
Create initial logger for weather server.
Paul Fisher <paul@pfish.zone>
parents:
diff
changeset
|
247 |
24
20c8ec56e447
logfile: Pull logfile thread out of Logger.
Paul Fisher <paul@pfish.zone>
parents:
21
diff
changeset
|
248 |
31
9bc3687e1e5e
logfile: Add an index, and don't keep everything in RAM.
Paul Fisher <paul@pfish.zone>
parents:
24
diff
changeset
|
249 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
|
250 return filename + '.index.bson' |
24
20c8ec56e447
logfile: Pull logfile thread out of Logger.
Paul Fisher <paul@pfish.zone>
parents:
21
diff
changeset
|
251 |
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 @contextlib.contextmanager |
20c8ec56e447
logfile: Pull logfile thread out of Logger.
Paul Fisher <paul@pfish.zone>
parents:
21
diff
changeset
|
254 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
|
255 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
|
256 fcntl.flock(file, operation) |
20c8ec56e447
logfile: Pull logfile thread out of Logger.
Paul Fisher <paul@pfish.zone>
parents:
21
diff
changeset
|
257 try: |
20c8ec56e447
logfile: Pull logfile thread out of Logger.
Paul Fisher <paul@pfish.zone>
parents:
21
diff
changeset
|
258 yield |
20c8ec56e447
logfile: Pull logfile thread out of Logger.
Paul Fisher <paul@pfish.zone>
parents:
21
diff
changeset
|
259 finally: |
20c8ec56e447
logfile: Pull logfile thread out of Logger.
Paul Fisher <paul@pfish.zone>
parents:
21
diff
changeset
|
260 fcntl.flock(file, fcntl.LOCK_UN) |
20c8ec56e447
logfile: Pull logfile thread out of Logger.
Paul Fisher <paul@pfish.zone>
parents:
21
diff
changeset
|
261 |
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 def _size(file: t.BinaryIO) -> int: |
20c8ec56e447
logfile: Pull logfile thread out of Logger.
Paul Fisher <paul@pfish.zone>
parents:
21
diff
changeset
|
264 return os.stat(file.fileno()).st_size |
20c8ec56e447
logfile: Pull logfile thread out of Logger.
Paul Fisher <paul@pfish.zone>
parents:
21
diff
changeset
|
265 |
21
beb42c835c52
Make weather server handle arbitrary data:
Paul Fisher <paul@pfish.zone>
parents:
0
diff
changeset
|
266 |
31
9bc3687e1e5e
logfile: Add an index, and don't keep everything in RAM.
Paul Fisher <paul@pfish.zone>
parents:
24
diff
changeset
|
267 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
|
268 |
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 @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
|
271 class IndexEntry: |
9bc3687e1e5e
logfile: Add an index, and don't keep everything in RAM.
Paul Fisher <paul@pfish.zone>
parents:
24
diff
changeset
|
272 entry_count: int |
9bc3687e1e5e
logfile: Add an index, and don't keep everything in RAM.
Paul Fisher <paul@pfish.zone>
parents:
24
diff
changeset
|
273 entry_key: object |
9bc3687e1e5e
logfile: Add an index, and don't keep everything in RAM.
Paul Fisher <paul@pfish.zone>
parents:
24
diff
changeset
|
274 byte: int |
9bc3687e1e5e
logfile: Add an index, and don't keep everything in RAM.
Paul Fisher <paul@pfish.zone>
parents:
24
diff
changeset
|
275 |
9bc3687e1e5e
logfile: Add an index, and don't keep everything in RAM.
Paul Fisher <paul@pfish.zone>
parents:
24
diff
changeset
|
276 @classmethod |
9bc3687e1e5e
logfile: Add an index, and don't keep everything in RAM.
Paul Fisher <paul@pfish.zone>
parents:
24
diff
changeset
|
277 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
|
278 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
|
279 |
9bc3687e1e5e
logfile: Add an index, and don't keep everything in RAM.
Paul Fisher <paul@pfish.zone>
parents:
24
diff
changeset
|
280 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
|
281 return attr.asdict(self, recurse=False) |
21
beb42c835c52
Make weather server handle arbitrary data:
Paul Fisher <paul@pfish.zone>
parents:
0
diff
changeset
|
282 |
0
efe7a1eff167
Create initial logger for weather server.
Paul Fisher <paul@pfish.zone>
parents:
diff
changeset
|
283 |
efe7a1eff167
Create initial logger for weather server.
Paul Fisher <paul@pfish.zone>
parents:
diff
changeset
|
284 def _open_or_create(path: str) -> t.BinaryIO: |
efe7a1eff167
Create initial logger for weather server.
Paul Fisher <paul@pfish.zone>
parents:
diff
changeset
|
285 while True: |
efe7a1eff167
Create initial logger for weather server.
Paul Fisher <paul@pfish.zone>
parents:
diff
changeset
|
286 try: |
efe7a1eff167
Create initial logger for weather server.
Paul Fisher <paul@pfish.zone>
parents:
diff
changeset
|
287 return open(path, 'r+b') |
efe7a1eff167
Create initial logger for weather server.
Paul Fisher <paul@pfish.zone>
parents:
diff
changeset
|
288 except FileNotFoundError: |
efe7a1eff167
Create initial logger for weather server.
Paul Fisher <paul@pfish.zone>
parents:
diff
changeset
|
289 pass |
efe7a1eff167
Create initial logger for weather server.
Paul Fisher <paul@pfish.zone>
parents:
diff
changeset
|
290 try: |
efe7a1eff167
Create initial logger for weather server.
Paul Fisher <paul@pfish.zone>
parents:
diff
changeset
|
291 return open(path, 'x+b') |
efe7a1eff167
Create initial logger for weather server.
Paul Fisher <paul@pfish.zone>
parents:
diff
changeset
|
292 except FileExistsError: |
efe7a1eff167
Create initial logger for weather server.
Paul Fisher <paul@pfish.zone>
parents:
diff
changeset
|
293 pass |
31
9bc3687e1e5e
logfile: Add an index, and don't keep everything in RAM.
Paul Fisher <paul@pfish.zone>
parents:
24
diff
changeset
|
294 |
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 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
|
297 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
|
298 return os.fdopen(duplicate, 'r+b') |