Search in sources :

Example 1 with AbstractMapTable

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

the class SDB method close.

@Override
public void close() throws IOException {
    if (closed)
        return;
    fileStatsCollector.setStop();
    for (int i = 0; i < config.getShardNumber(); i++) {
        this.activeInMemTables[i].close();
    }
    for (int i = 0; i < config.getShardNumber(); i++) {
        this.level0Mergers[i].setStop();
        this.level1Mergers[i].setStop();
    }
    for (int i = 0; i < config.getShardNumber(); i++) {
        try {
            log.info("Shard " + i + " waiting level 0 & 1 merge threads to exit...");
            this.countDownLatches[i].await();
        } catch (InterruptedException e) {
        // ignore;
        }
    }
    for (int i = 0; i < config.getShardNumber(); i++) {
        for (int j = 0; j <= MAX_LEVEL; j++) {
            LevelQueue lq = this.levelQueueLists[i].get(j);
            for (AbstractMapTable table : lq) {
                table.close();
            }
        }
    }
    closed = true;
    log.info("DB Closed.");
}
Also used : AbstractMapTable(com.ctriposs.sdb.table.AbstractMapTable)

Example 2 with AbstractMapTable

use of com.ctriposs.sdb.table.AbstractMapTable 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 3 with AbstractMapTable

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

the class FileStatsCollector method run.

@Override
public void run() {
    while (!stop) {
        try {
            for (int level = 0; level <= SDB.MAX_LEVEL; ++level) {
                long fileSize = 0;
                int fileCount = 0;
                for (int shard = 0; shard < levelQueueLists.length; ++shard) {
                    LevelQueue queue = levelQueueLists[shard].get(level);
                    queue.getReadLock().lock();
                    try {
                        for (AbstractMapTable table : queue) {
                            fileSize += table.getBackFileSize();
                        }
                        fileCount += queue.size();
                    } finally {
                        queue.getReadLock().unlock();
                    }
                }
                stats.recordFileStats(level, fileCount, fileSize);
            }
            Thread.sleep(MAX_SLEEP_TIME);
        } catch (Exception ex) {
            log.error("Error occurred in the file stats collector", ex);
        }
    }
}
Also used : AbstractMapTable(com.ctriposs.sdb.table.AbstractMapTable) LevelQueue(com.ctriposs.sdb.LevelQueue)

Example 4 with AbstractMapTable

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

the class Level1Merger method mergeSort.

public static void mergeSort(LevelQueue lq1, LevelQueue lq2, int ways, String dir, short shard) throws IOException, ClassNotFoundException {
    boolean hasLevel2MapTable = lq2.size() > 0;
    List<AbstractMapTable> tables = new ArrayList<AbstractMapTable>(ways);
    lq1.getReadLock().lock();
    try {
        Iterator<AbstractMapTable> iter = lq1.descendingIterator();
        for (int i = 0; i < ways - 1; i++) {
            tables.add(iter.next());
        }
        if (hasLevel2MapTable) {
            tables.add(lq2.get(0));
        } else {
            tables.add(iter.next());
        }
    } finally {
        lq1.getReadLock().unlock();
    }
    long expectedInsertions = 0;
    for (AbstractMapTable table : tables) {
        expectedInsertions += table.getAppendedSize();
    }
    if (expectedInsertions > Integer.MAX_VALUE)
        expectedInsertions = Integer.MAX_VALUE;
    // target table
    AbstractSortedMapTable sortedMapTable = new FCMapTable(dir, shard, SDB.LEVEL2, System.nanoTime(), (int) expectedInsertions);
    PriorityQueue<QueueElement> pq = new PriorityQueue<QueueElement>();
    // build initial heap
    for (AbstractMapTable table : tables) {
        QueueElement qe = new QueueElement();
        qe.sortedMapTable = table;
        qe.size = qe.sortedMapTable.getAppendedSize();
        qe.index = 0;
        qe.queue = new LinkedList<IMapEntry>();
        IMapEntry me = qe.getNextMapEntry();
        if (me != null) {
            qe.key = me.getKey();
            qe.mapEntry = me;
            qe.keyHash = me.getKeyHash();
            pq.add(qe);
        }
    }
    LinkedList<IMapEntry> targetCacheQueue = new LinkedList<IMapEntry>();
    // 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();
            IMapEntry me = qe2.getNextMapEntry();
            if (me != null) {
                qe2.key = me.getKey();
                qe2.mapEntry = me;
                qe2.keyHash = me.getKeyHash();
                pq.add(qe2);
            }
        }
        // remove deleted or expired entries in final merge sorting
        if (!qe1.mapEntry.isDeleted() && !qe1.mapEntry.isExpired()) {
            targetCacheQueue.add(qe1.mapEntry);
        }
        if (targetCacheQueue.size() >= CACHED_MAP_ENTRIES * DEFAULT_MERGE_WAYS) {
            while (targetCacheQueue.size() > 0) {
                IMapEntry mapEntry = targetCacheQueue.poll();
                byte[] value = mapEntry.getValue();
                // disk space optimization
                if (mapEntry.isExpired()) {
                    continue;
                }
                sortedMapTable.appendNew(mapEntry.getKey(), mapEntry.getKeyHash(), value, mapEntry.getTimeToLive(), mapEntry.getCreatedTime(), mapEntry.isDeleted(), mapEntry.isCompressed());
            }
        }
        IMapEntry me = qe1.getNextMapEntry();
        if (me != null) {
            qe1.key = me.getKey();
            qe1.mapEntry = me;
            qe1.keyHash = me.getKeyHash();
            pq.add(qe1);
        }
    }
    // remaining cached entries
    while (targetCacheQueue.size() > 0) {
        IMapEntry mapEntry = targetCacheQueue.poll();
        byte[] value = mapEntry.getValue();
        // disk space optimization
        if (mapEntry.isExpired()) {
            continue;
        }
        sortedMapTable.appendNew(mapEntry.getKey(), mapEntry.getKeyHash(), value, mapEntry.getTimeToLive(), mapEntry.getCreatedTime(), mapEntry.isDeleted(), mapEntry.isCompressed());
    }
    // persist metadata
    sortedMapTable.reMap();
    sortedMapTable.saveMetadata();
    // switching
    lq1.getWriteLock().lock();
    lq2.getWriteLock().lock();
    try {
        for (int i = 0; i < ways - 1; i++) {
            lq1.removeLast();
        }
        if (hasLevel2MapTable) {
            lq2.removeLast();
        } else {
            lq1.removeLast();
        }
        for (AbstractMapTable table : tables) {
            table.markUsable(false);
        }
        sortedMapTable.markUsable(true);
        lq2.addFirst(sortedMapTable);
    } finally {
        lq2.getWriteLock().unlock();
        lq1.getWriteLock().unlock();
    }
    for (AbstractMapTable table : tables) {
        table.close();
        table.delete();
    }
}
Also used : AbstractMapTable(com.ctriposs.sdb.table.AbstractMapTable) IMapEntry(com.ctriposs.sdb.table.IMapEntry) ArrayList(java.util.ArrayList) PriorityQueue(java.util.PriorityQueue) AbstractSortedMapTable(com.ctriposs.sdb.table.AbstractSortedMapTable) LinkedList(java.util.LinkedList) FCMapTable(com.ctriposs.sdb.table.FCMapTable)

Example 5 with AbstractMapTable

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

the class SDB method get.

/**
	 * Get value in the DB with specific key
	 *
	 * @param key map entry key
	 * @return non-null value if the entry exists, not deleted or expired.
	 * null value if the entry does not exist, or exists but deleted or expired.
	 */
public byte[] get(byte[] key) {
    Preconditions.checkArgument(key != null && key.length > 0, "key is empty");
    ensureNotClosed();
    long start = System.nanoTime();
    int reachedLevel = INMEM_LEVEL;
    try {
        short shard = this.getShard(key);
        // check active hashmap table first
        GetResult result = this.activeInMemTables[shard].get(key);
        if (result.isFound()) {
            if (!result.isDeleted() && !result.isExpired()) {
                return result.getValue();
            } else {
                // deleted or expired
                return null;
            }
        } else {
            // check level0 hashmap tables
            reachedLevel = LEVEL0;
            LevelQueue lq0 = levelQueueLists[shard].get(LEVEL0);
            lq0.getReadLock().lock();
            try {
                if (lq0 != null && lq0.size() > 0) {
                    for (AbstractMapTable table : lq0) {
                        result = table.get(key);
                        if (result.isFound())
                            break;
                    }
                }
            } finally {
                lq0.getReadLock().unlock();
            }
            if (result.isFound()) {
                if (!result.isDeleted() && !result.isExpired()) {
                    if (result.getLevel() == SDB.LEVEL2 && this.config.isLocalityEnabled()) {
                        // keep locality
                        this.put(key, result.getValue(), result.getTimeToLive(), result.getCreatedTime(), false);
                    }
                    return result.getValue();
                } else {
                    // deleted or expired
                    return null;
                }
            }
            // check level 1-2 on disk sorted tables
            searchLevel12: {
                for (int level = 1; level <= MAX_LEVEL; level++) {
                    reachedLevel = level;
                    LevelQueue lq = levelQueueLists[shard].get(level);
                    lq.getReadLock().lock();
                    try {
                        if (lq.size() > 0) {
                            for (AbstractMapTable table : lq) {
                                result = table.get(key);
                                if (result.isFound())
                                    break searchLevel12;
                            }
                        }
                    } finally {
                        lq.getReadLock().unlock();
                    }
                }
            }
            if (result.isFound()) {
                if (!result.isDeleted() && !result.isExpired()) {
                    if (result.getLevel() == SDB.LEVEL2 && this.config.isLocalityEnabled()) {
                        // keep locality
                        this.put(key, result.getValue(), result.getTimeToLive(), result.getCreatedTime(), false);
                    }
                    return result.getValue();
                } else {
                    // deleted or expired
                    return null;
                }
            }
        }
    } catch (IOException ioe) {
        stats.recordDBError(Operations.GET);
        throw new RuntimeException("Fail to get value by key, IOException occurr", ioe);
    } finally {
        stats.recordDBOperation(Operations.GET, reachedLevel, System.nanoTime() - start);
    }
    // no luck
    return null;
}
Also used : AbstractMapTable(com.ctriposs.sdb.table.AbstractMapTable) GetResult(com.ctriposs.sdb.table.GetResult) IOException(java.io.IOException)

Aggregations

AbstractMapTable (com.ctriposs.sdb.table.AbstractMapTable)6 PriorityQueue (java.util.PriorityQueue)3 FCMapTable (com.ctriposs.sdb.table.FCMapTable)2 HashMapTable (com.ctriposs.sdb.table.HashMapTable)2 IMapEntry (com.ctriposs.sdb.table.IMapEntry)2 MMFMapTable (com.ctriposs.sdb.table.MMFMapTable)2 IOException (java.io.IOException)2 ArrayList (java.util.ArrayList)2 LevelQueue (com.ctriposs.sdb.LevelQueue)1 AbstractSortedMapTable (com.ctriposs.sdb.table.AbstractSortedMapTable)1 ByteArrayWrapper (com.ctriposs.sdb.table.ByteArrayWrapper)1 GetResult (com.ctriposs.sdb.table.GetResult)1 InMemIndex (com.ctriposs.sdb.table.InMemIndex)1 File (java.io.File)1 FilenameFilter (java.io.FilenameFilter)1 LinkedList (java.util.LinkedList)1 Map (java.util.Map)1 Entry (java.util.Map.Entry)1