okuyama.imdst.util.KeyManagerValueMap.java Source code

Java tutorial

Introduction

Here is the source code for okuyama.imdst.util.KeyManagerValueMap.java

Source

package okuyama.imdst.util;

import java.util.*;
import java.io.*;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.atomic.AtomicInteger;

import okuyama.base.util.ILogger;
import okuyama.base.util.LoggerFactory;
import okuyama.base.lang.BatchException;
import okuyama.imdst.util.StatusUtil;
import okuyama.imdst.util.io.*;

import org.apache.commons.codec.digest.DigestUtils;

/**
 * Key?Value??Map.<br>
 * ??????.<br>
 * :Key?Value??HashMap???.<br>
 * :Key??Map??Value???<br>
 *                Key?Value?????????.<br>
 *                ???Value??.<br>
 *
 * @author T.Okuyama
 * @license GPL(Lv3)
 */
public class KeyManagerValueMap extends CoreValueMap implements Cloneable, Serializable {

    // ????Key?Value?????true
    public boolean memoryMode = true;

    // ????Key?Value?????true
    private boolean fullDiskMode = false;

    private transient BufferedWriter bw = null;
    private transient AtomicInteger dataFileBufferUseCount = null;
    private transient AbstractDataRandomAccess raf = null;

    private transient FileBaseDataMap overSizeDataStore = null;

    private transient Object sync = new Object();

    private transient boolean vacuumExecFlg = false;
    private transient List vacuumDiffDataList = null;

    protected Map dataSizeMap = new ConcurrentHashMap(20, 16, 16);
    private ArrayBlockingQueue deletedDataPointList = null;

    private String lineFile = null;
    private String tmpVacuumeLineFile = null;
    private String[] tmpVacuumeCopyMapDirs = null;

    private int lineCount = 0;
    private int oneDataLength = ImdstDefine.dataFileWriteMaxSize;
    private int seekOneDataLength = ImdstDefine.dataFileWriteMaxSize + 1;
    private long lastDataChangeTime = 0L;
    private int nowKeySize = 0;

    private transient boolean readObjectFlg = false;

    private boolean mapValueInSize = false;

    private String diskCacheFile = null;

    // 
    public KeyManagerValueMap(int size, boolean memoryMode, String[] virtualStoreDirs, boolean renewFlg,
            File bkupObjFile, String diskCacheFile) {
        super(size, new Double(size * 0.9).intValue(), 512, memoryMode, virtualStoreDirs, renewFlg, bkupObjFile);
        this.dataSizeMap = super.dataSizeMap;
        this.diskCacheFile = diskCacheFile;

        this.memoryMode = memoryMode;
        if (!this.memoryMode)
            this.mapValueInSize = true;
    }

    // 
    public KeyManagerValueMap(String[] dirs, int numberOfDataSize, boolean renewFlg, String diskCacheFile) {
        super(dirs, numberOfDataSize, renewFlg);
        this.dataSizeMap = super.dataSizeMap;
        this.diskCacheFile = diskCacheFile;
        this.memoryMode = false;
        this.fullDiskMode = true;
    }

    /**
     * ??????<br>
     * Object??????
     */
    public void initNoMemoryModeSetting(String lineFile) {
        try {
            if (sync == null)
                sync = new Object();

            readObjectFlg = true;

            this.tmpVacuumeLineFile = lineFile + ".vacuumtmp";
            this.tmpVacuumeCopyMapDirs = new String[5];
            this.tmpVacuumeCopyMapDirs[0] = lineFile + ".cpmapdir1/";
            this.tmpVacuumeCopyMapDirs[1] = lineFile + ".cpmapdir2/";
            this.tmpVacuumeCopyMapDirs[2] = lineFile + ".cpmapdir3/";
            this.tmpVacuumeCopyMapDirs[3] = lineFile + ".cpmapdir4/";
            this.tmpVacuumeCopyMapDirs[4] = lineFile + ".cpmapdir5/";

            // ??Value??Map?
            String[] overSizeDataStoreDirs = new String[1];
            for (int dirIdx = 0; dirIdx < 1; dirIdx++) {
                overSizeDataStoreDirs[dirIdx] = lineFile + "_" + dirIdx + "/";
            }

            if (this.overSizeDataStore == null)
                this.overSizeDataStore = new FileBaseDataMap(overSizeDataStoreDirs, 100000, 0.01,
                        ImdstDefine.saveDataMaxSize, ImdstDefine.dataFileWriteMaxSize * 5,
                        ImdstDefine.dataFileWriteMaxSize * 15);

            File valueFile = new File(lineFile);
            if (!valueFile.exists() || valueFile.length() < 1) {
                super.clear();
            }
            // ??BufferedWriter
            this.bw = new BufferedWriter(
                    new OutputStreamWriter(new FileOutputStream(valueFile, true), ImdstDefine.keyWorkFileEncoding),
                    1024 * 256);
            this.dataFileBufferUseCount = new AtomicInteger(0);

            // ??????
            if (ImdstDefine.dataFileWriteDelayFlg) {
                // ??
                this.raf = new CustomRandomAccess(new File(lineFile), "rw");
            } else {
                // ???
                //this.raf = new RandomAccessFile(new File(lineFile) , "rw");
                //this.raf = new SortedSchedulingRandomAccess(new File(lineFile) , "rw");
                this.raf = new HighSpeedDiskCacheRandomAccess(new File(lineFile), "rw", this.diskCacheFile);
            }
            // ???
            this.raf.setDataPointMap(this);

            // ????
            this.deletedDataPointList = new ArrayBlockingQueue(ImdstDefine.numberOfDeletedDataPoint);

            BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream(new File(lineFile)),
                    ImdstDefine.keyWorkFileEncoding));
            this.lineFile = lineFile;
            int counter = 0;

            // ????
            // ???????????()?????
            String readDataLine = null;
            while ((readDataLine = br.readLine()) != null) {

                counter++;
                boolean zeroDataFlg = false;
                int writeLen = this.oneDataLength;
                if (readDataLine.trim().length() == 0)
                    zeroDataFlg = true;

                if (readDataLine.getBytes().length < this.oneDataLength) {
                    int shiftByteSize = 0;
                    if (readDataLine.length() < "(B)!0".length()) {
                        int shift = "(B)!0".length() - readDataLine.length();
                        shiftByteSize = shift;
                    }
                    readDataLine = "(B)!0";
                    StringBuilder updateBuf = new StringBuilder(readDataLine);
                    for (int i = 0; i < (this.oneDataLength - readDataLine.length()); i++) {
                        updateBuf.append("&");
                        shiftByteSize++;
                    }

                    if (!zeroDataFlg) {
                        updateBuf.append("\n");
                        writeLen = writeLen + 1;
                    }

                    shiftByteSize++;

                    this.raf.seek(this.convertLineToSeekPoint(counter));
                    this.raf.write(updateBuf.toString().getBytes(), 0, writeLen);
                    for (int i = 0; i < shiftByteSize; i++) {
                        br.read();
                    }
                }
            }

            this.lineCount = counter;
            br.close();

            // ???
            this.nowKeySize = super.size();
        } catch (Exception e) {
            e.printStackTrace();
            // 
            StatusUtil.setStatusAndMessage(1, "KeyManagerValueMap - init - Error [" + e.getMessage() + "]");
        }
    }

    /**
     * ???.<br>
     * ???value??????padding????????????.<br>
     *
     * @param key
     * @return Object
     * @throw
     */
    public Object getNoCnv(Object key) {
        Object ret = null;

        if (this.memoryMode) {
            ret = super.get(key);
        } else {
            try {

                int i = 0;
                long seekPoint = 0L;
                byte[] buf = new byte[this.oneDataLength];

                // seek?
                if ((seekPoint = this.calcSeekDataPoint(key)) == -1)
                    return null;

                synchronized (sync) {
                    // Vacuum???????????????
                    // ????
                    if (vacuumExecFlg) {
                        if (seekPoint != this.calcSeekDataPoint(key)) {
                            // ???
                            return get(key);
                        }
                    }

                    this.readDataFile(buf, seekPoint, this.oneDataLength, key);
                }

                ret = new String(buf, ImdstDefine.keyWorkFileEncoding);
            } catch (Exception e) {
                e.printStackTrace();
                // 
                StatusUtil.setStatusAndMessage(1, "KeyManagerValueMap - get - Error [" + e.getMessage() + "]");

            }
        }
        return ret;
    }

    /**
     * get?.<br>
     * Memory?File????.<br>
     *
     * @param key kye(?String??)
     * @return Object ?(?String??)
     */
    public Object get(Object key) {
        Object ret = null;
        if (this.memoryMode) {
            ret = super.get(key);
        } else {
            try {

                // Vacuum?sync??
                if (vacuumExecFlg) {
                    ret = syncGet(key);
                } else {

                    int i = 0;
                    int readRet = 0;
                    long seekPoint = 0L;
                    byte[] buf = new byte[this.oneDataLength];

                    // seek?
                    if ((seekPoint = this.calcSeekDataPoint(key)) == -1) {

                        return null;
                    }

                    synchronized (sync) {
                        readRet = this.readDataFile(buf, seekPoint, this.oneDataLength, key);
                        if (readRet == -1) {

                            return null;
                        }

                        boolean overSizeData = false;
                        if (buf[this.oneDataLength - 1] != 38 || readRet > this.oneDataLength) {

                            overSizeData = true;
                            if (!overSizeDataStore.containsKey(key)) {

                                // ??????????
                                overSizeData = false;
                            }
                        }

                        if (overSizeData) {
                            // ??1????
                            // ????????????
                            ret = this.readOverSizeData(key, buf);
                        } else {

                            for (; i < buf.length; i++) {
                                if (buf[i] == 38)
                                    break;
                            }
                            ret = new String(buf, 0, i, ImdstDefine.keyWorkFileEncoding);
                        }
                        buf = null;
                    }
                }
            } catch (Exception e) {
                e.printStackTrace();
                // 
                StatusUtil.setStatusAndMessage(1, "KeyManagerValueMap - get - Error [" + e.getMessage() + "]");
            }
        }

        return ret;
    }

    // Vacuum??synchronized???Get?
    private Object syncGet(Object key) {

        Object ret = null;

        try {
            int i = 0;
            byte[] buf = new byte[this.oneDataLength];
            long seekPoint = 0L;
            int readRet = 0;

            synchronized (sync) {

                // Vacuum?Map??????????????
                // Vacuum???Map????????
                // seek?
                if ((seekPoint = this.calcSeekDataPoint(key)) == -1)
                    return null;

                readRet = this.readDataFile(buf, seekPoint, this.oneDataLength, key);

                boolean overSizeData = false;
                if (buf[this.oneDataLength - 1] != 38 || readRet > this.oneDataLength) {
                    overSizeData = true;
                    if (!overSizeDataStore.containsKey(key)) {
                        // ??????????
                        overSizeData = false;
                    }
                }

                if (overSizeData) {

                    // ??1????
                    // ????????????
                    ret = this.readOverSizeData(key, buf);
                } else {

                    for (; i < buf.length; i++) {
                        if (buf[i] == 38)
                            break;
                    }
                    ret = new String(buf, 0, i, ImdstDefine.keyWorkFileEncoding);
                }

                buf = null;
            }
        } catch (Exception e) {
            e.printStackTrace();
            // 
            StatusUtil.setStatusAndMessage(1, "KeyManagerValueMap - syncGet - Error [" + e.getMessage() + "]");

        }
        return ret;
    }

    /**
     * Value????????
     *
     */
    public long dataPointGet(Object key) {
        long ret = -1;
        try {
            ret = this.calcSeekDataPoint(key, false);
        } catch (Exception e) {
            e.printStackTrace();
            // 
            StatusUtil.setStatusAndMessage(1, "KeyManagerValueMap - dataPointGet - Error [" + e.getMessage() + "]");

        }
        return ret;
    }

    /**
     * put?.<br>
     * Memory?File????.<br>
     *
     * @param key kye(?String??)
     * @param value value(?String??)
     * @return Object ?(File????null)
     */
    public Object put(Object key, Object value) {

        Object ret = null;

        this.totalDataSizeCalc(key, value);

        if (this.memoryMode) {
            ret = super.put(key, value);
        } else {

            StringBuilder writeBuf = new StringBuilder(this.oneDataLength + 2);
            int valueSize = (value.toString()).length();
            int realValueSize = valueSize;
            try {

                if (readObjectFlg == true) {

                    long seekPoint = 0L;
                    boolean overSizeFlg = false;

                    if (((String) value).length() > this.oneDataLength) {
                        writeBuf.append(((String) value).substring(0, (this.oneDataLength)));
                        overSizeFlg = true;
                        valueSize = this.oneDataLength;
                    } else {
                        writeBuf.append((String) value);
                    }

                    // ????????????
                    // ????"&"??(38)
                    byte[] appendDatas = new byte[this.oneDataLength - valueSize];

                    for (int i = 0; i < appendDatas.length; i++) {
                        appendDatas[i] = 38;
                    }

                    writeBuf.append(new String(appendDatas));
                    writeBuf.append("\n");

                    if ((this.fullDiskMode == true && ImdstDefine.reuseDataFileValuePositionFlg == false)
                            || (seekPoint = this.calcSeekDataPoint(key, false)) == -1) {

                        // ?????
                        // ??
                        synchronized (sync) {

                            // ??????????
                            Integer deletedLine = null;

                            String deletedLineStr = (String) this.deletedDataPointList.peek();

                            if (deletedLineStr != null) {
                                String[] checkUseTime = deletedLineStr.split("\\."); // ???????????
                                if (Long.parseLong(checkUseTime[0]) < System.currentTimeMillis()) {
                                    if (mapValueInSize) {
                                        deletedLine = new Integer(((String[]) checkUseTime[1].split(":"))[0]);
                                    } else {
                                        deletedLine = new Integer(checkUseTime[1]);
                                    }
                                    deletedDataPointList.poll();
                                }
                            }

                            if (vacuumExecFlg) {
                                // Vacuum?
                                Object[] diffObj = { "1", (String) key, (String) value };
                                this.vacuumDiffDataList.add(diffObj);
                            }

                            if (deletedLine == null) {

                                this.bw.write(writeBuf.toString());
                                SystemUtil.diskAccessSync(this.bw, false);

                                this.lineCount++;

                                if (mapValueInSize) {
                                    super.put(key, new Integer(this.lineCount) + ":" + realValueSize);
                                } else {
                                    super.put(key, new Integer(this.lineCount));
                                }

                                this.checkDataFileWriterLimit(this.dataFileBufferUseCount.incrementAndGet());

                            } else {

                                // ????
                                raf.seek(this.convertLineToSeekPoint(deletedLine));
                                raf.write(writeBuf.toString().getBytes(), 0, this.oneDataLength);

                                if (mapValueInSize) {
                                    super.put(key, new Integer(deletedLine) + ":" + realValueSize);
                                } else {
                                    super.put(key, new Integer(deletedLine));
                                }
                            }

                            this.nowKeySize = super.size();
                            // ???
                            if (overSizeFlg) {

                                // ??1????
                                this.writeOverSizeData(key, value);

                            }

                        }
                    } else {

                        // ?????
                        synchronized (sync) {

                            if (vacuumExecFlg) {
                                // Vacuum?
                                Object[] diffObj = { "1", key, value };
                                this.vacuumDiffDataList.add(diffObj);
                            }

                            if (raf != null) {

                                raf.seek(seekPoint);
                                raf.write(writeBuf.toString().getBytes(), 0, this.oneDataLength);
                            }
                            // ???
                            if (overSizeFlg) {
                                // ??1????
                                // ??????????
                                this.writeOverSizeData(key, value);
                            }
                        }
                    }
                } else {

                    if (mapValueInSize) {
                        super.put(key, value + ":" + realValueSize);
                    } else {
                        super.put(key, value);
                    }
                }
            } catch (Exception e) {
                e.printStackTrace();
                // 
                StatusUtil.setStatusAndMessage(1, "KeyManagerValueMap - put - Error [" + e.getMessage() + "]");
            }
        }
        return ret;
    }

    /**
     * remove?.<br>
     * Memory?File??????.<br>
     *
     * @param key kye(?String??)
     * @return Object ?
     */
    public Object remove(Object key) {
        Object ret = null;

        synchronized (sync) {
            this.totalDataSizeCalc(key, null);
            ret = super.remove(key);
            if (this.overSizeDataStore != null && this.overSizeDataStore.containsKey(key)) {
                this.overSizeDataStore.remove(key);
            }

            this.nowKeySize = super.size();

            // ??????(ValueFile????????)
            if (ret != null) {
                if (!this.memoryMode) {
                    String deleteLinePointStr = new Long((System.currentTimeMillis() + (1000 * 60 * 35))).toString()
                            + "." + ret;
                    this.deletedDataPointList.offer(deleteLinePointStr);
                }
            }

            if (vacuumExecFlg) {

                Object diffObj[] = { "2", (String) key };
                this.vacuumDiffDataList.add(diffObj);
            }
        }

        return ret;
    }

    /**
     * containsKey?.<br>
     * Memory?File??????.<br>
     *
     * @param key kye(?String??)
     * @return boolean ?
     */
    public boolean containsKey(Object key) {
        if (vacuumExecFlg) {
            synchronized (sync) {
                return super.containsKey(key);
            }
        }

        return super.containsKey(key);
    }

    private void totalDataSizeCalc(Object key, Object value) {
        if (!ImdstDefine.calcSizeFlg)
            return;

        long addSize = 0L;

        if (value != null)
            addSize = new Double((((String) key).length() + ((String) value).length()) * 0.8).longValue();

        if (addSize != 0L)
            addSize = addSize + 20;

        String unique = null;
        String keyStr = (String) key;
        int beforeSize = 0;
        AtomicLong size = null;
        int nowValLen = 0;

        if (keyStr.indexOf("#") == 0) {

            unique = keyStr.substring(0, 6);
        } else {
            unique = "all";
        }

        if (mapValueInSize) {
            String val = (String) super.get(key);

            if (val != null) {
                nowValLen = new Double(
                        (((String) key).length() + new Integer(((String[]) val.split(":"))[1]).intValue()) * 0.8)
                                .intValue()
                        + 20;
            }
        } else {

            Object val = this.get(key);

            if (val != null) {
                nowValLen = new Double((((String) key).length() + ((String) val).length()) * 0.8).intValue() + 20;
            }
        }
        if (nowValLen != 0) {
            beforeSize = nowValLen * -1;
        }

        if (!dataSizeMap.containsKey(unique)) {
            size = new AtomicLong(0L);
            dataSizeMap.put(unique, size);
        } else {
            size = (AtomicLong) dataSizeMap.get(unique);
        }

        // ?
        size.getAndAdd(beforeSize);
        size.getAndAdd(addSize);
    }

    public long getDataUseSize(String unique) {

        AtomicLong size = new AtomicLong(0L);

        if (unique == null)
            unique = "all";

        if (dataSizeMap.containsKey(unique)) {

            size = (AtomicLong) dataSizeMap.get(unique);
        }

        return size.longValue();
    }

    public String[] getAllDataUseSize() {

        if (dataSizeMap == null || dataSizeMap.size() == 0)
            return null;

        String[] sizeList = new String[dataSizeMap.size()];
        Set entrySet = dataSizeMap.entrySet();
        Iterator entryIte = entrySet.iterator();
        int idx = 0;
        while (entryIte.hasNext()) {

            Map.Entry obj = (Map.Entry) entryIte.next();
            if (obj == null)
                continue;

            String key = (String) obj.getKey();
            AtomicLong size = (AtomicLong) obj.getValue();

            sizeList[idx] = key + "=" + size.toString();
            idx++;
        }

        return sizeList;
    }

    /**
     * ??????????.<br>
     * ?MapMap????????super?Map???Key???<br>
     * ?????value??????Data????????<br>
     * Map?Key?????put?.<br>
     * ??Key??????????????????<br>
     * ???????super?Map??Map?super?Map?put?.<br>
     * ??super?Map??????????????????
     * ??????????????????
     * ????Vacuum.<br>
     */
    public boolean vacuumData() {
        boolean ret = false;

        BufferedWriter tmpBw = null;
        RandomAccessFile raf = null;
        Map vacuumWorkMap = null;
        boolean userMap = false;
        String dataStr = null;
        Set entrySet = null;
        Iterator entryIte = null;
        String key = null;
        int putCounter = 0;

        synchronized (sync) {

            if (this.vacuumDiffDataList != null) {
                this.vacuumDiffDataList.clear();
                this.vacuumDiffDataList = null;
            }

            this.vacuumDiffDataList = new FileBaseDataList(this.tmpVacuumeLineFile);
            vacuumExecFlg = true;
        }

        //vacuumWorkMap = new ConcurrentHashMap(super.size());
        if (JavaSystemApi.getUseMemoryPercent() > 40) {
            userMap = true;
            vacuumWorkMap = new FileBaseDataMap(this.tmpVacuumeCopyMapDirs, super.size(), 0.20);
        } else {
            vacuumWorkMap = new HashMap(super.size());
        }

        try {

            tmpBw = new BufferedWriter(
                    new OutputStreamWriter(new FileOutputStream(new File(this.lineFile + ".tmp"), true),
                            ImdstDefine.keyWorkFileEncoding),
                    1024 * 256);
            raf = new RandomAccessFile(new File(this.lineFile), "r");

            entrySet = super.entrySet();
            entryIte = entrySet.iterator();

            while (entryIte.hasNext()) {

                Map.Entry obj = (Map.Entry) entryIte.next();
                key = (String) obj.getKey();
                if (key != null && (dataStr = (String) getNoCnv(key)) != null) {
                    tmpBw.write(dataStr);
                    tmpBw.write("\n");
                    putCounter++;

                    if (mapValueInSize) {
                        vacuumWorkMap.put(key, new Integer(putCounter).toString() + ":" + dataStr.length());
                    } else {
                        vacuumWorkMap.put(key, new Integer(putCounter).toString());
                    }
                }
            }

        } catch (Exception e) {
            e.printStackTrace();
            // 
            StatusUtil.setStatusAndMessage(1, "KeyManagerValueMap - vacuumData - Error [" + e.getMessage() + "]");
        } finally {
            try {
                // ?????
                if (StatusUtil.getStatus() == 0) {

                    // flush
                    SystemUtil.diskAccessSync(tmpBw);
                    // close
                    tmpBw.close();

                    // ?????
                    synchronized (sync) {

                        raf.close();

                        if (this.raf != null)
                            this.raf.close();
                        if (this.bw != null)
                            this.bw.close();

                        File dataFile = new File(this.lineFile);
                        if (dataFile.exists()) {
                            dataFile.delete();
                        }
                        dataFile = null;
                        // KeyMapKeyMap???
                        File tmpFile = new File(this.lineFile + ".tmp");
                        tmpFile.renameTo(new File(this.lineFile));

                        // super?Map?
                        super.clear();

                        // workMap?
                        Integer workMapData = null;
                        Set workEntrySet = vacuumWorkMap.entrySet();
                        Iterator workEntryIte = workEntrySet.iterator();
                        String workKey = null;

                        while (workEntryIte.hasNext()) {

                            Map.Entry obj = (Map.Entry) workEntryIte.next();
                            workKey = (String) obj.getKey();
                            if (workKey != null) {

                                if (mapValueInSize) {
                                    super.put(key, (String) vacuumWorkMap.get(workKey));
                                } else {
                                    super.put(workKey, new Integer((String) vacuumWorkMap.get(workKey)));
                                }
                            }
                        }

                        // ?
                        this.nowKeySize = super.size();
                        // ??
                        this.initNoMemoryModeSetting(this.lineFile);

                        // Vacuum????synchronized?????
                        int vacuumDiffDataSize = this.vacuumDiffDataList.size();

                        if (vacuumDiffDataSize > 0) {

                            Object[] diffObj = null;
                            for (int i = 0; i < vacuumDiffDataSize; i++) {

                                // ??
                                diffObj = (Object[]) this.vacuumDiffDataList.get(i);
                                if (diffObj[0].equals("1")) {
                                    // put
                                    put(diffObj[1], diffObj[2]);
                                } else if (diffObj[0].equals("2")) {
                                    // remove
                                    remove(diffObj[1]);
                                }
                            }
                        }

                        this.vacuumDiffDataList.clear();
                        this.vacuumDiffDataList = null;

                        if (userMap) {
                            ((FileBaseDataMap) vacuumWorkMap).finishClear();
                        }
                        vacuumWorkMap = null;

                        // Vacuum
                        vacuumExecFlg = false;
                        ret = true;
                    }
                }
            } catch (Exception e2) {
                e2.printStackTrace();
                try {
                    File tmpFile = new File(this.lineFile + ".tmp");
                    if (tmpFile.exists()) {
                        tmpFile.delete();
                    }
                } catch (Exception e3) {
                    e3.printStackTrace();
                    // 
                    StatusUtil.setStatusAndMessage(1,
                            "KeyManagerValueMap - vacuumData - Error [" + e3.getMessage() + e3.getMessage() + "]");
                }
            }
        }

        return ret;
    }

    private void checkDataFileWriterLimit(int nowCount) {
        if (nowCount > ImdstDefine.maxDataFileBufferUseCount) {
            synchronized (sync) {
                try {

                    this.bw.flush();
                    this.bw.close();
                    this.bw = null;
                } catch (Exception e) {
                    this.bw = null;
                } finally {
                    try {
                        this.bw = new BufferedWriter(
                                new OutputStreamWriter(new FileOutputStream(new File(this.lineFile), true),
                                        ImdstDefine.keyWorkFileEncoding),
                                1024 * 256);
                        this.dataFileBufferUseCount = new AtomicInteger(0);

                    } catch (Exception e) {
                        this.bw = null;
                    }
                }
            }
        }
    }

    public void close() {
        try {
            synchronized (sync) {
                if (this.deletedDataPointList != null)
                    this.deletedDataPointList.clear();

                if (this.raf != null)
                    this.raf.close();
                if (this.bw != null)
                    this.bw.close();

            }
        } catch (Exception e3) {
        }
    }

    public void fileStoreMapObject(File file) throws Exception {
        super.fileStoreMapObject(file, this.dataSizeMap);
    }

    /**
     * Disk?????.<br>
     *
     * @throw Exception
     */
    public void deleteMapDataFile() throws Exception {
        try {
            synchronized (sync) {
                if (this.deletedDataPointList != null)
                    this.deletedDataPointList.clear();

                if (this.raf != null) {
                    this.raf.close();
                    this.raf = null;
                }

                if (this.bw != null) {
                    this.bw.close();
                    this.bw = null;
                }

                File dataFile = new File(this.lineFile);
                if (dataFile.exists()) {
                    dataFile.delete();
                }

            }
        } catch (Exception e3) {
            e3.printStackTrace();
            throw e3;
        }
    }

    /**
     * ????????Value?.<br>
     * ????.<br>
     * 1Value????????????????+1?.<br>
     * 1???????????
     * ???????-1?.<br>
     *
     * @param buf ??Buffer
     * @param seekPoint seek
     * @param readLength ??
     * @return ??
     */
    private int readDataFile(byte[] buf, long seekPoint, int readLength, Object key) throws Exception {
        int ret = readLength;

        if (raf != null) {

            if (!ImdstDefine.dataFileWriteDelayFlg) {
                ((AbstractDataRandomAccess) this.raf).seekAndRead(seekPoint, buf, 0, this.oneDataLength, key);
            } else {
                raf.seek(seekPoint);
                SystemUtil.diskAccessSync(raf, buf, 0, this.oneDataLength);
            }
        } else {
            return -1;
        }

        if (buf[buf.length - 1] != 38 && buf[buf.length - 2] != 33 && buf[buf.length - 1] != 48)
            ret++;

        return ret;
    }

    /**
     * ???????????.<br>
     */
    private void writeOverSizeData(Object key, Object value) {
        //File overDataFile = new File(this.lineFile + "_/" + (key.toString().hashCode() % 20) + "/" +  DigestUtils.md5Hex(key.toString().getBytes()));
        //BufferedWriter overBw = null;
        try {
            this.overSizeDataStore.put((String) key,
                    ((String) value).substring(this.oneDataLength, ((String) value).length()));
            //overBw = new BufferedWriter (new OutputStreamWriter(new FileOutputStream(overDataFile, false), ImdstDefine.keyWorkFileEncoding));
            //overBw.write(((String)value).substring(this.oneDataLength, ((String)value).length()));
            //SystemUtil.diskAccessSync(overBw);
        } catch (Exception inE) {
            inE.printStackTrace();
            // 
            StatusUtil.setStatusAndMessage(1,
                    "KeyManagerValueMap - Inner File Write - Error [" + inE.getMessage() + "]");
        } finally {
            /*try {
            if (overBw != null) overBw.close();
            } catch (Exception inE2) {
            }*/
        }
    }

    /**
     * ??????????.<br>
     */
    private String readOverSizeData(Object key, byte[] buf) {
        String ret = null;
        try {

            String readStr = (String) this.overSizeDataStore.get((String) key);

            StringBuilder retTmpBuf = new StringBuilder(this.oneDataLength);
            retTmpBuf.append(new String(buf, 0, this.oneDataLength, ImdstDefine.keyWorkFileEncoding));
            retTmpBuf.append(readStr);

            ret = retTmpBuf.toString();
        } catch (Exception inE) {
            inE.printStackTrace();
            // 
            StatusUtil.setStatusAndMessage(1,
                    "KeyManagerValueMap - Inner File Read[get] - Error [" + inE.getMessage() + "]");
        }
        return ret;
    }

    /**
     * Key???????Key???Value???????.<br>
     * ?????.<br>
     *
     * @param key Key
     * @return long ?? ??????-1???
     */
    private long calcSeekDataPoint(Object key) {
        return this.calcSeekDataPoint(key, true);
    }

    /**
     * Key???????Key???Value???????.<br>
     * ?????.<br>
     *
     * @param key Key
     * @return long ?? ??????-1???
     */
    private long calcSeekDataPoint(Object key, boolean requestSeekPoint) {

        Integer lineInteger = null;
        if (mapValueInSize) {
            Object lineIntegerObj = (Object) super.get(key);
            if (lineIntegerObj != null) {
                String lineIntegerMix = (String) super.get(key);
                if (lineIntegerMix != null) {
                    lineInteger = new Integer(((String[]) lineIntegerMix.split(":"))[0]);
                }
            }
        } else {
            lineInteger = (Integer) super.get(key);
        }
        long ret = this.convertLineToSeekPoint(lineInteger);
        if (ret != -1 && requestSeekPoint == true) {
            if (!ImdstDefine.dataFileWriteDelayFlg)
                ((AbstractDataRandomAccess) this.raf).requestSeekPoint(ret, 0, this.oneDataLength);
        }
        return ret;
    }

    /**
     * ?????seek?????.<br>
     *
     * @param lineInteger 
     * @return long seek
     */
    private long convertLineToSeekPoint(Integer lineInteger) {

        int line = 0;
        if (lineInteger != null) {
            line = lineInteger.intValue();
        } else {
            return -1;
        }

        // seek
        return new Long(this.seekOneDataLength).longValue() * new Long((line - 1)).longValue();
    }

    /**
     * getKeySize.<br>
     *
     * @param
     * @return int
     * @throws
     */
    public int getKeySize() {
        return this.nowKeySize;
    }

    /**
     * getAllDataCount.<br>
     *
     * @param
     * @return int
     * @throws
     */
    public int getAllDataCount() {
        return this.lineCount;
    }

    /**
     * ???.<br>
     * @param time 
     */
    public void setKLastDataChangeTime(long time) {
        this.lastDataChangeTime = time;
    }

    /**
     * ????.<br>
     * @return long 
     */
    public long getKLastDataChangeTime() {
        return this.lastDataChangeTime;
    }
}