DBConsensusManager { public OpBlockChain compact(int prevSize, OpBlockChain blc, boolean db) { if (blc == null || blc.isNullBlock() || blc.getParent().isNullBlock()) { return blc; } OpBlockChain compactedParent = null; if (blc.isDbAccessed() == blc.getParent().isDbAccessed()) { compactedParent = compact(blc.getSuperblockSize(), blc.getParent(), db); boolean compact = compactedParent == blc.getParent(); compact = compact && ((double) blc.getSuperblockSize() + settingsManager.OPENDB_COMPACT_COEFICIENT.get() * prevSize) > ((double) blc.getParent().getSuperblockSize()); if (compact) { LOGGER.info("Chain to compact: "); printBlockChain(blc); if (blc.isDbAccessed() && db) { return compactTwoDBAccessed(blc); } else { LOGGER.info(String.format("Compact runtime superblock '%s' into superblock '%s' ", blc.getParent().getSuperBlockHash(), blc.getSuperBlockHash())); blc = new OpBlockChain(blc, blc.getParent(), blc.getRules()); return blc; } } } else { compactedParent = compact(0, blc.getParent(), db); } if (blc.getParent() != compactedParent) { blc.changeToEqualParent(compactedParent); } return blc; }  Map<String, OpBlock> getOrphanedBlocks(); String getSuperblockHash(); OpBlockChain init(MetadataDb metadataDB); OpIndexColumn getIndex(String type, String columnId); Collection<OpIndexColumn> getIndicesForType(String type); void insertBlock(OpBlock opBlock); OpBlockChain saveMainBlockchain(OpBlockChain blc); OpBlockChain compact(int prevSize, OpBlockChain blc, boolean db); int removeOperations(Set<String> ops); boolean removeFullBlock(OpBlock block); OpBlockChain unloadSuperblockFromDB(OpBlockChain blc); ResourceDTO storeResourceObject(ResourceDTO imageDTO); ResourceDTO getResourceObjectIfExists(ResourceDTO imageDTO); List<ResourceDTO> getResources(boolean status, int addedMoreThanSecondsAgo); void removeResource(ResourceDTO resDTO); void updateResourceActiveStatus(ResourceDTO imageDTO, boolean status); Long getAmountResourcesInDB(); boolean validateExistingOperation(OpOperation op); void insertOperation(OpOperation op); OpOperation getOperationByHash(String hash); String getSetting(String key); Map<String, Map<String, OpIndexColumn>> getIndices();  }
@Test public void testCompact() throws FailedVerificationException { int i = 0; OpBlockChain opBlockChain = dbConsensusManager.init(metadataDb); generateOperations(formatter, opBlockChain); Deque<OpOperation> dequeOperations = opBlockChain.getQueueOperations(); assertFalse(dequeOperations.isEmpty()); Set<String> operationsToDelete = new HashSet<>(); List<OpOperation> addOperation = new ArrayList<>(); Iterator<OpOperation> iterator = dequeOperations.descendingIterator(); while (i < 3) { OpOperation opOperation = iterator.next(); operationsToDelete.add(opOperation.getRawHash()); addOperation.add(opOperation); i++; } int amountLoadedOperations = opBlockChain.getQueueOperations().size(); OpBlockChain blockchain = new OpBlockChain(opBlockChain.getParent(), opBlockChain.getRules()); for (OpOperation o : opBlockChain.getQueueOperations()) { if (!operationsToDelete.contains(o.getRawHash())) { blockchain.addOperation(o); } } opBlockChain = blockchain; assertEquals(operationsToDelete.size(), amountLoadedOperations - opBlockChain.getQueueOperations().size()); OpBlock opBlock = opBlockChain.createBlock(serverName, serverKeyPair); opBlock.getOperations().forEach(opOperation -> dbConsensusManager.insertOperation(opOperation)); assertEquals(opBlock.getOperations().size(), getAmountFromDbByTable(OPERATIONS_TABLE)); OpBlockChain newBlc = new OpBlockChain(opBlockChain, opBlockChain.getRules()); addOperation.forEach(newBlc::addOperation); opBlock = newBlc.createBlock(serverName, serverKeyPair); opBlock.getOperations().forEach(opOperation -> dbConsensusManager.insertOperation(opOperation)); newBlc = dbConsensusManager.compact(0, newBlc, true); assertNotNull(newBlc); }