Skip to content

Commit 1900745

Browse files
Add try/finally and checked writes to IndexSerializer
1 parent 851a101 commit 1900745

File tree

1 file changed

+53
-36
lines changed

1 file changed

+53
-36
lines changed

src/Persistence/IndexSerializer.php

Lines changed: 53 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -70,29 +70,31 @@ public function writeHnsw(string $path, array $state): void
7070

7171
$fh = fopen($path, 'wb');
7272
if ($fh === false) {
73-
throw new \RuntimeException("Failed to open hnsw.bin for writing: {$path}");
73+
throw new \RuntimeException("Failed to open file for writing: {$path}");
7474
}
7575

76-
fwrite($fh, self::HNSW_MAGIC);
77-
fwrite($fh, pack('C', self::VERSION));
78-
fwrite($fh, pack('NNNN', $dim, $nodeCount, $ep, (int) $state['maxLayer']));
76+
try {
77+
$this->checkedWrite($fh, self::HNSW_MAGIC);
78+
$this->checkedWrite($fh, pack('C', self::VERSION));
79+
$this->checkedWrite($fh, pack('NNNN', $dim, $nodeCount, $ep, (int) $state['maxLayer']));
7980

80-
foreach ($nodes as $nodeId => $node) {
81-
fwrite($fh, pack('NN', $nodeId, $node['maxLayer']));
82-
if ($dim > 0) {
83-
fwrite($fh, pack('d*', ...$node['vector']));
84-
}
85-
for ($l = 0; $l <= $node['maxLayer']; $l++) {
86-
$conns = $node['connections'][$l] ?? [];
87-
$cnt = count($conns);
88-
fwrite($fh, pack('N', $cnt));
89-
if ($cnt > 0) {
90-
fwrite($fh, pack('N*', ...$conns));
81+
foreach ($nodes as $nodeId => $node) {
82+
$this->checkedWrite($fh, pack('NN', $nodeId, $node['maxLayer']));
83+
if ($dim > 0) {
84+
$this->checkedWrite($fh, pack('d*', ...$node['vector']));
85+
}
86+
for ($l = 0; $l <= $node['maxLayer']; $l++) {
87+
$conns = $node['connections'][$l] ?? [];
88+
$cnt = count($conns);
89+
$this->checkedWrite($fh, pack('N', $cnt));
90+
if ($cnt > 0) {
91+
$this->checkedWrite($fh, pack('N*', ...$conns));
92+
}
9193
}
9294
}
95+
} finally {
96+
fclose($fh);
9397
}
94-
95-
fclose($fh);
9698
}
9799

98100
/**
@@ -192,31 +194,33 @@ public function writeBm25(string $path, array $state): void
192194
{
193195
$fh = fopen($path, 'wb');
194196
if ($fh === false) {
195-
throw new \RuntimeException("Failed to open bm25.bin for writing: {$path}");
197+
throw new \RuntimeException("Failed to open file for writing: {$path}");
196198
}
197199

198-
fwrite($fh, self::BM25_MAGIC);
199-
fwrite($fh, pack('C', self::VERSION));
200-
fwrite($fh, pack('N', $state['totalTokens']));
200+
try {
201+
$this->checkedWrite($fh, self::BM25_MAGIC);
202+
$this->checkedWrite($fh, pack('C', self::VERSION));
203+
$this->checkedWrite($fh, pack('N', $state['totalTokens']));
201204

202-
$docLengths = $state['docLengths'];
203-
fwrite($fh, pack('N', count($docLengths)));
204-
foreach ($docLengths as $nodeId => $length) {
205-
fwrite($fh, pack('NN', $nodeId, $length));
206-
}
205+
$docLengths = $state['docLengths'];
206+
$this->checkedWrite($fh, pack('N', count($docLengths)));
207+
foreach ($docLengths as $nodeId => $length) {
208+
$this->checkedWrite($fh, pack('NN', $nodeId, $length));
209+
}
207210

208-
$invertedIndex = $state['invertedIndex'];
209-
fwrite($fh, pack('N', count($invertedIndex)));
210-
foreach ($invertedIndex as $term => $postings) {
211-
$termBytes = (string) $term;
212-
fwrite($fh, pack('n', strlen($termBytes)) . $termBytes);
213-
fwrite($fh, pack('N', count($postings)));
214-
foreach ($postings as $postNodeId => $tf) {
215-
fwrite($fh, pack('NN', $postNodeId, $tf));
211+
$invertedIndex = $state['invertedIndex'];
212+
$this->checkedWrite($fh, pack('N', count($invertedIndex)));
213+
foreach ($invertedIndex as $term => $postings) {
214+
$termBytes = (string) $term;
215+
$this->checkedWrite($fh, pack('n', strlen($termBytes)) . $termBytes);
216+
$this->checkedWrite($fh, pack('N', count($postings)));
217+
foreach ($postings as $postNodeId => $tf) {
218+
$this->checkedWrite($fh, pack('NN', $postNodeId, $tf));
219+
}
216220
}
221+
} finally {
222+
fclose($fh);
217223
}
218-
219-
fclose($fh);
220224
}
221225

222226
/**
@@ -290,4 +294,17 @@ public function readBm25(string $path): array
290294
'invertedIndex' => $invertedIndex,
291295
];
292296
}
297+
298+
/**
299+
* @param resource $fh
300+
*/
301+
private function checkedWrite($fh, string $data): void
302+
{
303+
$len = strlen($data);
304+
$written = fwrite($fh, $data);
305+
306+
if ($written !== $len) {
307+
throw new \RuntimeException("Failed to write {$len} bytes (wrote " . ($written === false ? '0' : $written) . ')');
308+
}
309+
}
293310
}

0 commit comments

Comments
 (0)