34
34
import org .opensearch .common .Randomness ;
35
35
import org .opensearch .common .cache .tier .keystore .RBMIntKeyLookupStore ;
36
36
import org .opensearch .common .cache .tier .keystore .RBMSizeEstimator ;
37
+ import org .opensearch .common .metrics .CounterMetric ;
37
38
import org .opensearch .test .OpenSearchTestCase ;
38
39
39
40
import java .util .ArrayList ;
41
+ import java .util .HashSet ;
40
42
import java .util .Random ;
41
43
import java .util .concurrent .Executors ;
42
44
import java .util .concurrent .Future ;
@@ -277,12 +279,10 @@ public void testNullInputs() throws Exception {
277
279
}
278
280
279
281
public void testMemoryCapValueInitialization () {
280
- // double[] logModulos = new double[] { 0.0, 31.2, 30, 29, 28, 13 };
281
- // 0, 31, 29, 28, 26
282
282
RBMIntKeyLookupStore .KeystoreModuloValue [] mods = RBMIntKeyLookupStore .KeystoreModuloValue .values ();
283
283
double [] expectedMultipliers = new double [] { 1.2 , 1.2 , 1 , 1 , 1 };
284
284
double [] expectedSlopes = new double [] { 0.637 , 0.637 , 0.619 , 0.614 , 0.629 };
285
- double [] expectedIntercepts = new double [] { 3.091 , 3.091 , 2.993 , 2.905 , 2.603 }; // check the numbers closer later
285
+ double [] expectedIntercepts = new double [] { 3.091 , 3.091 , 2.993 , 2.905 , 2.603 };
286
286
long memSizeCapInBytes = (long ) 100.0 * RBMSizeEstimator .BYTES_IN_MB ;
287
287
double delta = 0.01 ;
288
288
for (int i = 0 ; i < mods .length ; i ++) {
@@ -295,4 +295,106 @@ public void testMemoryCapValueInitialization() {
295
295
}
296
296
297
297
}
298
+
299
+ public void testRemovalLogic () throws Exception {
300
+ RBMIntKeyLookupStore .KeystoreModuloValue moduloValue = RBMIntKeyLookupStore .KeystoreModuloValue .TWO_TO_TWENTY_SIX ;
301
+ int modulo = moduloValue .getValue ();
302
+ RBMIntKeyLookupStore kls = new RBMIntKeyLookupStore (moduloValue , 0L );
303
+
304
+ // Test standard sequence: add K1, K2, K3 which all transform to C, then:
305
+ // Remove K3
306
+ // Remove K2, re-add it, re-remove it twice (duplicate should do nothing)
307
+ // Remove K1, which should finally actually remove everything
308
+ int c = -42 ;
309
+ int k1 = c + modulo ;
310
+ int k2 = c + 2 * modulo ;
311
+ int k3 = c + 3 * modulo ;
312
+ kls .add (k1 );
313
+ assertTrue (kls .contains (k1 ));
314
+ assertTrue (kls .contains (k3 ));
315
+ kls .add (k2 );
316
+ CounterMetric numCollisions = kls .getNumCollisionsForValue (k2 );
317
+ assertNotNull (numCollisions );
318
+ assertEquals (2 , numCollisions .count ());
319
+ kls .add (k3 );
320
+ assertEquals (3 , numCollisions .count ());
321
+ assertEquals (1 , kls .getSize ());
322
+
323
+ boolean removed = kls .remove (k3 );
324
+ assertFalse (removed );
325
+ HashSet <Integer > removalSet = kls .getRemovalSetForValue (k3 );
326
+ assertEquals (1 , removalSet .size ());
327
+ assertTrue (removalSet .contains (k3 ));
328
+ assertEquals (2 , numCollisions .count ());
329
+ assertEquals (1 , kls .getSize ());
330
+
331
+ removed = kls .remove (k2 );
332
+ assertFalse (removed );
333
+ assertEquals (2 , removalSet .size ());
334
+ assertTrue (removalSet .contains (k2 ));
335
+ assertEquals (1 , numCollisions .count ());
336
+ assertEquals (1 , kls .getSize ());
337
+
338
+ kls .add (k2 );
339
+ assertEquals (1 , removalSet .size ());
340
+ assertFalse (removalSet .contains (k2 ));
341
+ assertEquals (2 , numCollisions .count ());
342
+ assertEquals (1 , kls .getSize ());
343
+
344
+ removed = kls .remove (k2 );
345
+ assertFalse (removed );
346
+ assertEquals (2 , removalSet .size ());
347
+ assertTrue (removalSet .contains (k2 ));
348
+ assertEquals (1 , numCollisions .count ());
349
+ assertEquals (1 , kls .getSize ());
350
+
351
+ removed = kls .remove (k2 );
352
+ assertFalse (removed );
353
+ assertEquals (2 , removalSet .size ());
354
+ assertTrue (removalSet .contains (k2 ));
355
+ assertEquals (1 , numCollisions .count ());
356
+ assertEquals (1 , kls .getSize ());
357
+
358
+ removed = kls .remove (k1 );
359
+ assertTrue (removed );
360
+ assertNull (kls .getRemovalSetForValue (k1 ));
361
+ assertNull (kls .getNumCollisionsForValue (k1 ));
362
+ assertEquals (0 , kls .getSize ());
363
+ }
364
+
365
+ public void testRemovalLogicWithHashCollision () throws Exception {
366
+ RBMIntKeyLookupStore .KeystoreModuloValue moduloValue = RBMIntKeyLookupStore .KeystoreModuloValue .TWO_TO_TWENTY_SIX ;
367
+ int modulo = moduloValue .getValue ();
368
+ RBMIntKeyLookupStore kls = new RBMIntKeyLookupStore (moduloValue , 0L );
369
+
370
+ // Test adding K1 twice (maybe two keys hash to K1), then removing it twice.
371
+ // We expect it to be unable to remove the last one, but there should be no false negatives.
372
+ int c = 77 ;
373
+ int k1 = c + modulo ;
374
+ int k2 = c + 2 * modulo ;
375
+ kls .add (k1 );
376
+ kls .add (k2 );
377
+ CounterMetric numCollisions = kls .getNumCollisionsForValue (k1 );
378
+ assertEquals (2 , numCollisions .count ());
379
+ kls .add (k1 );
380
+ assertEquals (3 , numCollisions .count ());
381
+
382
+ boolean removed = kls .remove (k1 );
383
+ assertFalse (removed );
384
+ HashSet <Integer > removalSet = kls .getRemovalSetForValue (k1 );
385
+ assertTrue (removalSet .contains (k1 ));
386
+ assertEquals (2 , numCollisions .count ());
387
+
388
+ removed = kls .remove (k2 );
389
+ assertFalse (removed );
390
+ assertTrue (removalSet .contains (k2 ));
391
+ assertEquals (1 , numCollisions .count ());
392
+
393
+ removed = kls .remove (k1 );
394
+ assertFalse (removed );
395
+ assertTrue (removalSet .contains (k1 ));
396
+ assertEquals (1 , numCollisions .count ());
397
+ assertTrue (kls .contains (k1 ));
398
+ assertTrue (kls .contains (k2 ));
399
+ }
298
400
}
0 commit comments