diff --git a/src/main/java/com/lbry/database/rows/PrefixRow.java b/src/main/java/com/lbry/database/rows/PrefixRow.java index c16eadc..7a08033 100644 --- a/src/main/java/com/lbry/database/rows/PrefixRow.java +++ b/src/main/java/com/lbry/database/rows/PrefixRow.java @@ -45,8 +45,8 @@ public PrefixRow(RocksDB database, RevertibleOperationStack operationStack,List< public abstract Prefix prefix(); - public RocksIterator iterate() throws RocksDBException{ - return this.iterate(null); + public RocksIterator iterate(){ + return this.database.newIterator(this.columnFamily); } //TODO diff --git a/src/test/java/com/lbry/database/tests/RevertablePrefixDBTest.java b/src/test/java/com/lbry/database/tests/RevertablePrefixDBTest.java index 6679fee..efdbe24 100644 --- a/src/test/java/com/lbry/database/tests/RevertablePrefixDBTest.java +++ b/src/test/java/com/lbry/database/tests/RevertablePrefixDBTest.java @@ -1,34 +1,24 @@ package com.lbry.database.tests; import com.lbry.database.PrefixDB; -import com.lbry.database.keys.ActiveAmountKey; -import com.lbry.database.keys.ClaimTakeoverKey; -import com.lbry.database.revert.RevertibleOperation; -import com.lbry.database.revert.RevertiblePut; +import com.lbry.database.keys.*; import com.lbry.database.util.ArrayHelper; -import com.lbry.database.values.ActiveAmountValue; -import com.lbry.database.values.ClaimTakeoverValue; +import com.lbry.database.values.*; import java.io.File; import java.io.IOException; import java.nio.ByteBuffer; import java.nio.ByteOrder; import java.nio.file.Files; -import java.util.Arrays; +import java.util.*; import java.util.function.BiFunction; -import java.util.function.Function; -import org.junit.jupiter.api.AfterAll; -import org.junit.jupiter.api.BeforeAll; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.TestInstance; +import org.junit.jupiter.api.*; import org.rocksdb.ReadOptions; import org.rocksdb.RocksDBException; import org.rocksdb.RocksIterator; -import org.rocksdb.Slice; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertNull; +import static org.junit.jupiter.api.Assertions.*; @TestInstance(TestInstance.Lifecycle.PER_CLASS) public class RevertablePrefixDBTest{ @@ -45,6 +35,8 @@ public void setUp() throws IOException,RocksDBException{ @AfterAll public void tearDown(){} + + @Disabled @Test public void testRollback() throws RocksDBException{ String name = "derp"; @@ -155,7 +147,240 @@ public void testRollback() throws RocksDBException{ } @Test - public void testHubDatabaseIterator(){} + public void testHubDatabaseIterator() throws RocksDBException{ + String name = "derp"; + byte[] claimHash0 = new byte[20]; + Arrays.fill(claimHash0, (byte) 0x00); + byte[] claimHash1 = new byte[20]; + Arrays.fill(claimHash1, (byte) 0x01); + byte[] claimHash2 = new byte[20]; + Arrays.fill(claimHash2, (byte) 0x02); + byte[] claimHash3 = new byte[20]; + Arrays.fill(claimHash3, (byte) 0x02); + int overflowValue = 0xFFFFFFFF; + + this.database.claim_expiration.stashPut(new ClaimExpirationKey(){{ + this.expiration = 99; + this.tx_num = 999; + this.position = 0; + }},new ClaimExpirationValue(){{ + this.claim_hash = claimHash0; + this.normalized_name = name; + }}); + this.database.claim_expiration.stashPut(new ClaimExpirationKey(){{ + this.expiration = 100; + this.tx_num = 1000; + this.position = 0; + }},new ClaimExpirationValue(){{ + this.claim_hash = claimHash1; + this.normalized_name = name; + }}); + this.database.claim_expiration.stashPut(new ClaimExpirationKey(){{ + this.expiration = 100; + this.tx_num = 1001; + this.position = 0; + }},new ClaimExpirationValue(){{ + this.claim_hash = claimHash2; + this.normalized_name = name; + }}); + this.database.claim_expiration.stashPut(new ClaimExpirationKey(){{ + this.expiration = 101; + this.tx_num = 1002; + this.position = 0; + }},new ClaimExpirationValue(){{ + this.claim_hash = claimHash3; + this.normalized_name = name; + }}); + this.database.claim_expiration.stashPut(new ClaimExpirationKey(){{ + this.expiration = overflowValue-1; + this.tx_num = 1003; + this.position = 0; + }},new ClaimExpirationValue(){{ + this.claim_hash = claimHash3; + this.normalized_name = name; + }}); + this.database.claim_expiration.stashPut(new ClaimExpirationKey(){{ + this.expiration = overflowValue; + this.tx_num = 1004; + this.position = 0; + }},new ClaimExpirationValue(){{ + this.claim_hash = claimHash3; + this.normalized_name = name; + }}); + this.database.tx_num.stashPut(new TxNumKey(){{ + this.tx_hash = new byte[32]; + Arrays.fill(this.tx_hash, (byte) 0x00); + }},new TxNumValue(){{ + this.tx_num = 101; + }}); + this.database.claim_takeover.stashPut(new ClaimTakeoverKey(){{ + this.normalized_name = name; + }},new ClaimTakeoverValue(){{ + this.claim_hash = claimHash3; + this.height = 101; + }}); + + this.database.db_state.stashPut(KeyInterface.NULL,new DBState(){{ + this.genesis = new byte[]{'n','?',(byte) 0xcf,0x12,(byte) 0x99,(byte) 0xd4,(byte) 0xec,']','y',(byte) 0xc3,(byte) 0xa4,(byte) 0xc9,0x1d,'b','J','J',(byte) 0xcf,(byte) 0x9e,'.',0x17,'=',(byte) 0x95,(byte) 0xa1,(byte) 0xa0,'P','O','g','v','i','h','u','V'}; + this.height = 0; + this.tx_count = 1; + this.tip = new byte[32]; //TODO + this.utxo_flush_count = 1; + this.wall_time = 0; + this.bit_fields = 1; + this.db_version = 7; + this.hist_flush_count = 1; + this.comp_flush_count = -1; + this.comp_cursor = -1; + this.es_sync_height = 0; + this.hashX_status_last_indexed_height = 0; + // 0 + }}); + this.database.unsafeCommit(); + + DBState state = (DBState) this.database.db_state.get(KeyInterface.NULL); + assertArrayEquals(new byte[]{'n','?',(byte) 0xcf,0x12,(byte) 0x99,(byte) 0xd4,(byte) 0xec,']','y',(byte) 0xc3,(byte) 0xa4,(byte) 0xc9,0x1d,'b','J','J',(byte) 0xcf,(byte) 0x9e,'.',0x17,'=',(byte) 0x95,(byte) 0xa1,(byte) 0xa0,'P','O','g','v','i','h','u','V'},state.genesis); + + { + Map actualMap = new HashMap<>(); + RocksIterator iterator = this.database.claim_expiration.iterate(); + iterator.seekToFirst(); + while(iterator.isValid()){ + if(this.database.claim_expiration.unpackKey(iterator.key()).expiration==98){ + actualMap.put(iterator.key(),iterator.value()); + } + iterator.next(); + } + assertEquals(0,actualMap.size()); + } + //TODO (start=98 & stop=99) vs (prefix=98) + //TODO (start=99 & stop=100) vs (prefix=99) + { + Map expectedMap = new HashMap<>(); + expectedMap.put(this.database.claim_expiration.packKey(new ClaimExpirationKey(){{ + this.expiration = 99; + this.tx_num = 999; + this.position = 0; + }}),this.database.claim_expiration.packValue(new ClaimExpirationValue(){{ + this.claim_hash = claimHash0; + this.normalized_name = name; + }})); + Map actualMap = new HashMap<>(); + RocksIterator iterator = this.database.claim_expiration.iterate(); + iterator.seekToFirst(); + while(iterator.isValid()){ + if(this.database.claim_expiration.unpackKey(iterator.key()).expiration==99){ + actualMap.put(iterator.key(),iterator.value()); + } + iterator.next(); + } + assertEquals(expectedMap.size(),actualMap.size()); + Iterator> expectedEntrySetIterator = expectedMap.entrySet().iterator(); + Iterator> actualEntrySetIterator = actualMap.entrySet().iterator(); + for(int i=0;i expectedEntry = expectedEntrySetIterator.next(); + Map.Entry actualEntry = actualEntrySetIterator.next(); + assertArrayEquals(expectedEntry.getKey(),actualEntry.getKey()); + assertArrayEquals(expectedEntry.getValue(),actualEntry.getValue()); + } + } + { + Map expectedMap = new HashMap<>(); + expectedMap.put(this.database.claim_expiration.packKey(new ClaimExpirationKey(){{ + this.expiration = 100; + this.tx_num = 1000; + this.position = 0; + }}),this.database.claim_expiration.packValue(new ClaimExpirationValue(){{ + this.claim_hash = claimHash1; + this.normalized_name = name; + }})); + expectedMap.put(this.database.claim_expiration.packKey(new ClaimExpirationKey(){{ + this.expiration = 100; + this.tx_num = 1001; + this.position = 0; + }}),this.database.claim_expiration.packValue(new ClaimExpirationValue(){{ + this.claim_hash = claimHash2; + this.normalized_name = name; + }})); + Map actualMap = new HashMap<>(); + RocksIterator iterator = this.database.claim_expiration.iterate(); + iterator.seekToLast(); + while(iterator.isValid()){ + if(this.database.claim_expiration.unpackKey(iterator.key()).expiration==100){ + actualMap.put(iterator.key(),iterator.value()); + } + iterator.prev(); // ? + } + assertEquals(expectedMap.size(),actualMap.size()); + Iterator> expectedEntrySetIterator = expectedMap.entrySet().iterator(); + Iterator> actualEntrySetIterator = actualMap.entrySet().iterator(); + for(int i=0;i expectedEntry = expectedEntrySetIterator.next(); + Map.Entry actualEntry = actualEntrySetIterator.next(); + assertArrayEquals(expectedEntry.getKey(),actualEntry.getKey()); + assertArrayEquals(expectedEntry.getValue(),actualEntry.getValue()); + } + } + //TODO (start=100 & stop=101) vs (prefix=100) + { + Map expectedMap = new HashMap<>(); + expectedMap.put(this.database.claim_expiration.packKey(new ClaimExpirationKey(){{ + this.expiration = overflowValue-1; + this.tx_num = 1003; + this.position = 0; + }}),this.database.claim_expiration.packValue(new ClaimExpirationValue(){{ + this.claim_hash = claimHash3; + this.normalized_name = name; + }})); + Map actualMap = new HashMap<>(); + RocksIterator iterator = this.database.claim_expiration.iterate(); + iterator.seekToFirst(); + while(iterator.isValid()){ + if(this.database.claim_expiration.unpackKey(iterator.key()).expiration==overflowValue-1){ + actualMap.put(iterator.key(),iterator.value()); + } + iterator.next(); + } + assertEquals(expectedMap.size(),actualMap.size()); + Iterator> expectedEntrySetIterator = expectedMap.entrySet().iterator(); + Iterator> actualEntrySetIterator = actualMap.entrySet().iterator(); + for(int i=0;i expectedEntry = expectedEntrySetIterator.next(); + Map.Entry actualEntry = actualEntrySetIterator.next(); + assertArrayEquals(expectedEntry.getKey(),actualEntry.getKey()); + assertArrayEquals(expectedEntry.getValue(),actualEntry.getValue()); + } + } + { + Map expectedMap = new HashMap<>(); + expectedMap.put(this.database.claim_expiration.packKey(new ClaimExpirationKey(){{ + this.expiration = overflowValue; + this.tx_num = 1004; + this.position = 0; + }}),this.database.claim_expiration.packValue(new ClaimExpirationValue(){{ + this.claim_hash = claimHash3; + this.normalized_name = name; + }})); + Map actualMap = new HashMap<>(); + RocksIterator iterator = this.database.claim_expiration.iterate(); + iterator.seekToFirst(); + while(iterator.isValid()){ + if(this.database.claim_expiration.unpackKey(iterator.key()).expiration==overflowValue){ + actualMap.put(iterator.key(),iterator.value()); + } + iterator.next(); + } + assertEquals(expectedMap.size(),actualMap.size()); + Iterator> expectedEntrySetIterator = expectedMap.entrySet().iterator(); + Iterator> actualEntrySetIterator = actualMap.entrySet().iterator(); + for(int i=0;i expectedEntry = expectedEntrySetIterator.next(); + Map.Entry actualEntry = actualEntrySetIterator.next(); + assertArrayEquals(expectedEntry.getKey(),actualEntry.getKey()); + assertArrayEquals(expectedEntry.getValue(),actualEntry.getValue()); + } + } + } @Test public void testHubDatabaseIteratorStartStop() throws RocksDBException{