/** * Removes all entries from the cache and the SortedIndex, regardless of their state. * * @throws IllegalStateException If the StreamSegmentReadIndex is not closed. */ private void removeAllEntries() { // A bit unusual, but we want to make sure we do not call this while the index is active. Preconditions.checkState(this.closed, "Cannot call removeAllEntries unless the ReadIndex is closed."); int count; synchronized (this.lock) { this.indexEntries.forEach(entry -> { if (entry.isDataEntry()) { CacheKey key = getCacheKey(entry); this.cache.remove(key); } }); count = this.indexEntries.size(); this.indexEntries.clear(); } log.info("{}: Cleared all cache entries ({}).", this.traceObjectId, count); }
/** * Gets a copy of all the ReadIndexEntries in this Index that are not RedirectReadIndices. All returned * entries have their offsets adjusted by the given amount. * * @param offsetAdjustment The amount to adjust the offset by. */ private List<MergedIndexEntry> getAllEntries(long offsetAdjustment) { Exceptions.checkArgument(offsetAdjustment >= 0, "offsetAdjustment", "offsetAdjustment must be a non-negative number."); synchronized (this.lock) { List<MergedIndexEntry> result = new ArrayList<>(this.indexEntries.size()); this.indexEntries.forEach(entry -> { if (entry.isDataEntry()) { result.add(new MergedIndexEntry(entry.getStreamSegmentOffset() + offsetAdjustment, this.metadata.getId(), (CacheIndexEntry) entry)); } }); return result; } }
/** * Tests the remove(), size(), get(), getFirst(), getLast() methods. */ @Test public void testRemove() { val index = createIndex(); val keys = populate(index); // Remove the items, in order. keys.sort(KEY_COMPARATOR); val keysToRemove = new LinkedList<Long>(keys); int expectedSize = index.size(); while (keysToRemove.size() > 0) { // Remove either the first or the last key - this helps test getFirst/getLast properly. long key = expectedSize % 2 == 0 ? keysToRemove.removeLast() : keysToRemove.removeFirst(); val entry = index.get(key); val removedEntry = index.remove(key); expectedSize--; Assert.assertEquals("Unexpected removed entry for key " + key, entry, removedEntry); Assert.assertEquals("Unexpected size after removing key " + key, expectedSize, index.size()); Assert.assertNull("Entry was not removed for key " + key, index.get(key)); if (expectedSize == 0) { Assert.assertNull("Unexpected value from getFirst() when index is empty.", index.getFirst()); Assert.assertNull("Unexpected value from getLast() when index is empty.", index.getLast()); } else { Assert.assertEquals("Unexpected value from getFirst() after removing key " + key, (long) keysToRemove.getFirst(), index.getFirst().key()); Assert.assertEquals("Unexpected value from getLast() after removing key " + key, (long) keysToRemove.getLast(), index.getLast().key()); } } }
Assert.assertEquals("Unexpected size.", i + 1, index.size()); Assert.assertEquals("Unexpected value from getFirst() after " + index.size() + " insertions.", firstEntry, index.getFirst()); Assert.assertEquals("Unexpected value from getLast() after " + index.size() + " insertions.", lastEntry, index.getLast()); Assert.assertEquals("Unexpected overridden entry for key " + key, oldEntry, overriddenEntry); Assert.assertEquals("New entry was not placed in the index for key " + key, entry, reRetrievedEntry); Assert.assertEquals("Unexpected size when overriding entry.", ITEM_COUNT, index.size());
/** * Tests the forEach() method. */ @Test public void testForEach() { // Create an index and populate it. val index = createIndex(); val validKeys = populate(index); // Extract the keys using forEach - they should be ordered naturally. val actualKeys = new ArrayList<Long>(); index.forEach(e -> actualKeys.add(e.key())); // Order the inserted keys using the same comparator we used for the index. validKeys.sort(KEY_COMPARATOR); // Verify that modifying the index while looping through it does throw an exception. AssertExtensions.assertThrows( "forEach did not throw when a new item was added during enumeration.", () -> index.forEach(e -> index.put(new TestEntry(index.size()))), ex -> ex instanceof ConcurrentModificationException); AssertExtensions.assertThrows( "forEach did not throw when an item was removed during enumeration.", () -> index.forEach(e -> index.remove(e.key())), ex -> ex instanceof ConcurrentModificationException); AssertExtensions.assertThrows( "forEach did not throw when the index was cleared during enumeration.", () -> index.forEach(e -> index.clear()), ex -> ex instanceof ConcurrentModificationException); }
/** * Tests the clear() method. */ @Test public void testClear() { val index = createIndex(); val keys = populate(index); Assert.assertNotNull("Unexpected return value for getFirst() on non-empty index.", index.getFirst()); Assert.assertNotNull("Unexpected return value for getLast() on non-empty index.", index.getLast()); index.clear(); Assert.assertEquals("Unexpected size of empty index.", 0, index.size()); Assert.assertNull("Unexpected return value for getFirst() on empty index.", index.getFirst()); Assert.assertNull("Unexpected return value for getLast() on empty index.", index.getLast()); for (long key : keys) { Assert.assertNull("Unexpected value for get() on empty index.", index.get(key)); Assert.assertNull("Unexpected value for getCeiling() on empty index.", index.getCeiling(key)); } }