/** * Tests that any reservation that will not violate minimum shared cache will fail, during server * startup and dynamic updation */ public void testMinimumSharedCache() { int totalCache = 20 * ByteUtils.BYTES_PER_MB; // total cache size int shareA = 10 * ByteUtils.BYTES_PER_MB; // A reserves 10MB // lets use all the default values. Props props = new Props(); props.put("node.id", 1); props.put("voldemort.home", "test/common/voldemort/config"); VoldemortConfig voldemortConfig = new VoldemortConfig(props); voldemortConfig.setBdbCacheSize(totalCache); voldemortConfig.setBdbOneEnvPerStore(true); voldemortConfig.setBdbDataDirectory(bdbMasterDir.toURI().getPath()); voldemortConfig.setBdbMinimumSharedCache(15 * ByteUtils.BYTES_PER_MB); BdbStorageEngine storeA = null; bdbStorage = new BdbStorageConfiguration(voldemortConfig); assertEquals(0, bdbStorage.getReservedCacheSize()); try { StoreDefinition defA = TestUtils.makeStoreDefinition("storeA", shareA / ByteUtils.BYTES_PER_MB); storeA = (BdbStorageEngine) bdbStorage.getStore(defA); fail("Should have thrown exception since minSharedCache will be violated"); } catch (StorageInitializationException sie) { // should come here. } // failing operations should not alter reserved cache size assertEquals(0, bdbStorage.getReservedCacheSize()); voldemortConfig.setBdbMinimumSharedCache(10 * ByteUtils.BYTES_PER_MB); bdbStorage = new BdbStorageConfiguration(voldemortConfig); try { StoreDefinition defA = TestUtils.makeStoreDefinition("storeA", shareA / ByteUtils.BYTES_PER_MB); storeA = (BdbStorageEngine) bdbStorage.getStore(defA); } catch (StorageInitializationException sie) { // should not come here. fail("minSharedCache should n't have been violated"); } assertEquals(shareA, bdbStorage.getReservedCacheSize()); long reserveCacheSize = bdbStorage.getReservedCacheSize(); // now, try increasing the reservation dynamically and it should fail try { StoreDefinition defA = TestUtils.makeStoreDefinition("storeA", 15); bdbStorage.update(defA); fail("Should have thrown exception since minSharedCache will be violated"); } catch (StorageInitializationException sie) { // should come here. } // this failure cannot alter the reservedCacheSize assertEquals(reserveCacheSize, bdbStorage.getReservedCacheSize()); if (storeA != null) storeA.close(); }
public void testDynamicReservations() { int totalCache = 20 * ByteUtils.BYTES_PER_MB; // total cache size int shareA = 10 * ByteUtils.BYTES_PER_MB; // A reserves 10MB int shareB = totalCache - shareA; int numRecords = 40; // lets use all the default values. Props props = new Props(); props.put("node.id", 1); props.put("voldemort.home", "test/common/voldemort/config"); VoldemortConfig voldemortConfig = new VoldemortConfig(props); voldemortConfig.setBdbCacheSize(totalCache); voldemortConfig.setBdbOneEnvPerStore(true); voldemortConfig.setBdbDataDirectory(bdbMasterDir.toURI().getPath()); voldemortConfig.setBdbMinimumSharedCache(5 * ByteUtils.BYTES_PER_MB); bdbStorage = new BdbStorageConfiguration(voldemortConfig); StoreDefinition defA = TestUtils.makeStoreDefinition("storeA", shareA / (1024 * 1024)); BdbStorageEngine storeA = (BdbStorageEngine) bdbStorage.getStore(defA); StoreDefinition defB = TestUtils.makeStoreDefinition("storeB"); BdbStorageEngine storeB = (BdbStorageEngine) bdbStorage.getStore(defB); // load data into the stores; each store is guaranteed to be ~ 40MB. // Data won't fit in memory byte[] value = new byte[ByteUtils.BYTES_PER_MB]; for (int i = 0; i < numRecords; i++) { storeA.put(TestUtils.toByteArray("testKey" + i), new Versioned<byte[]>(value), null); storeB.put(TestUtils.toByteArray("testKey" + i), new Versioned<byte[]>(value), null); } // 1. start with 10MB reserved cache for A and the rest 10MB for B long cacheSizeA = Long.MIN_VALUE; long cacheSizeB = Long.MIN_VALUE; for (int cycle = 0; cycle < 10; cycle++) { for (int i = 0; i < numRecords; i++) { long cycleCacheSizeA = getAndCheckCacheSize(storeA, defA, "testKey" + i); long cycleCacheSizeB = getAndCheckCacheSize(storeB, defB, "testKey" + i); // record the maximum cache size, each store every grew to cacheSizeA = (cycleCacheSizeA > cacheSizeA) ? cycleCacheSizeA : cacheSizeA; cacheSizeB = (cycleCacheSizeB > cacheSizeB) ? cycleCacheSizeB : cacheSizeB; } } assertTrue(Math.abs(cacheSizeA - shareA) <= ByteUtils.BYTES_PER_MB); assertTrue(Math.abs(cacheSizeB - shareB) <= ByteUtils.BYTES_PER_MB); // 2. dynamically grow the cache to 15MB and watch B shrink. shareA = 15 * ByteUtils.BYTES_PER_MB; shareB = totalCache - shareA; defA = TestUtils.makeStoreDefinition("storeA", shareA / (1024 * 1024)); bdbStorage.update(defA); cacheSizeA = Long.MIN_VALUE; cacheSizeB = Long.MIN_VALUE; for (int cycle = 0; cycle < 10; cycle++) { for (int i = 0; i < numRecords; i++) { long cycleCacheSizeA = getAndCheckCacheSize(storeA, defA, "testKey" + i); long cycleCacheSizeB = getAndCheckCacheSize(storeB, defB, "testKey" + i); // record the maximum cache size, each store every grew to cacheSizeA = (cycleCacheSizeA > cacheSizeA) ? cycleCacheSizeA : cacheSizeA; cacheSizeB = (cycleCacheSizeB > cacheSizeB) ? cycleCacheSizeB : cacheSizeB; } } assertTrue(Math.abs(cacheSizeA - shareA) <= ByteUtils.BYTES_PER_MB); assertTrue(Math.abs(cacheSizeB - shareB) <= ByteUtils.BYTES_PER_MB); // 3. dynamically shrink it back to 10MB and watch B expand again. shareA = 10 * ByteUtils.BYTES_PER_MB; shareB = totalCache - shareA; defA = TestUtils.makeStoreDefinition("storeA", shareA / (1024 * 1024)); bdbStorage.update(defA); cacheSizeA = Long.MIN_VALUE; cacheSizeB = Long.MIN_VALUE; for (int cycle = 0; cycle < 10; cycle++) { for (int i = 0; i < numRecords; i++) { long cycleCacheSizeA = getAndCheckCacheSize(storeA, defA, "testKey" + i); long cycleCacheSizeB = getAndCheckCacheSize(storeB, defB, "testKey" + i); // record the maximum cache size, each store every grew to cacheSizeA = (cycleCacheSizeA > cacheSizeA) ? cycleCacheSizeA : cacheSizeA; cacheSizeB = (cycleCacheSizeB > cacheSizeB) ? cycleCacheSizeB : cacheSizeB; } } // check that they are not exceedingly high than their limits. Small // overflows are expected. But should not be more than a 1MB assertTrue(Math.abs(cacheSizeA - shareA) <= ByteUtils.BYTES_PER_MB); assertTrue(Math.abs(cacheSizeB - shareB) <= ByteUtils.BYTES_PER_MB); storeA.close(); storeB.close(); }