/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.apache.cassandra.cql3;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.concurrent.Callable;

import org.junit.Assert;
import org.junit.BeforeClass;
import org.junit.Test;

import org.apache.cassandra.cache.KeyCacheKey;
import org.apache.cassandra.config.DatabaseDescriptor;
import org.apache.cassandra.config.Schema;
import org.apache.cassandra.db.Keyspace;
import org.apache.cassandra.index.Index;
import org.apache.cassandra.metrics.CacheMetrics;
import org.apache.cassandra.metrics.CassandraMetricsRegistry;
import org.apache.cassandra.schema.CachingParams;
import org.apache.cassandra.service.CacheService;
import org.apache.cassandra.service.StorageService;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.assertNull;

import org.apache.cassandra.utils.Pair;


public class KeyCacheCqlTest extends CQLTester
{

    private static final String commonColumnsDef =
    "part_key_a     int," +
    "part_key_b     text," +
    "clust_key_a    int," +
    "clust_key_b    text," +
    "clust_key_c    frozen<list<text>>," + // to make it really big
    "col_text       text," +
    "col_int        int," +
    "col_long       bigint," +
    "col_blob       blob,";
    private static final String commonColumns =
    "part_key_a," +
    "part_key_b," +
    "clust_key_a," +
    "clust_key_b," +
    "clust_key_c," + // to make it really big
    "col_text," +
    "col_int," +
    "col_long";

    // 1200 chars
    private static final String longString =
                                     "0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789" +
                                     "0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789" +
                                     "0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789" +
                                     "0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789" +
                                     "0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789" +
                                     "0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789" +
                                     "0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789" +
                                     "0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789" +
                                     "0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789" +
                                     "0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789" +
                                     "0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789" +
                                     "0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789";

    /**
     * Prevent system tables from populating the key cache to ensure that
     * the test can reliably check the size of the key cache size and its metrics.
     * Test tables will be created with caching enabled manually in the CQL statement,
     * see {@link KeyCacheCqlTest#createTable(String)}.
     *
     * Then call the base class initialization, which must be done after disabling the key cache.
     */
    @BeforeClass
    public static void setUpClass()
    {
        CachingParams.DEFAULT = CachingParams.CACHE_NOTHING;
        CQLTester.setUpClass();
    }

    /**
     * Create a table in KEYSPACE_PER_TEST_PER_TEST because it will get dropped synchronously by CQLTester after
     * each test, whereas the default keyspace gets dropped asynchronously and this may cause unexpected
     * flush operations during a test, which would change the expected result of metrics.
     *
     * Then add manual caching, since by default we have disabled cachinng for all other tables, to ensure
     * that we can assert on the key cache size and metrics.
     */
    @Override
    protected String createTable(String query)
    {
        return super.createTable(KEYSPACE_PER_TEST, query + " WITH caching = { 'keys' : 'ALL', 'rows_per_partition' : '0' }");
    }

    @Override
    protected UntypedResultSet execute(String query, Object... values) throws Throwable
    {
        return executeFormattedQuery(formatQuery(KEYSPACE_PER_TEST, query), values);
    }

    @Override
    protected void createIndex(String query)
    {
        createFormattedIndex(formatQuery(KEYSPACE_PER_TEST, query));
    }

    @Override
    protected void dropTable(String query)
    {
        dropFormattedTable(String.format(query, KEYSPACE_PER_TEST + "." + currentTable()));
    }

    @Test
    public void testSliceQueriesShallowIndexEntry() throws Throwable
    {
        DatabaseDescriptor.setColumnIndexCacheSize(0);
        testSliceQueries();
    }

    @Test
    public void testSliceQueriesIndexInfoOnHeap() throws Throwable
    {
        DatabaseDescriptor.setColumnIndexCacheSize(8);
        testSliceQueries();
    }

    private void testSliceQueries() throws Throwable
    {
        createTable("CREATE TABLE %s (pk text, ck1 int, ck2 int, val text, vpk text, vck1 int, vck2 int, PRIMARY KEY (pk, ck1, ck2))");

        for (int pkInt = 0; pkInt < 20; pkInt++)
        {
            String pk = Integer.toString(pkInt);
            for (int ck1 = 0; ck1 < 10; ck1++)
            {
                for (int ck2 = 0; ck2 < 10; ck2++)
                {
                    execute("INSERT INTO %s (pk, ck1, ck2, val, vpk, vck1, vck2) VALUES (?, ?, ?, ?, ?, ?, ?)",
                            pk, ck1, ck2, makeStringValue(pk, ck1, ck2), pk, ck1, ck2);
                }
            }
        }

        StorageService.instance.forceKeyspaceFlush(KEYSPACE_PER_TEST);

        for (int pkInt = 0; pkInt < 20; pkInt++)
        {
            String pk = Integer.toString(pkInt);
            assertClusterRows(execute("SELECT val, vpk, vck1, vck2 FROM %s WHERE pk=?", pk),
                              pk, 0, 10, 0, 10);

            for (int ck1 = 0; ck1 < 10; ck1++)
            {
                assertClusterRows(execute("SELECT val, vpk, vck1, vck2 FROM %s WHERE pk=? AND ck1=?", pk, ck1),
                                  pk, ck1, ck1+1, 0, 10);

                assertClusterRows(execute("SELECT val, vpk, vck1, vck2 FROM %s WHERE pk=? AND ck1<?", pk, ck1),
                                  pk, 0, ck1, 0, 10);
                assertClusterRows(execute("SELECT val, vpk, vck1, vck2 FROM %s WHERE pk=? AND ck1>?", pk, ck1),
                                  pk, ck1+1, 10, 0, 10);
                assertClusterRows(execute("SELECT val, vpk, vck1, vck2 FROM %s WHERE pk=? AND ck1<=?", pk, ck1),
                                  pk, 0, ck1+1, 0, 10);
                assertClusterRows(execute("SELECT val, vpk, vck1, vck2 FROM %s WHERE pk=? AND ck1>=?", pk, ck1),
                                  pk, ck1, 10, 0, 10);

                for (int ck2 = 0; ck2 < 10; ck2++)
                {
                    assertRows(execute("SELECT val, vpk, vck1, vck2 FROM %s WHERE pk=? AND ck1=? AND ck2=?", pk, ck1, ck2),
                               new Object[]{ makeStringValue(pk, ck1, ck2), pk, ck1, ck2 });

                    assertClusterRows(execute("SELECT val, vpk, vck1, vck2 FROM %s WHERE pk=? AND ck1=? AND ck2<?", pk, ck1, ck2),
                                      pk, ck1, ck1+1, 0, ck2);
                    assertClusterRows(execute("SELECT val, vpk, vck1, vck2 FROM %s WHERE pk=? AND ck1=? AND ck2>?", pk, ck1, ck2),
                                      pk, ck1, ck1+1, ck2+1, 10);
                    assertClusterRows(execute("SELECT val, vpk, vck1, vck2 FROM %s WHERE pk=? AND ck1=? AND ck2<=?", pk, ck1, ck2),
                                      pk, ck1, ck1+1, 0, ck2+1);
                    assertClusterRows(execute("SELECT val, vpk, vck1, vck2 FROM %s WHERE pk=? AND ck1=? AND ck2>=?", pk, ck1, ck2),
                                      pk, ck1, ck1+1, ck2, 10);
                }
            }
        }
    }

    private static void assertClusterRows(UntypedResultSet rows, String pk, int ck1from, int ck1to, int ck2from, int ck2to)
    {
        String info = "pk=" + pk + ", ck1from=" + ck1from + ", ck1to=" + ck1to + ", ck2from=" + ck2from + ", ck2to=" + ck2to;
        Iterator<UntypedResultSet.Row> iter = rows.iterator();
        int cnt = 0;
        int expect = (ck1to - ck1from) * (ck2to - ck2from);
        for (int ck1 = ck1from; ck1 < ck1to; ck1++)
        {
            for (int ck2 = ck2from; ck2 < ck2to; ck2++)
            {
                assertTrue("expected " + expect + " (already got " + cnt + ") rows, but more rows are available for " + info, iter.hasNext());
                UntypedResultSet.Row row = iter.next();
                assertEquals(makeStringValue(pk, ck1, ck2), row.getString("val"));
                assertEquals(pk, row.getString("vpk"));
                assertEquals(ck1, row.getInt("vck1"));
                assertEquals(ck2, row.getInt("vck2"));
            }
        }
        assertFalse("expected " + expect + " (already got " + cnt + ") rows, but more rows are available for " + info, iter.hasNext());
    }

    private static String makeStringValue(String pk, int ck1, int ck2)
    {
        return longString + ',' + pk + ',' + ck1 + ',' + ck2;
    }

    @Test
    public void test2iKeyCachePathsShallowIndexEntry() throws Throwable
    {
        DatabaseDescriptor.setColumnIndexCacheSize(0);
        test2iKeyCachePaths();
    }

    @Test
    public void test2iKeyCachePathsIndexInfoOnHeap() throws Throwable
    {
        DatabaseDescriptor.setColumnIndexCacheSize(8);
        test2iKeyCachePaths();
    }

    private void test2iKeyCachePaths() throws Throwable
    {
        String table = createTable("CREATE TABLE %s ("
                                   + commonColumnsDef
                                   + "PRIMARY KEY ((part_key_a, part_key_b),clust_key_a,clust_key_b,clust_key_c))");
        createIndex("CREATE INDEX some_index ON %s (col_int)");
        insertData(table, "some_index", true);
        clearCache();

        CacheMetrics metrics = CacheService.instance.keyCache.getMetrics();

        long expectedRequests = 0;

        for (int i = 0; i < 10; i++)
        {
            UntypedResultSet result = execute("SELECT part_key_a FROM %s WHERE col_int = ?", i);
            assertEquals(500, result.size());
            // Index requests and table requests are both added to the same metric
            // We expect 10 requests on the index SSTables and 10 IN requests on the table SSTables + BF false positives
            expectedRequests += recentBloomFilterFalsePositives() + 20;
        }

        long hits = metrics.hits.getCount();
        long requests = metrics.requests.getCount();
        assertEquals(0, hits);
        assertEquals(expectedRequests, requests);

        for (int i = 0; i < 10; i++)
        {
            UntypedResultSet result = execute("SELECT part_key_a FROM %s WHERE col_int = ?", i);
            // 100 part-keys * 50 clust-keys
            // indexed on part-key % 10 = 10 index partitions
            // (50 clust-keys  *  100-part-keys  /  10 possible index-values) = 500
            assertEquals(500, result.size());
            // Index requests and table requests are both added to the same metric
            // We expect 10 requests on the index SSTables and 10 IN requests on the table SSTables + BF false positives
            expectedRequests += recentBloomFilterFalsePositives() + 20;
        }

        metrics = CacheService.instance.keyCache.getMetrics();
        hits = metrics.hits.getCount();
        requests = metrics.requests.getCount();
        assertEquals(200, hits);
        assertEquals(expectedRequests, requests);

        CacheService.instance.keyCache.submitWrite(Integer.MAX_VALUE).get();

        int beforeSize = CacheService.instance.keyCache.size();

        CacheService.instance.keyCache.clear();

        Assert.assertEquals(0, CacheService.instance.keyCache.size());

        // then load saved
        CacheService.instance.keyCache.loadSaved();

        assertEquals(beforeSize, CacheService.instance.keyCache.size());

        for (int i = 0; i < 10; i++)
        {
            UntypedResultSet result = execute("SELECT part_key_a FROM %s WHERE col_int = ?", i);
            // 100 part-keys * 50 clust-keys
            // indexed on part-key % 10 = 10 index partitions
            // (50 clust-keys  *  100-part-keys  /  10 possible index-values) = 500
            assertEquals(500, result.size());
        }

        //Test Schema.getColumnFamilyStoreIncludingIndexes, several null check paths
        //are defensive and unreachable
        assertNull(Schema.instance.getColumnFamilyStoreIncludingIndexes(Pair.create("foo", "bar")));
        assertNull(Schema.instance.getColumnFamilyStoreIncludingIndexes(Pair.create(KEYSPACE_PER_TEST, "bar")));

        dropTable("DROP TABLE %s");
        Schema.instance.updateVersion();

        //Test loading for a dropped 2i/table
        CacheService.instance.keyCache.clear();

        // then load saved
        CacheService.instance.keyCache.loadSaved();

        assertEquals(0, CacheService.instance.keyCache.size());
    }

    @Test
    public void test2iKeyCachePathsSaveKeysForDroppedTableShallowIndexEntry() throws Throwable
    {
        DatabaseDescriptor.setColumnIndexCacheSize(0);
        test2iKeyCachePathsSaveKeysForDroppedTable();
    }

    @Test
    public void test2iKeyCachePathsSaveKeysForDroppedTableIndexInfoOnHeap() throws Throwable
    {
        DatabaseDescriptor.setColumnIndexCacheSize(8);
        test2iKeyCachePathsSaveKeysForDroppedTable();
    }

    private void test2iKeyCachePathsSaveKeysForDroppedTable() throws Throwable
    {
        String table = createTable("CREATE TABLE %s ("
                                   + commonColumnsDef
                                   + "PRIMARY KEY ((part_key_a, part_key_b),clust_key_a,clust_key_b,clust_key_c))");
        createIndex("CREATE INDEX some_index ON %s (col_int)");
        insertData(table, "some_index", true);
        clearCache();

        CacheMetrics metrics = CacheService.instance.keyCache.getMetrics();

        long expectedNumberOfRequests = 0;

        for (int i = 0; i < 10; i++)
        {
            UntypedResultSet result = execute("SELECT part_key_a FROM %s WHERE col_int = ?", i);
            assertEquals(500, result.size());

            // Index requests and table requests are both added to the same metric
            // We expect 10 requests on the index SSTables and 10 IN requests on the table SSTables + BF false positives
            expectedNumberOfRequests += recentBloomFilterFalsePositives() + 20;
        }

        long hits = metrics.hits.getCount();
        long requests = metrics.requests.getCount();
        assertEquals(0, hits);
        assertEquals(expectedNumberOfRequests, requests);

        for (int i = 0; i < 10; i++)
        {
            UntypedResultSet result = execute("SELECT part_key_a FROM %s WHERE col_int = ?", i);
            // 100 part-keys * 50 clust-keys
            // indexed on part-key % 10 = 10 index partitions
            // (50 clust-keys  *  100-part-keys  /  10 possible index-values) = 500
            assertEquals(500, result.size());

            // Index requests and table requests are both added to the same metric
            // We expect 10 requests on the index SSTables and 10 IN requests on the table SSTables + BF false positives
            expectedNumberOfRequests += recentBloomFilterFalsePositives() + 20;
        }

        metrics = CacheService.instance.keyCache.getMetrics();
        hits = metrics.hits.getCount();
        requests = metrics.requests.getCount();
        assertEquals(200, hits);
        assertEquals(expectedNumberOfRequests, requests);

        dropTable("DROP TABLE %s");

        CacheService.instance.keyCache.submitWrite(Integer.MAX_VALUE).get();

        CacheService.instance.keyCache.clear();

        Assert.assertEquals(0, CacheService.instance.keyCache.size());

        // then load saved
        CacheService.instance.keyCache.loadSaved();

        Iterator<KeyCacheKey> iter = CacheService.instance.keyCache.keyIterator();
        while(iter.hasNext())
        {
            KeyCacheKey key = iter.next();
            Assert.assertFalse(key.ksAndCFName.left.equals("KEYSPACE_PER_TEST"));
            Assert.assertFalse(key.ksAndCFName.right.startsWith(table));
        }
    }

    @Test
    public void testKeyCacheNonClusteredShallowIndexEntry() throws Throwable
    {
        DatabaseDescriptor.setColumnIndexCacheSize(0);
        testKeyCacheNonClustered();
    }

    @Test
    public void testKeyCacheNonClusteredIndexInfoOnHeap() throws Throwable
    {
        DatabaseDescriptor.setColumnIndexCacheSize(8);
        testKeyCacheNonClustered();
    }

    private void testKeyCacheNonClustered() throws Throwable
    {
        String table = createTable("CREATE TABLE %s ("
                                   + commonColumnsDef
                                   + "PRIMARY KEY ((part_key_a, part_key_b)))");
        insertData(table, null, false);
        clearCache();

        long expectedNumberOfRequests = 0;

        for (int i = 0; i < 10; i++)
        {
            assertRows(execute("SELECT col_text FROM %s WHERE part_key_a = ? AND part_key_b = ?", i, Integer.toOctalString(i)),
                       new Object[]{ String.valueOf(i) + '-' + String.valueOf(0) });

            // the data for the key is in 1 SSTable but we have to take into account bloom filter false positive
            expectedNumberOfRequests += recentBloomFilterFalsePositives() + 1;
        }

        CacheMetrics metrics = CacheService.instance.keyCache.getMetrics();
        long hits = metrics.hits.getCount();
        long requests = metrics.requests.getCount();
        assertEquals(0, hits);
        assertEquals(10, requests);

        for (int i = 0; i < 100; i++)
        {
            assertRows(execute("SELECT col_text FROM %s WHERE part_key_a = ? AND part_key_b = ?", i, Integer.toOctalString(i)),
                       new Object[]{ String.valueOf(i) + '-' + String.valueOf(0) });

            // the data for the key is in 1 SSTable but we have to take into account bloom filter false positive
            expectedNumberOfRequests += recentBloomFilterFalsePositives() + 1;
        }

        hits = metrics.hits.getCount();
        requests = metrics.requests.getCount();
        assertEquals(10, hits);
        assertEquals(expectedNumberOfRequests, requests);
    }

    @Test
    public void testKeyCacheClusteredShallowIndexEntry() throws Throwable
    {
        DatabaseDescriptor.setColumnIndexCacheSize(0);
        testKeyCacheClustered();
    }

    @Test
    public void testKeyCacheClusteredIndexInfoOnHeap() throws Throwable
    {
        DatabaseDescriptor.setColumnIndexCacheSize(8);
        testKeyCacheClustered();
    }

    private void testKeyCacheClustered() throws Throwable
    {
        String table = createTable("CREATE TABLE %s ("
                                   + commonColumnsDef
                                   + "PRIMARY KEY ((part_key_a, part_key_b),clust_key_a,clust_key_b,clust_key_c))");
        insertData(table, null, true);
        clearCache();

        // query on partition key

        // 10 queries, each 50 result rows
        for (int i = 0; i < 10; i++)
        {
            assertEquals(50, execute("SELECT col_text FROM %s WHERE part_key_a = ? AND part_key_b = ?", i, Integer.toOctalString(i)).size());
        }

        CacheMetrics metrics = CacheService.instance.keyCache.getMetrics();
        long hits = metrics.hits.getCount();
        long requests = metrics.requests.getCount();
        assertEquals(0, hits);
        assertEquals(10, requests);

        // 10 queries, each 50 result rows
        for (int i = 0; i < 10; i++)
        {
            assertEquals(50, execute("SELECT col_text FROM %s WHERE part_key_a = ? AND part_key_b = ?", i, Integer.toOctalString(i)).size());
        }

        metrics = CacheService.instance.keyCache.getMetrics();
        hits = metrics.hits.getCount();
        requests = metrics.requests.getCount();
        assertEquals(10, hits);
        assertEquals(10 + 10, requests);

        // 100 queries - must get a hit in key-cache
        for (int i = 0; i < 10; i++)
        {
            for (int c = 0; c < 10; c++)
            {
                assertRows(execute("SELECT col_text, col_long FROM %s WHERE part_key_a = ? AND part_key_b = ? and clust_key_a = ?", i, Integer.toOctalString(i), c),
                           new Object[]{ String.valueOf(i) + '-' + String.valueOf(c), (long) c });
            }
        }

        metrics = CacheService.instance.keyCache.getMetrics();
        hits = metrics.hits.getCount();
        requests = metrics.requests.getCount();
        assertEquals(10 + 100, hits);
        assertEquals(20 + 100, requests);

        // 5000 queries - first 10 partitions already in key cache
        for (int i = 0; i < 100; i++)
        {
            for (int c = 0; c < 50; c++)
            {
                assertRows(execute("SELECT col_text, col_long FROM %s WHERE part_key_a = ? AND part_key_b = ? and clust_key_a = ?", i, Integer.toOctalString(i), c),
                           new Object[]{ String.valueOf(i) + '-' + String.valueOf(c), (long) c });
            }
        }

        hits = metrics.hits.getCount();
        requests = metrics.requests.getCount();
        assertEquals(110 + 4910, hits);
        assertEquals(120 + 5500, requests);
    }

    // Inserts 100 partitions split over 10 sstables (flush after 10 partitions).
    // Clustered tables receive 50 CQL rows per partition.
    private void insertData(String table, String index, boolean withClustering) throws Throwable
    {
        prepareTable(table);
        if (index != null)
        {
            StorageService.instance.disableAutoCompaction(KEYSPACE_PER_TEST, table + '.' + index);
            triggerBlockingFlush(Keyspace.open(KEYSPACE_PER_TEST).getColumnFamilyStore(table).indexManager.getIndexByName(index));
        }

        for (int i = 0; i < 100; i++)
        {
            int partKeyA = i;
            String partKeyB = Integer.toOctalString(i);
            for (int c = 0; c < (withClustering ? 50 : 1); c++)
            {
                int clustKeyA = c;
                String clustKeyB = Integer.toOctalString(c);
                List<String> clustKeyC = makeList(clustKeyB);
                String colText = String.valueOf(i) + '-' + String.valueOf(c);
                int colInt = i % 10;
                long colLong = c;
                execute("INSERT INTO %s (" + commonColumns + ") VALUES (?, ?, ?, ?, ?, ?, ?, ?)",
                        partKeyA, partKeyB,
                        clustKeyA, clustKeyB, clustKeyC,
                        colText, colInt, colLong);
            }

            if (i % 10 == 9)
            {
                Keyspace.open(KEYSPACE_PER_TEST).getColumnFamilyStore(table).forceFlush().get();
                if (index != null)
                    triggerBlockingFlush(Keyspace.open(KEYSPACE_PER_TEST).getColumnFamilyStore(table).indexManager.getIndexByName(index));
            }
        }
    }

    private static void prepareTable(String table) throws IOException, InterruptedException, java.util.concurrent.ExecutionException
    {
        StorageService.instance.disableAutoCompaction(KEYSPACE_PER_TEST, table);
        Keyspace.open(KEYSPACE_PER_TEST).getColumnFamilyStore(table).forceFlush().get();
        Keyspace.open(KEYSPACE_PER_TEST).getColumnFamilyStore(table).truncateBlocking();
    }

    private static List<String> makeList(String value)
    {
        List<String> list = new ArrayList<>(50);
        for (int i = 0; i < 50; i++)
        {
            list.add(value + i);
        }
        return list;
    }

    private static void clearCache()
    {
        CassandraMetricsRegistry.Metrics.getNames().forEach(CassandraMetricsRegistry.Metrics::remove);
        CacheService.instance.keyCache.clear();
        CacheMetrics metrics = CacheService.instance.keyCache.getMetrics();
        Assert.assertEquals(0, metrics.entries.getValue().intValue());
        Assert.assertEquals(0L, metrics.hits.getCount());
        Assert.assertEquals(0L, metrics.requests.getCount());
        Assert.assertEquals(0L, metrics.size.getValue().longValue());
    }

    private static void triggerBlockingFlush(Index index) throws Exception
    {
        assert index != null;
        Callable<?> flushTask = index.getBlockingFlushTask();
        if (flushTask != null)
            flushTask.call();
    }

    private long recentBloomFilterFalsePositives()
    {
        return getCurrentColumnFamilyStore(KEYSPACE_PER_TEST).metric.recentBloomFilterFalsePositives.getValue();
    }
}
