gridool.dht.impl.DefaultLocalDirectory.java Source code

Java tutorial

Introduction

Here is the source code for gridool.dht.impl.DefaultLocalDirectory.java

Source

/*
 * @(#)$Id$
 *
 * Copyright 2006-2008 Makoto YUI
 *
 * Licensed 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.
 * 
 * Contributors:
 *     Makoto YUI - initial implementation
 */
package gridool.dht.impl;

import gridool.Settings;
import gridool.dht.AbstractLocalDirectory;
import gridool.dht.btree.BIndexFile;
import gridool.dht.btree.BIndexMultiValueFile;
import gridool.dht.btree.CallbackHandler;
import gridool.dht.btree.IndexException;
import gridool.dht.btree.IndexQuery;
import gridool.dht.btree.Paged;
import gridool.dht.btree.Value;
import gridool.dht.btree.BasicIndexQuery.IndexConditionEQ;
import gridool.dht.btree.BasicIndexQuery.IndexConditionSW;
import gridool.locking.LockManager;
import gridool.util.GridUtils;
import gridool.util.primitive.Primitives;

import java.io.File;
import java.util.Collection;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;

import javax.annotation.CheckForNull;
import javax.annotation.Nonnull;
import javax.annotation.concurrent.ThreadSafe;

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

/**
 * 
 * <DIV lang="en"></DIV>
 * <DIV lang="ja"></DIV>
 * 
 * @author Makoto YUI (yuin405@gmail.com)
 */
@ThreadSafe
public final class DefaultLocalDirectory extends AbstractLocalDirectory {
    private static final Log LOG = LogFactory.getLog(DefaultLocalDirectory.class);
    private static final String IDX_SUFFIX_NAME = ".bfile";

    private static final float dataCacheRatio;
    private static final float nodeCachePurgePerc, datacachePurgePerc;
    static {
        dataCacheRatio = Primitives.parseFloat(Settings.get("gridool.dht.ld.bfile.bulkload.datacache_ratio"), 0.4f);
        nodeCachePurgePerc = Primitives
                .parseFloat(Settings.get("gridool.dht.ld.bfile.bulkload.nodecache_purgeperc"), 0.1f);
        datacachePurgePerc = Primitives
                .parseFloat(Settings.get("gridool.dht.ld.bfile.bulkload.datacache_purgeperc"), 0.2f);
    }

    @Nonnull
    private final ConcurrentMap<String, BIndexFile> map;
    private BIndexFile defaultIndex;

    public DefaultLocalDirectory(@CheckForNull LockManager lockManger) {
        super(lockManger);
        this.map = new ConcurrentHashMap<String, BIndexFile>(16);
    }

    @SuppressWarnings("unchecked")
    public BIndexFile getInternalIndex(String idxName) {
        return map.get(idxName);
    }

    public void start() throws IndexException {
        BIndexFile idx = createIndex(DEFAULT_IDX_NAME, true);
        map.put(DEFAULT_IDX_NAME, idx);
        this.defaultIndex = idx;
    }

    public void close() throws IndexException {
        final Collection<BIndexFile> values = map.values();
        if (DELETE_IDX_ON_EXIT) {
            for (BIndexFile btree : values) {
                btree.drop();
            }
        } else {
            for (BIndexFile btree : values) {
                btree.close();
            }
        }
    }

    public boolean create(String idxName) throws IndexException {
        synchronized (map) {
            BIndexFile btree = map.get(idxName);
            if (btree == null) {
                btree = createIndex(idxName, false);
                btree.init(false);
                map.put(idxName, btree);
                return true;
            }
        }
        return false;
    }

    public void drop(String... idxNames) throws IndexException {
        for (String idx : idxNames) {
            final BIndexFile btree = map.remove(idx);
            if (btree != null) {
                btree.drop();
            }
        }
    }

    public void sync(String... idxNames) throws IndexException {
        for (String idx : idxNames) {
            final BIndexFile btree = map.get(idx);
            if (btree != null) {
                btree.flush(true, false);
            }
        }
    }

    public void purgeAll(boolean clear) throws IndexException {
        for (BIndexFile btree : map.values()) {
            if (btree != null) {
                btree.flush(true, clear);
            }
        }
    }

    @Override
    public byte[] get(byte[] key) throws IndexException {
        Value k = new Value(key);
        return defaultIndex.getValueBytes(k);
    }

    @Override
    public void set(byte[] key, byte[] value) throws IndexException {
        defaultIndex.putValue(new Value(key), value);
    }

    public void addMapping(final String idxName, final byte[][] keys, final byte[] value) throws IndexException {
        final BIndexFile btree = openIndex(idxName);
        for (byte[] k : keys) {
            btree.addValue(new Value(k), value);
        }
    }

    public void addMapping(final String idxName, final byte[][] keys, final byte[][] values) throws IndexException {
        if (keys.length != values.length) {
            throw new IllegalArgumentException();
        }

        final BIndexFile btree = openIndex(idxName);
        final int length = keys.length;
        for (int i = 0; i < length; i++) {
            btree.addValue(new Value(keys[i]), values[i]);
        }
    }

    public void setMapping(String idxName, byte[][] keys, byte[][] values) throws IndexException {
        if (keys.length != values.length) {
            throw new IllegalArgumentException();
        }

        final BIndexFile btree = openIndex(idxName);
        final int length = keys.length;
        for (int i = 0; i < length; i++) {
            btree.putValue(new Value(keys[i]), values[i]);
        }
    }

    public byte[][] removeMapping(final String idxName, final byte[] key) throws IndexException {
        BIndexFile btree = map.get(idxName);
        if (btree != null) {
            Value k = new Value(key);
            return btree.remove(k);
        }
        return null;
    }

    public boolean removeMapping(final String idxName, final byte[]... keys) throws IndexException {
        final BIndexFile btree = map.get(idxName);
        if (btree != null) {
            boolean foundAll = true;
            for (byte[] key : keys) {
                Value k = new Value(key);
                if (btree.remove(k) == null) {
                    foundAll = false;
                }
            }
            return foundAll;
        }
        return false;
    }

    public void exactSearch(final String idxName, final byte[] key, final CallbackHandler handler)
            throws IndexException {
        final BIndexFile btree = map.get(idxName);
        if (btree == null) {
            return;
        }
        Value k = new Value(key);
        IndexQuery query = new IndexConditionEQ(k);
        btree.search(query, handler);
    }

    public void prefixSearch(final String idxName, final byte[] key, final CallbackHandler handler)
            throws IndexException {
        final BIndexFile btree = map.get(idxName);
        if (btree == null) {
            return;
        }
        Value k = new Value(key);
        IndexQuery query = new IndexConditionSW(k);
        btree.search(query, handler);
    }

    public void retrieve(String idxName, IndexQuery query, CallbackHandler callback) throws IndexException {
        final BIndexFile btree = map.get(idxName);
        if (btree == null) {
            return;
        }
        btree.search(query, callback);
    }

    private BIndexFile openIndex(final String idxName) throws IndexException {
        BIndexFile btree;
        synchronized (map) {
            btree = map.get(idxName);
            if (btree == null) {
                btree = createIndex(idxName, false);
                btree.init(false);
                map.put(idxName, btree);
            }
        }
        return btree;
    }

    private BIndexFile createIndex(final String name, final boolean create) throws IndexException {
        File colDir = GridUtils.getIndexDir(true);
        File idxFile = new File(colDir, name + IDX_SUFFIX_NAME);
        Integer cacheSize = getCacheSize(name);
        final BIndexFile btree;
        if (cacheSize == null) {
            btree = new BIndexMultiValueFile(idxFile); //new BIndexFile(idxFile, true);
        } else {
            int idxCaches = cacheSize.intValue();
            int dataCaches = (int) (idxCaches * dataCacheRatio);
            //btree = new BIndexFile(idxFile, Paged.DEFAULT_PAGESIZE, idxCaches, dataCaches, true);
            btree = new BIndexMultiValueFile(idxFile, Paged.DEFAULT_PAGESIZE, idxCaches, dataCaches);
        }
        if (DELETE_IDX_ON_EXIT) {
            if (idxFile.exists()) {
                if (!idxFile.delete()) {
                    throw new IndexException("Could not prepared a file: " + idxFile.getAbsolutePath());
                }
            }
        }
        if (create) {
            btree.init(false);
        }
        LOG.info("Use an original B+tree index on " + idxFile.getAbsolutePath() + " for LocalDirectory");
        return btree;
    }

    @Override
    public void setBulkloading(boolean enable, String... idxNames) {
        if (idxNames.length == 0) {
            for (BIndexFile bfile : map.values()) {
                if (bfile != null) {
                    bfile.setBulkloading(enable, nodeCachePurgePerc, datacachePurgePerc);
                }
            }
        } else {
            for (String idxName : idxNames) {
                BIndexFile bfile = map.get(idxName);
                if (bfile != null) {
                    bfile.setBulkloading(enable, nodeCachePurgePerc, datacachePurgePerc);
                }
            }
        }
    }

}