Skip to content

Commit b660669

Browse files
committed
Fix PQ file path migration
1 parent 1eab961 commit b660669

File tree

1 file changed

+37
-2
lines changed

1 file changed

+37
-2
lines changed

engine/src/main/java/com/arcadedb/index/vector/LSMVectorIndex.java

Lines changed: 37 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,8 @@
5050
import java.io.File;
5151
import java.io.IOException;
5252
import java.nio.ByteBuffer;
53+
import java.nio.file.Files;
54+
import java.nio.file.StandardCopyOption;
5355
import java.util.*;
5456
import java.util.concurrent.atomic.AtomicBoolean;
5557
import java.util.concurrent.atomic.AtomicInteger;
@@ -244,7 +246,7 @@ public LSMVectorIndex(final DatabaseInternal database, final String name, final
244246

245247
// Create PQ file handler for Product Quantization (zero-disk-I/O search)
246248
// Note: PQ file uses direct I/O (not ArcadeDB pages) since it's loaded entirely into memory
247-
this.pqFile = new LSMVectorIndexPQFile(filePath);
249+
this.pqFile = createPQFileWithFallback(mutable.getFilePath());
248250

249251
LogManager.instance()
250252
.log(this, Level.FINE, "Created LSMVectorIndex: indexName=%s, vectorFileId=%d, graphFileId=%d", indexName,
@@ -286,7 +288,7 @@ protected LSMVectorIndex(final DatabaseInternal database, final String name, fin
286288

287289
// Create PQ file handler (for zero-disk-I/O search)
288290
// PQ data will be loaded after schema loads metadata (see loadVectorsAfterSchemaLoad)
289-
this.pqFile = new LSMVectorIndexPQFile(filePath);
291+
this.pqFile = createPQFileWithFallback(mutable.getFilePath());
290292

291293
// Initialize compaction fields
292294
this.currentMutablePages = new AtomicInteger(mutable.getTotalPages());
@@ -309,6 +311,39 @@ protected LSMVectorIndex(final DatabaseInternal database, final String name, fin
309311
// See loadVectorsAfterSchemaLoad() method which is called by LSMVectorIndexMutable.onAfterSchemaLoad()
310312
}
311313

314+
private LSMVectorIndexPQFile createPQFileWithFallback(final String primaryBasePath) {
315+
// Use the component file path as canonical. If legacy PQ exists at a shorter base name, migrate it once.
316+
final LSMVectorIndexPQFile pq = new LSMVectorIndexPQFile(primaryBasePath);
317+
318+
// Derive a legacy base path by stripping the first extension (e.g., drop .4.262144.v0.lsmvecidx)
319+
String legacyBasePath = null;
320+
final int dot = primaryBasePath.indexOf('.');
321+
if (dot > 0) {
322+
legacyBasePath = primaryBasePath.substring(0, dot);
323+
}
324+
325+
if (!pq.exists() && legacyBasePath != null) {
326+
final LSMVectorIndexPQFile legacyPQ = new LSMVectorIndexPQFile(legacyBasePath);
327+
if (legacyPQ.exists()) {
328+
try {
329+
final var targetParent = pq.getFilePath().getParent();
330+
if (targetParent != null && !Files.exists(targetParent)) {
331+
Files.createDirectories(targetParent);
332+
}
333+
Files.move(legacyPQ.getFilePath(), pq.getFilePath(), StandardCopyOption.REPLACE_EXISTING);
334+
LogManager.instance().log(this, Level.INFO,
335+
"Migrated PQ file from legacy path %s to canonical %s", legacyPQ.getFilePath(), pq.getFilePath());
336+
} catch (final Exception e) {
337+
LogManager.instance().log(this, Level.WARNING,
338+
"Failed to migrate PQ file from legacy path %s to canonical %s: %s", legacyPQ.getFilePath(), pq.getFilePath(),
339+
e.getMessage());
340+
}
341+
}
342+
}
343+
344+
return pq;
345+
}
346+
312347
/**
313348
* Load vectors from pages after schema has loaded metadata.
314349
* Called by LSMVectorIndexMutable.onAfterSchemaLoad() after dimensions are set from schema.json.

0 commit comments

Comments
 (0)