Search in sources :

Example 1 with MMFMapTable

use of com.ctriposs.sdb.table.MMFMapTable in project sessdb by ppdai.

the class Level0MergerTest method testCase02.

@Test
public void testCase02() throws IOException, ClassNotFoundException {
    HashMapTable[] sourceTables = new HashMapTable[4];
    LevelQueue lq0 = new LevelQueue();
    for (int i = 0; i < 4; i++) {
        sourceTables[i] = new HashMapTable(testDir, SDB.LEVEL0, System.nanoTime() + i);
        sourceTables[i].setCompressionEnabled(true);
        lq0.addFirst(sourceTables[i]);
        assertTrue(sourceTables[i].isImmutable());
    }
    // delete
    int max = AbstractMapTable.INIT_INDEX_ITEMS_PER_TABLE;
    HashMapTable table4 = sourceTables[3];
    int start = 0;
    while (start < max) {
        table4.delete(String.valueOf(start).getBytes());
        start = start + 4;
    }
    // expiration
    HashMapTable table3 = sourceTables[2];
    start = 1;
    while (start < max) {
        table3.put(String.valueOf(start).getBytes(), String.valueOf(start).getBytes(), 200, System.currentTimeMillis());
        start = start + 4;
    }
    // expire table3
    try {
        Thread.sleep(2000);
    } catch (InterruptedException e) {
    // ignore
    }
    // time to live 60 sec
    HashMapTable table2 = sourceTables[1];
    start = 2;
    while (start < max) {
        table2.put(String.valueOf(start).getBytes(), String.valueOf(start).getBytes(), 60 * 1000, System.currentTimeMillis());
        start = start + 4;
    }
    // time to live 120 sec with items that have been updated(table 2), deleted(table 4) and expired(table 3)
    HashMapTable table1 = sourceTables[0];
    start = 0;
    while (start < max) {
        table1.put(String.valueOf(start).getBytes(), String.valueOf(start).getBytes(), 120 * 1000, System.currentTimeMillis());
        start = start + 1;
    }
    LevelQueue lq1 = new LevelQueue();
    Level0Merger.mergeSort(lq0, lq1, 4, testDir, (short) 0);
    for (int i = 0; i < 4; i++) {
        assertTrue(sourceTables[i].isImmutable());
    }
    assertTrue(lq1.size() == 1);
    MMFMapTable targetTable = (MMFMapTable) lq1.poll();
    assertTrue(targetTable.getLevel() == SDB.LEVEL1);
    assertTrue(targetTable.getAppendedSize() == max);
    // validate delete
    start = 0;
    while (start < max) {
        GetResult result = targetTable.get(String.valueOf(start).getBytes());
        assertTrue(result.isFound());
        assertTrue(result.isDeleted());
        start += 4;
    }
    // validate expiration
    start = 1;
    while (start < max) {
        GetResult result = targetTable.get(String.valueOf(start).getBytes());
        assertTrue(result.isFound());
        assertTrue(result.isExpired());
        start += 4;
    }
    // validate ttl 60s
    start = 2;
    while (start < max) {
        GetResult result = targetTable.get(String.valueOf(start).getBytes());
        assertTrue(result.isFound());
        assertTrue(result.getTimeToLive() == 60 * 1000);
        start += 4;
    }
    // validate ttl 120s
    start = 3;
    while (start < max) {
        GetResult result = targetTable.get(String.valueOf(start).getBytes());
        assertTrue(result.isFound());
        assertTrue(result.getTimeToLive() == 120 * 1000);
        start += 4;
    }
    List<String> keyList = new ArrayList<String>();
    for (long i = 0; i < max; i++) {
        keyList.add(String.valueOf(i));
    }
    Collections.sort(keyList, new Comparator<String>() {

        @Override
        public int compare(String arg0, String arg1) {
            int hash0 = Arrays.hashCode(arg0.getBytes());
            int hash1 = Arrays.hashCode(arg1.getBytes());
            if (hash0 < hash1)
                return -1;
            else if (hash0 > hash1)
                return 1;
            else
                return 0;
        }
    });
    for (int i = 0; i < max; i++) {
        IMapEntry mapEntry = targetTable.getMapEntry(i);
        assertTrue(mapEntry.getIndex() == i);
        assertTrue(new String(mapEntry.getKey()).equals(keyList.get(i)));
        int intKey = Integer.parseInt(new String(mapEntry.getKey()));
        // validate disk space optimization
        if (// deleted
        intKey % 4 == 0)
            assertTrue(Arrays.equals(new byte[] { 0 }, mapEntry.getValue()));
        else if (// expired
        intKey % 4 == 1)
            assertTrue(Arrays.equals(new byte[] { 0 }, mapEntry.getValue()));
        else {
            assertTrue(new String(Snappy.uncompress(mapEntry.getValue())).equals(keyList.get(i)));
        //assertTrue(new String(mapEntry.getValue()).equals(keyList.get(i)));
        }
    }
    Random random = new Random();
    for (int i = 0; i < 1024; i++) {
        long key = random.nextInt(max);
        GetResult result = targetTable.get(String.valueOf(key).getBytes());
        assertTrue(result.isFound());
    }
    targetTable.close();
    targetTable.delete();
}
Also used : MMFMapTable(com.ctriposs.sdb.table.MMFMapTable) GetResult(com.ctriposs.sdb.table.GetResult) IMapEntry(com.ctriposs.sdb.table.IMapEntry) ArrayList(java.util.ArrayList) LevelQueue(com.ctriposs.sdb.LevelQueue) HashMapTable(com.ctriposs.sdb.table.HashMapTable) Random(java.util.Random) Test(org.junit.Test)

Example 2 with MMFMapTable

use of com.ctriposs.sdb.table.MMFMapTable in project sessdb by ppdai.

the class MMFMapTableTest method testAppendAndGet.

@Test
public void testAppendAndGet() throws IOException, ClassNotFoundException {
    long createdTime = System.nanoTime();
    mapTable = new MMFMapTable(testDir, 1, createdTime, 1000, 4);
    assertTrue(mapTable.getLevel() == 1);
    assertTrue(mapTable.getCreatedTime() == createdTime);
    assertTrue(mapTable.getAppendedSize() == 0);
    assertTrue(mapTable.isEmpty());
    //assertTrue(mapTable.getBackFileSize() == (MMFMapTable.INIT_INDEX_FILE_SIZE + MMFMapTable.INIT_DATA_FILE_SIZE) * Level0Merger.DEFAULT_MERGE_WAYS);
    mapTable.appendNew("key".getBytes(), "value".getBytes(), 500);
    assertTrue(mapTable.getLevel() == 1);
    assertTrue(mapTable.getCreatedTime() == createdTime);
    assertTrue(mapTable.getAppendedSize() == 1);
    assertFalse(mapTable.isEmpty());
    GetResult result = mapTable.get("key".getBytes());
    assertTrue(result.isFound());
    assertTrue(!result.isDeleted());
    assertTrue(!result.isExpired());
    try {
        Thread.sleep(1000);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
    result = mapTable.get("key".getBytes());
    assertTrue(result.isFound());
    assertTrue(!result.isDeleted());
    assertTrue(result.isExpired());
    result = mapTable.get("key1".getBytes());
    assertFalse(result.isFound());
    assertFalse(mapTable.isUsable());
}
Also used : MMFMapTable(com.ctriposs.sdb.table.MMFMapTable) GetResult(com.ctriposs.sdb.table.GetResult) Test(org.junit.Test)

Example 3 with MMFMapTable

use of com.ctriposs.sdb.table.MMFMapTable in project sessdb by ppdai.

the class Level0Merger method mergeSort.

public static void mergeSort(LevelQueue source, LevelQueue target, int ways, String dir, short shard) throws IOException, ClassNotFoundException {
    List<HashMapTable> tables = new ArrayList<HashMapTable>(ways);
    source.getReadLock().lock();
    try {
        Iterator<AbstractMapTable> iter = source.descendingIterator();
        for (int i = 0; i < ways; i++) {
            tables.add((HashMapTable) iter.next());
        }
    } finally {
        source.getReadLock().unlock();
    }
    int expectedInsertions = 0;
    for (HashMapTable table : tables) {
        expectedInsertions += table.getRealSize();
    }
    // target table
    MMFMapTable sortedMapTable = new MMFMapTable(dir, shard, SDB.LEVEL1, System.nanoTime(), expectedInsertions, ways);
    PriorityQueue<QueueElement> pq = new PriorityQueue<QueueElement>();
    // build initial heap
    for (HashMapTable table : tables) {
        QueueElement qe = new QueueElement();
        final HashMapTable hmTable = table;
        qe.hashMapTable = hmTable;
        List<Map.Entry<ByteArrayWrapper, InMemIndex>> list = new ArrayList<Map.Entry<ByteArrayWrapper, InMemIndex>>(qe.hashMapTable.getEntrySet());
        Collections.sort(list, new Comparator<Map.Entry<ByteArrayWrapper, InMemIndex>>() {

            @Override
            public int compare(Entry<ByteArrayWrapper, InMemIndex> o1, Entry<ByteArrayWrapper, InMemIndex> o2) {
                IMapEntry mapEntry1 = hmTable.getMapEntry(o1.getValue().getIndex());
                IMapEntry mapEntry2 = hmTable.getMapEntry(o2.getValue().getIndex());
                try {
                    int hash1 = mapEntry1.getKeyHash();
                    int hash2 = mapEntry2.getKeyHash();
                    if (hash1 < hash2)
                        return -1;
                    else if (hash1 > hash2)
                        return 1;
                    else {
                        return o1.getKey().compareTo(o2.getKey());
                    }
                } catch (IOException e) {
                    throw new RuntimeException("Fail to get hash code in map entry", e);
                }
            }
        });
        qe.iterator = list.iterator();
        if (qe.iterator.hasNext()) {
            Map.Entry<ByteArrayWrapper, InMemIndex> me = qe.iterator.next();
            qe.key = me.getKey().getData();
            qe.inMemIndex = me.getValue();
            IMapEntry mapEntry = table.getMapEntry(qe.inMemIndex.getIndex());
            qe.keyHash = mapEntry.getKeyHash();
            pq.add(qe);
        }
    }
    // merge sort
    while (pq.size() > 0) {
        QueueElement qe1 = pq.poll();
        // remove old/stale entries
        while (pq.peek() != null && qe1.keyHash == pq.peek().keyHash && BytesUtil.compare(qe1.key, pq.peek().key) == 0) {
            QueueElement qe2 = pq.poll();
            if (qe2.iterator.hasNext()) {
                Map.Entry<ByteArrayWrapper, InMemIndex> me = qe2.iterator.next();
                qe2.key = me.getKey().getData();
                qe2.inMemIndex = me.getValue();
                IMapEntry mapEntry = qe2.hashMapTable.getMapEntry(qe2.inMemIndex.getIndex());
                qe2.keyHash = mapEntry.getKeyHash();
                pq.add(qe2);
            }
        }
        IMapEntry mapEntry = qe1.hashMapTable.getMapEntry(qe1.inMemIndex.getIndex());
        byte[] value = mapEntry.getValue();
        // disk space optimization
        if (mapEntry.isDeleted() || mapEntry.isExpired()) {
            value = new byte[] { 0 };
        }
        sortedMapTable.appendNew(mapEntry.getKey(), mapEntry.getKeyHash(), value, mapEntry.getTimeToLive(), mapEntry.getCreatedTime(), mapEntry.isDeleted(), mapEntry.isCompressed());
        if (qe1.iterator.hasNext()) {
            Map.Entry<ByteArrayWrapper, InMemIndex> me = qe1.iterator.next();
            qe1.key = me.getKey().getData();
            qe1.inMemIndex = me.getValue();
            IMapEntry mEntry = qe1.hashMapTable.getMapEntry(qe1.inMemIndex.getIndex());
            qe1.keyHash = mEntry.getKeyHash();
            pq.add(qe1);
        }
    }
    // persist metadata
    sortedMapTable.reMap();
    sortedMapTable.saveMetadata();
    // dump to level 1
    source.getWriteLock().lock();
    target.getWriteLock().lock();
    try {
        for (int i = 0; i < ways; i++) {
            source.removeLast();
        }
        for (HashMapTable table : tables) {
            table.markUsable(false);
        }
        sortedMapTable.markUsable(true);
        target.addFirst(sortedMapTable);
    } finally {
        target.getWriteLock().unlock();
        source.getWriteLock().unlock();
    }
    for (HashMapTable table : tables) {
        table.close();
        table.delete();
    }
}
Also used : MMFMapTable(com.ctriposs.sdb.table.MMFMapTable) AbstractMapTable(com.ctriposs.sdb.table.AbstractMapTable) InMemIndex(com.ctriposs.sdb.table.InMemIndex) IMapEntry(com.ctriposs.sdb.table.IMapEntry) ArrayList(java.util.ArrayList) IOException(java.io.IOException) HashMapTable(com.ctriposs.sdb.table.HashMapTable) PriorityQueue(java.util.PriorityQueue) IMapEntry(com.ctriposs.sdb.table.IMapEntry) Entry(java.util.Map.Entry) ByteArrayWrapper(com.ctriposs.sdb.table.ByteArrayWrapper) Map(java.util.Map)

Example 4 with MMFMapTable

use of com.ctriposs.sdb.table.MMFMapTable in project sessdb by ppdai.

the class MMFMapTableTest method testLoopAndReopen.

@Test
public void testLoopAndReopen() throws IOException, ClassNotFoundException {
    long createdTime = System.nanoTime();
    int loop = 32 * 1024;
    mapTable = new MMFMapTable(testDir, 1, createdTime, loop, 4);
    assertTrue(mapTable.getLevel() == 1);
    assertTrue(mapTable.getCreatedTime() == createdTime);
    assertTrue(mapTable.getAppendedSize() == 0);
    assertTrue(mapTable.isEmpty());
    //assertTrue(mapTable.getBackFileSize() == (MMFMapTable.INIT_INDEX_FILE_SIZE + MMFMapTable.INIT_DATA_FILE_SIZE) * Level0Merger.DEFAULT_MERGE_WAYS);
    assertFalse(mapTable.isUsable());
    List<byte[]> list = new ArrayList<byte[]>();
    for (int i = 0; i < loop; i++) {
        list.add(("key" + i).getBytes());
    }
    Collections.sort(list, new Comparator<byte[]>() {

        @Override
        public int compare(byte[] arg0, byte[] arg1) {
            int hash0 = Arrays.hashCode(arg0);
            int hash1 = Arrays.hashCode(arg1);
            if (hash0 < hash1)
                return -1;
            else if (hash0 > hash1)
                return 1;
            else
                return 0;
        }
    });
    for (int i = 0; i < loop; i++) {
        mapTable.appendNew(list.get(i), ("value" + i).getBytes(), -1);
    }
    assertTrue(mapTable.getAppendedSize() == loop);
    mapTable.reMap();
    assertTrue(mapTable.getBackFileSize() < (MMFMapTable.INIT_INDEX_FILE_SIZE + MMFMapTable.INIT_DATA_FILE_SIZE) * Level0Merger.DEFAULT_MERGE_WAYS);
    long start = System.currentTimeMillis();
    for (int i = 0; i < loop; i++) {
        GetResult result = mapTable.get(("key" + i).getBytes());
        assertTrue(result.isFound());
    }
    long time = System.currentTimeMillis() - start;
    System.out.printf("Get %,d K ops per second%n", (int) (loop / time));
    GetResult result = mapTable.get(("key" + loop).getBytes());
    assertFalse(result.isFound());
    assertFalse(result.isDeleted() || result.isExpired());
    mapTable.markUsable(true);
    mapTable.saveMetadata();
    mapTable.close();
    mapTable = new MMFMapTable(testDir, mapTable.getFileName());
    assertTrue(mapTable.isUsable());
    assertTrue(mapTable.getAppendedSize() == loop);
    for (int i = 0; i < loop; i++) {
        result = mapTable.get(("key" + i).getBytes());
        assertTrue(result.isFound());
    }
    result = mapTable.get(("key" + loop).getBytes());
    assertFalse(result.isFound());
    assertFalse(result.isDeleted() || result.isExpired());
    mapTable.markUsable(false);
    mapTable.saveMetadata();
    mapTable.close();
    mapTable = new MMFMapTable(testDir, mapTable.getFileName());
    assertFalse(mapTable.isUsable());
    assertTrue(mapTable.getAppendedSize() == loop);
    for (int i = 0; i < loop; i++) {
        result = mapTable.get(("key" + i).getBytes());
        assertTrue(result.isFound());
    }
}
Also used : MMFMapTable(com.ctriposs.sdb.table.MMFMapTable) GetResult(com.ctriposs.sdb.table.GetResult) ArrayList(java.util.ArrayList) Test(org.junit.Test)

Example 5 with MMFMapTable

use of com.ctriposs.sdb.table.MMFMapTable in project sessdb by ppdai.

the class MMFMapTableTest method operationAfterClosedTest.

@Test
public void operationAfterClosedTest() throws Exception {
    long createdTime = System.nanoTime();
    mapTable = new MMFMapTable(testDir, 1, createdTime, 1, 4);
    mapTable.close();
    final byte[] testKey = new byte[] { 1 }, testValue = new byte[] { 1 };
    try {
        mapTable.appendNew(testKey, testValue, 1000);
        fail("Should not get here after the SDB is closed.");
    } catch (IllegalStateException e) {
    }
    try {
        mapTable.appendNew(testKey, Arrays.hashCode(testKey), testValue, 1000, System.currentTimeMillis(), false, false);
        fail("Should not get here after the SDB is closed.");
    } catch (IllegalStateException e) {
    }
    try {
        mapTable.getMapEntry(0);
        fail("Should not get here after the SDB is closed.");
    } catch (IllegalStateException e) {
    }
    try {
        mapTable.reMap();
        fail("Should not get here after the SDB is closed.");
    } catch (IllegalStateException e) {
    }
    try {
        mapTable.persistToAppendDataFileOffset();
        fail("Should not get here after the SDB is closed.");
    } catch (IllegalStateException e) {
    }
    try {
        mapTable.persistToAppendIndex();
        fail("Should not get here after the SDB is closed.");
    } catch (IllegalStateException e) {
    }
    try {
        mapTable.persistBloomFilter();
        fail("Should not get here after the SDB is closed.");
    } catch (IllegalStateException e) {
    }
    try {
        mapTable.saveMetadata();
        fail("Should not get here after the SDB is closed.");
    } catch (IllegalStateException e) {
    }
}
Also used : MMFMapTable(com.ctriposs.sdb.table.MMFMapTable) Test(org.junit.Test)

Aggregations

MMFMapTable (com.ctriposs.sdb.table.MMFMapTable)10 Test (org.junit.Test)8 GetResult (com.ctriposs.sdb.table.GetResult)7 ArrayList (java.util.ArrayList)6 IMapEntry (com.ctriposs.sdb.table.IMapEntry)5 LevelQueue (com.ctriposs.sdb.LevelQueue)4 HashMapTable (com.ctriposs.sdb.table.HashMapTable)4 Random (java.util.Random)4 FCMapTable (com.ctriposs.sdb.table.FCMapTable)3 AbstractMapTable (com.ctriposs.sdb.table.AbstractMapTable)2 PriorityQueue (java.util.PriorityQueue)2 ByteArrayWrapper (com.ctriposs.sdb.table.ByteArrayWrapper)1 InMemIndex (com.ctriposs.sdb.table.InMemIndex)1 File (java.io.File)1 FilenameFilter (java.io.FilenameFilter)1 IOException (java.io.IOException)1 Map (java.util.Map)1 Entry (java.util.Map.Entry)1