Skip to content

Commit feaf82a

Browse files
committed
more tests
1 parent ddd192e commit feaf82a

File tree

5 files changed

+207
-101
lines changed

5 files changed

+207
-101
lines changed

fdb-extensions/src/main/java/com/apple/foundationdb/async/hnsw/HNSW.java

Lines changed: 42 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -141,21 +141,6 @@ public static class Config {
141141
private final boolean useRaBitQ;
142142
private final int raBitQNumExBits;
143143

144-
protected Config(final int numDimensions) {
145-
this.random = DEFAULT_RANDOM;
146-
this.metric = DEFAULT_METRIC;
147-
this.numDimensions = numDimensions;
148-
this.useInlining = DEFAULT_USE_INLINING;
149-
this.m = DEFAULT_M;
150-
this.mMax = DEFAULT_M_MAX;
151-
this.mMax0 = DEFAULT_M_MAX_0;
152-
this.efConstruction = DEFAULT_EF_CONSTRUCTION;
153-
this.extendCandidates = DEFAULT_EXTEND_CANDIDATES;
154-
this.keepPrunedConnections = DEFAULT_KEEP_PRUNED_CONNECTIONS;
155-
this.useRaBitQ = DEFAULT_USE_RABITQ;
156-
this.raBitQNumExBits = DEFAULT_RABITQ_NUM_EX_BITS;
157-
}
158-
159144
protected Config(@Nonnull final Random random, @Nonnull final Metric metric, final int numDimensions,
160145
final boolean useInlining, final int m, final int mMax, final int mMax0,
161146
final int efConstruction, final boolean extendCandidates, final boolean keepPrunedConnections,
@@ -231,6 +216,37 @@ public ConfigBuilder toBuilder() {
231216
getRaBitQNumExBits());
232217
}
233218

219+
@Override
220+
public final boolean equals(final Object o) {
221+
if (!(o instanceof Config)) {
222+
return false;
223+
}
224+
225+
final Config config = (Config)o;
226+
return numDimensions == config.numDimensions && useInlining == config.useInlining && m == config.m &&
227+
mMax == config.mMax && mMax0 == config.mMax0 && efConstruction == config.efConstruction &&
228+
extendCandidates == config.extendCandidates &&
229+
keepPrunedConnections == config.keepPrunedConnections && useRaBitQ == config.useRaBitQ &&
230+
raBitQNumExBits == config.raBitQNumExBits && random.equals(config.random) &&
231+
metric == config.metric;
232+
}
233+
234+
@Override
235+
public int hashCode() {
236+
int result = metric.name().hashCode();
237+
result = 31 * result + numDimensions;
238+
result = 31 * result + Boolean.hashCode(useInlining);
239+
result = 31 * result + m;
240+
result = 31 * result + mMax;
241+
result = 31 * result + mMax0;
242+
result = 31 * result + efConstruction;
243+
result = 31 * result + Boolean.hashCode(extendCandidates);
244+
result = 31 * result + Boolean.hashCode(keepPrunedConnections);
245+
result = 31 * result + Boolean.hashCode(useRaBitQ);
246+
result = 31 * result + raBitQNumExBits;
247+
return result;
248+
}
249+
234250
@Override
235251
@Nonnull
236252
public String toString() {
@@ -409,6 +425,17 @@ public static ConfigBuilder newConfigBuilder() {
409425
return new ConfigBuilder();
410426
}
411427

428+
/**
429+
* Returns a default {@link Config}.
430+
* @param numDimensions number of dimensions
431+
* @return a new default {@code Config}.
432+
* @see ConfigBuilder#build
433+
*/
434+
@Nonnull
435+
public static Config defaultConfig(int numDimensions) {
436+
return new ConfigBuilder().build(numDimensions);
437+
}
438+
412439
/**
413440
* Creates a new {@code HNSW} instance using the default configuration, write listener, and read listener.
414441
* <p>

fdb-extensions/src/main/java/com/apple/foundationdb/async/hnsw/InliningStorageAdapter.java

Lines changed: 31 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -176,13 +176,26 @@ private Node<NodeReferenceWithVector> nodeFromRaw(final int layer,
176176
@Nonnull
177177
private NodeReferenceWithVector neighborFromRaw(final int layer, final @Nonnull byte[] key, final byte[] value) {
178178
final OnReadListener onReadListener = getOnReadListener();
179-
180179
onReadListener.onKeyValueRead(layer, key, value);
180+
181181
final Tuple neighborKeyTuple = getDataSubspace().unpack(key);
182182
final Tuple neighborValueTuple = Tuple.fromBytes(value);
183183

184-
final Tuple neighborPrimaryKey = neighborKeyTuple.getNestedTuple(2); // neighbor primary key
185-
final RealVector neighborVector = StorageAdapter.vectorFromTuple(getConfig(), neighborValueTuple); // the entire value is the vector
184+
return neighborFromTuples(neighborKeyTuple, neighborValueTuple);
185+
}
186+
187+
/**
188+
* Constructs a {@code NodeReferenceWithVector} from tuples retrieved from storage.
189+
* <p>
190+
* @param keyTuple the key tuple from the database, which contains the neighbor's primary key.
191+
* @param valueTuple the value tuple from the database, which represents the neighbor's vector.
192+
* @return a new {@link NodeReferenceWithVector} instance representing the deserialized neighbor.
193+
* @throws IllegalArgumentException if the key or value byte arrays are malformed and cannot be unpacked.
194+
*/
195+
@Nonnull
196+
private NodeReferenceWithVector neighborFromTuples(final @Nonnull Tuple keyTuple, final Tuple valueTuple) {
197+
final Tuple neighborPrimaryKey = keyTuple.getNestedTuple(2); // neighbor primary key
198+
final RealVector neighborVector = StorageAdapter.vectorFromTuple(getConfig(), valueTuple); // the entire value is the vector
186199
return new NodeReferenceWithVector(neighborPrimaryKey, neighborVector);
187200
}
188201

@@ -308,6 +321,7 @@ private byte[] getNeighborKey(final int layer,
308321
@Override
309322
public Iterable<Node<NodeReferenceWithVector>> scanLayer(@Nonnull final ReadTransaction readTransaction, int layer,
310323
@Nullable final Tuple lastPrimaryKey, int maxNumRead) {
324+
final OnReadListener onReadListener = getOnReadListener();
311325
final byte[] layerPrefix = getDataSubspace().pack(Tuple.from(layer));
312326
final Range range =
313327
lastPrimaryKey == null
@@ -317,30 +331,29 @@ public Iterable<Node<NodeReferenceWithVector>> scanLayer(@Nonnull final ReadTran
317331
final AsyncIterable<KeyValue> itemsIterable =
318332
readTransaction.getRange(range,
319333
maxNumRead, false, StreamingMode.ITERATOR);
320-
int numRead = 0;
321334
Tuple nodePrimaryKey = null;
322335
ImmutableList.Builder<Node<NodeReferenceWithVector>> nodeBuilder = ImmutableList.builder();
323-
ImmutableList.Builder<NodeReferenceWithVector> neighborsBuilder = ImmutableList.builder();
336+
ImmutableList.Builder<NodeReferenceWithVector> neighborsBuilder = null;
324337
for (final KeyValue item: itemsIterable) {
325-
final NodeReferenceWithVector neighbor =
326-
neighborFromRaw(layer, item.getKey(), item.getValue());
327-
final Tuple primaryKeyFromNodeReference = neighbor.getPrimaryKey();
328-
if (nodePrimaryKey == null) {
329-
nodePrimaryKey = primaryKeyFromNodeReference;
330-
} else {
331-
if (!nodePrimaryKey.equals(primaryKeyFromNodeReference)) {
338+
final byte[] key = item.getKey();
339+
final byte[] value = item.getValue();
340+
onReadListener.onKeyValueRead(layer, key, value);
341+
342+
final Tuple neighborKeyTuple = getDataSubspace().unpack(key);
343+
final Tuple neighborValueTuple = Tuple.fromBytes(value);
344+
final NodeReferenceWithVector neighbor = neighborFromTuples(neighborKeyTuple, neighborValueTuple);
345+
final Tuple nodePrimaryKeyFromNeighbor = neighborKeyTuple.getNestedTuple(1);
346+
if (nodePrimaryKey == null || !nodePrimaryKey.equals(nodePrimaryKeyFromNeighbor)) {
347+
if (nodePrimaryKey != null) {
332348
nodeBuilder.add(getNodeFactory().create(nodePrimaryKey, null, neighborsBuilder.build()));
333349
}
350+
nodePrimaryKey = nodePrimaryKeyFromNeighbor;
351+
neighborsBuilder = ImmutableList.builder();
334352
}
335353
neighborsBuilder.add(neighbor);
336-
numRead ++;
337-
}
338-
339-
// there may be a rest
340-
if (numRead > 0 && numRead < maxNumRead) {
341-
nodeBuilder.add(getNodeFactory().create(nodePrimaryKey, null, neighborsBuilder.build()));
342354
}
343355

356+
// there may be a rest; throw it away
344357
return nodeBuilder.build();
345358
}
346359
}

fdb-extensions/src/main/java/com/apple/foundationdb/async/hnsw/StorageAdapter.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -168,7 +168,7 @@ void writeNode(@Nonnull Transaction transaction, @Nonnull Node<N> node, int laye
168168
@Nonnull NeighborsChangeSet<N> changeSet);
169169

170170
/**
171-
* Scans a specified layer of the directory, returning an iterable sequence of nodes.
171+
* Scans a specified layer of the structure, returning an iterable sequence of nodes.
172172
* <p>
173173
* This method allows for paginated scanning of a layer. The scan can be started from the beginning of the layer by
174174
* passing {@code null} for the {@code lastPrimaryKey}, or it can be resumed from a previous point by providing the

0 commit comments

Comments
 (0)