com.chinamobile.bcbsp.comm.BDBMap.java Source code

Java tutorial

Introduction

Here is the source code for com.chinamobile.bcbsp.comm.BDBMap.java

Source

/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.chinamobile.bcbsp.comm;

import java.io.File;
import java.io.Serializable;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;

import java.util.Map;
import java.util.Map.Entry;

import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.atomic.AtomicLong;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import com.chinamobile.bcbsp.util.BSPJob;
import com.sleepycat.bind.EntryBinding;
import com.sleepycat.bind.serial.SerialBinding;
import com.sleepycat.bind.serial.StoredClassCatalog;
import com.sleepycat.bind.tuple.TupleBinding;
import com.sleepycat.collections.StoredSortedMap;

import com.sleepycat.je.Database;
import com.sleepycat.je.DatabaseConfig;
import com.sleepycat.je.DatabaseException;
import com.sleepycat.je.DatabaseExistsException;
import com.sleepycat.je.DatabaseNotFoundException;
import com.sleepycat.je.EnvironmentConfig;

/**
 * Persistent Map builded by BerkeleyDB Java edition uing je-4.10.
 * @param <K>
 * @param <V>
 */
public class BDBMap<K extends Serializable, V extends Serializable> implements Cloneable, Serializable {
    /** Class logger. */
    private static final Log LOG = LogFactory.getLog(BDBMap.class);
    /** the Id of serial version. */
    private static final long serialVersionUID = 3427799316155220967L;
    /** one database environment can contain several databases. */
    private transient BdbEnvironment dbEnv;
    /** database for storing key-value. */
    private transient Database mapDb;
    /** Stored Collections provided by dbd. */
    private transient StoredSortedMap<K, V> storedMap;
    /** directory the database. */
    private transient File dbDir;
    /** database name. */
    private transient String dbName;
    /** size of bdMap. */
    private AtomicLong bdbMapSize = new AtomicLong(0);
    /** the map of key frequence. */
    private Map<K, Integer> keyFrequnce = new HashMap<K, Integer>();

    /**
     * Open an existing database.
     * @param db
     * @param keyClass
     * @param valueClass
     * @param classCatalog
     */
    public BDBMap(BSPJob job, Database db, Class<K> keyClass, Class<V> valueClass,
            StoredClassCatalog classCatalog) {
        mapDb = db;
        setDbName(db.getDatabaseName());
        bdbMapSize = new AtomicLong(0);
        bindDatabase(mapDb, keyClass, valueClass, classCatalog);
    }

    /**
     * Create a database.
     * @param dbDir
     * @param dbName
     * @param keyClass
     * @param valueClass
     */
    public BDBMap(BSPJob job, File dbDir, String dbName, Class<K> keyClass, Class<V> valueClass) {

        this.setDbDir(dbDir);
        this.setDbName(dbName);
        bdbMapSize = new AtomicLong(0);
        createAndBindDatabase(dbDir, dbName, keyClass, valueClass);
    }

    /**
     * Bind a database db with BDB's Stored Collection.
     * @param db
     * @param keyClass
     * @param valueClass
     * @param classCatalog
     */
    public void bindDatabase(Database db, Class<K> keyClass, Class<V> valueClass, StoredClassCatalog classCatalog) {
        EntryBinding<K> keyBinding = TupleBinding.getPrimitiveBinding(keyClass);
        EntryBinding<V> valueBinding = TupleBinding.getPrimitiveBinding(valueClass);
        if (keyBinding == null) {
            keyBinding = new SerialBinding<K>(classCatalog, keyClass);
        }
        if (valueBinding == null) {
            valueBinding = new SerialBinding<V>(classCatalog, valueClass);
        }
        mapDb = db;
        storedMap = new StoredSortedMap<K, V>(db, // db
                keyBinding, // Key
                valueBinding, // Value
                true);
    }

    /**
     * Create and Bind a database db using bindDatabase().
     * @param dbDir
     * @param dbName
     * @param keyClass
     * @param valueClass
     */
    public void createAndBindDatabase(File dbDir, String dbName, Class<K> keyClass, Class<V> valueClass)
            throws DatabaseNotFoundException, DatabaseExistsException, DatabaseException, IllegalArgumentException {
        File envFile = null;
        EnvironmentConfig envConfig = null;
        DatabaseConfig dbConfig = null;
        Database db = null;
        try {
            envFile = dbDir;
            envConfig = new EnvironmentConfig();
            envConfig.setAllowCreate(true);
            envConfig.setTransactional(false);
            envConfig.setCachePercent(30);
            envConfig.setConfigParam("je.evictor.nodesPerScan", "20");
            dbConfig = new DatabaseConfig();
            dbConfig.setAllowCreate(true);
            dbConfig.setTransactional(false);
            dbConfig.setTemporary(true);
            dbConfig.setSortedDuplicates(true);
            dbEnv = new BdbEnvironment(envFile, envConfig);
            db = dbEnv.openDatabase(null, dbName, dbConfig);
            bindDatabase(db, keyClass, valueClass, dbEnv.getClassCatalog());
        } catch (DatabaseNotFoundException e) {
            throw e;
        } catch (DatabaseExistsException e) {
            throw e;
        } catch (DatabaseException e) {
            throw e;
        } catch (IllegalArgumentException e) {
            throw e;
        }
    }

    /**
     * return current BDBMap size.
     */
    public int size() {
        synchronized (bdbMapSize) {
            return (int) (bdbMapSize.get());
        }
    }

    /**
     * not used 20140529.
     * */
    public void keyFrequnceIncrement(K key) {
        Integer freq = keyFrequnce.get(key);
        keyFrequnce.put(key, freq == null ? 1 : freq + 1);
    }

    public void keyFrequnceDecrement(K key, int count) {

        Integer freq = keyFrequnce.get(key);
        keyFrequnce.put(key, freq - count);
    }

    public int getkeyFrequnce(K key) {

        int freq = 0;
        try {
            freq = keyFrequnce.get(key);
        } catch (Exception e) {
            LOG.error("BDB getkeyFrequnce Exception", e);
        }
        return freq;

    }

    public K getMostFrequetKey() {

        int maxSize = 0;
        Integer tmp;
        Entry<K, Integer> entry = null;
        Iterator<Entry<K, Integer>> it = keyFrequnce.entrySet().iterator();
        K key = null;
        while (it.hasNext()) {

            entry = it.next();
            tmp = entry.getValue();

            if (tmp > maxSize) {
                maxSize = tmp;
                key = entry.getKey();
            }

        }

        return key;
    }

    /**
     * put a key-value pair into database
     */
    public V put(K key, V value) {
        synchronized (bdbMapSize) {

            storedMap.put(key, value);
            bdbMapSize.incrementAndGet();
        }
        return value;

    }

    /**
     * delete a key-value pair from database
     */
    public V delete(K key) {
        V value;
        try {
            synchronized (bdbMapSize) {
                if (storedMap.containsKey(key)) {
                    int count = getkeyFrequnce(key);
                    value = storedMap.remove(key);
                    bdbMapSize.addAndGet(-count);
                } else
                    value = null;
            }
            return value;
        } catch (Exception e) {
            LOG.error("BDB delete() Exception", e);
        }
        return null;
    }

    public V get(K key) {
        V value = null;
        try {
            value = storedMap.get(key);
        } catch (Exception e) {
            LOG.error("BDB get() Exception", e);
        }
        return value;

    }

    /**
     * When duplicates are allowed, this method return all values associated with
     * the key
     */
    public ConcurrentLinkedQueue<IMessage> getDupilcates(K key) {

        String tmp;
        int indexOf$;
        Collection<V> valueSet = storedMap.duplicates(key);
        ConcurrentLinkedQueue<IMessage> list = new ConcurrentLinkedQueue<IMessage>();

        Iterator<V> it = valueSet.iterator();
        while (it.hasNext()) {
            // Note Need To Be Upgraded.
            IMessage tmpmsg = new BSPMessage();
            tmp = it.next().toString();
            indexOf$ = tmp.indexOf('$');
            tmpmsg.fromString(tmp.substring(indexOf$ + 1));

            list.add(tmpmsg);
        }
        storedMap.remove(key);
        bdbMapSize.addAndGet(-list.size());
        return list;

    }

    /**
     * When duplicates are allowed, this method return values' count associated
     * with the key
     */
    public int getDupilcatesCount(K key) {

        return storedMap.duplicates(key).size();

    }

    /**
     * Return true if the database contains the key.Otherwise return false
     */
    public Boolean containsKey(K key) {
        return storedMap.containsKey(key);
    }

    /**
     * Delete all key-value pairs in the database
     */
    public void clear() {
        keyFrequnce.clear();
        storedMap.clear();
        bdbMapSize.set(0);

    }

    public void shutdown() {
        mapDb.close();
        dbEnv.close();
    }

    /* Zhicheng Liu added */
    public IMessage aMessage(K key) {

        String tmp;
        int indexOf$;
        Collection<V> valueSet = storedMap.duplicates(key);

        Iterator<V> it = valueSet.iterator();

        IMessage tmpmsg = null;

        while (it.hasNext()) {
            // Note Need To Be Upgraded.
            tmpmsg = new BSPMessage();
            tmp = it.next().toString();
            indexOf$ = tmp.indexOf('$');
            tmpmsg.fromString(tmp.substring(indexOf$ + 1));

            break;
        }
        // StoredMap.remove(key);
        return tmpmsg;

    }

    public File getDbDir() {
        return dbDir;
    }

    public void setDbDir(File dbDir) {
        this.dbDir = dbDir;
    }

    public String getDbName() {
        return dbName;
    }

    public void setDbName(String dbName) {
        this.dbName = dbName;
    }

}