Skip to content

Commit 831766a

Browse files
committed
Fix PQ file path migration
1 parent bcf9a0d commit 831766a

1 file changed

Lines changed: 37 additions & 2 deletions

File tree

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;
@@ -250,7 +252,7 @@ public LSMVectorIndex(final DatabaseInternal database, final String name, final
250252

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

255257
LogManager.instance()
256258
.log(this, Level.FINE, "Created LSMVectorIndex: indexName=%s, vectorFileId=%d, graphFileId=%d", indexName,
@@ -292,7 +294,7 @@ protected LSMVectorIndex(final DatabaseInternal database, final String name, fin
292294

293295
// Create PQ file handler (for zero-disk-I/O search)
294296
// PQ data will be loaded after schema loads metadata (see loadVectorsAfterSchemaLoad)
295-
this.pqFile = new LSMVectorIndexPQFile(filePath);
297+
this.pqFile = createPQFileWithFallback(mutable.getFilePath());
296298

297299
// Initialize compaction fields
298300
this.currentMutablePages = new AtomicInteger(mutable.getTotalPages());
@@ -315,6 +317,39 @@ protected LSMVectorIndex(final DatabaseInternal database, final String name, fin
315317
// See loadVectorsAfterSchemaLoad() method which is called by LSMVectorIndexMutable.onAfterSchemaLoad()
316318
}
317319

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

0 commit comments

Comments
 (0)