Package org.chaidb.db.index.btree.bufmgr

Source Code of org.chaidb.db.index.btree.bufmgr.StorageMeta

/*
* Copyright (C) 2006  http://www.chaidb.org
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
* GNU General Public License for more details.
*
*/

package org.chaidb.db.index.btree.bufmgr;

import org.apache.log4j.Logger;
import org.apache.xerces.parsers.DOMParser;
import org.chaidb.db.DbEnvironment;
import org.chaidb.db.exception.ChaiDBException;
import org.chaidb.db.exception.ErrorCode;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.InputSource;

import java.io.*;
import java.util.*;

/**
* @author Stanley
*/
public class StorageMeta {

    private String storageMetaFile;
    private HashMap colStorageMap = new HashMap();
    private String defaultPrimaryDir = DbEnvironment.getDataHome();

    private static Logger logger = Logger.getLogger(StorageMeta.class);

    private static final String FILE_NAME = "collection_storage.xml";
    private static final String XML_HEADER = "<?xml version=\"1.0\" ?>";
    private static final String NEW_LINE = "\n";
    private static final String COLLECTIONS = "Collections";
    private static final String COLLECTION = "Collection";
    private static final String COLLECTION_ID = "id";
    private static final String PRIMARY_DIRECTORY = "primaryDir";
    private static final String EXTENDED_DIRECTORY = "ExtendedDirectory";
    private static final String EXTENDED_PATH = "path";
    private static final String CURRENT_DIRECTORY = "currentDir";

    public StorageMeta() {
        storageMetaFile = DbEnvironment.DB_HOME + File.separator + "conf" + File.separator + FILE_NAME;
        readFromDisk();
    }

    /**
     * For unit test
     *
     * @param confFile the configure file path
     */
    public StorageMeta(String confFile, String defaultDir) {
        storageMetaFile = confFile;
        defaultPrimaryDir = defaultDir;
        readFromDisk();
    }

    /**
     * To load a collection Storage metadata from disk  into collectionStorageMap
     */
    private synchronized void readFromDisk() {

        String collectionID;
        String primaryDir;
        LinkedList extendedDirs;
        String extendedPath;
        String currentDir;
        CollectionStorage colStorage;
        NodeList childNodes;

        Document doc = getDocument();
        if (doc == null) {
            return;
        }

        NodeList nodeList = doc.getElementsByTagName(COLLECTION);
        if (nodeList.getLength() == 0) {
            return;
        }
        for (int i = 0; i < nodeList.getLength(); i++) {

            collectionID = null;
            primaryDir = null;
            extendedDirs = new LinkedList();
            currentDir = null;

            Node node = nodeList.item(i);
            collectionID = node.getAttributes().getNamedItem(COLLECTION_ID).getNodeValue();
            primaryDir = node.getAttributes().getNamedItem(PRIMARY_DIRECTORY).getNodeValue();
            currentDir = node.getAttributes().getNamedItem(CURRENT_DIRECTORY).getNodeValue();
            childNodes = node.getChildNodes();

            for (int j = 0; j < childNodes.getLength(); j++) {

                Node childNode = childNodes.item(j);
                if (childNode.getNodeType() == Node.ELEMENT_NODE) {
                    extendedPath = childNode.getAttributes().getNamedItem(EXTENDED_PATH).getNodeValue();
                    extendedDirs.addLast(extendedPath);
                }
            }
            colStorage = new CollectionStorage(primaryDir, extendedDirs, currentDir);
            colStorageMap.put(new Integer(collectionID), colStorage);
        }
    }

    /**
     * This method can write data to a tmp file, when your all operations
     * successly you should call commit to commit the changes, or call rollback
     * to discard changes if any operation failed.
     */
    private void writeToDisk() throws ChaiDBException {
        StringBuffer buff = new StringBuffer(XML_HEADER + NEW_LINE);
        Iterator entries = colStorageMap.entrySet().iterator();
        Map.Entry entry;
        CollectionStorage colStorage;
        String collectionID;

        buff.append("<").append(COLLECTIONS).append(">").append(NEW_LINE);
        {
            while (entries.hasNext()) {
                entry = (Map.Entry) entries.next();
                collectionID = ((Integer) entry.getKey()).toString();
                colStorage = (CollectionStorage) entry.getValue();
                buff.append("<").append(COLLECTION).append(" ");
                buff.append(COLLECTION_ID).append("=").append("\"").append(collectionID).append("\"").append(" ");
                buff.append(PRIMARY_DIRECTORY).append("=").append("\"").append(colStorage.getPrimaryDirectory()).append("\"").append(" ");
                buff.append(CURRENT_DIRECTORY).append("=").append("\"").append(colStorage.getCurrentDirectory()).append("\"").append(" ");
                buff.append(">").append(NEW_LINE);
                Iterator dires = colStorage.extendedDirs.iterator();
                while (dires.hasNext()) {
                    buff.append("<").append(EXTENDED_DIRECTORY).append(" ");
                    buff.append(EXTENDED_PATH).append("=").append("\"").append((String) dires.next()).append("\"").append(" ");
                    buff.append("/>").append(NEW_LINE);
                }
                buff.append("</").append(COLLECTION).append(">").append(NEW_LINE);
            }
        }
        buff.append("</").append(COLLECTIONS).append(">");

        FileOutputStream fo = null;
        try {
            fo = new FileOutputStream(storageMetaFile);
            fo.write(buff.toString().getBytes("UTF-8"));
            fo.flush();
        } catch (UnsupportedEncodingException e) {
            logger.error(e);
        } catch (IOException ioe) {
            String details = "The operation saving collection storage metadata into " + storageMetaFile + " failed" + ". " + ioe.toString() + ".";
            throw new ChaiDBException(ErrorCode.RUNTIME_IO_ERROR, details);
        } finally {
            if (fo != null) {
                try {
                    fo.close();
                } catch (Exception fe) {

                }
            }
        }

    }


    private boolean fileExists() {
        File f = new File(storageMetaFile);
        if (!f.exists() || f.length() == 0) {
            return false;
        }
        return true;
    }

    /**
     * Get DOM Document from storageMetaFile
     *
     * @return Document if the file exists and is well-format. null if not.
     */
    private Document getDocument() {
        if (!fileExists()) {
            return null;
        }

        Document doc = null;
        try {
            InputSource input = new InputSource(new FileInputStream(storageMetaFile));
            DOMParser parser = new DOMParser();
            parser.parse(input);
            doc = parser.getDocument();
        } catch (Exception e) {
            String details = "The operation reading collection storage metadata from " + storageMetaFile + " failed" + ". " + e.toString() + ".";
            logger.info(details);
            //throw new ChaiDBException(ErrorCode.FILE_NOT_FOUND_ERROR, details);
        }
        return doc;
    }

    /**
     * @param fileName the input file name
     * @return String the primary directory
     */
    public synchronized String getPrimaryDirectory(String fileName) {

        CollectionStorage collectionStorage = null;
        String relativePath = getRelativePath(fileName);

        collectionStorage = (CollectionStorage) colStorageMap.get(getCollectionID(fileName));

        if (collectionStorage == null) {
            return defaultPrimaryDir + relativePath;
        }
        return collectionStorage.getPrimaryDirectory() + relativePath;

    }

    /**
     * @param fileName
     * @return
     */
    public synchronized String getCurrentFileName(String fileName) {

        CollectionStorage collectionStorage = null;
        //String relativePath = getRelativePath(fileName);
        String relativePath = new File(fileName).getName();

        collectionStorage = (CollectionStorage) colStorageMap.get(getCollectionID(fileName));

        if (collectionStorage == null) {
            return defaultPrimaryDir + relativePath;
        }
        return collectionStorage.getCurrentDirectory() + relativePath;
    }

    /**
     * @param fileName
     * @return
     */
    public synchronized Iterator getAllFileNames(String fileName) {
        LinkedList fileList = new LinkedList();

        CollectionStorage collectionStorage = null;
        String relativePath = getRelativePath(fileName);

        collectionStorage = (CollectionStorage) colStorageMap.get(getCollectionID(fileName));

        if (collectionStorage == null) {
            fileList.add(defaultPrimaryDir + relativePath);
        } else {
            fileList.add(collectionStorage.getPrimaryDirectory() + relativePath);
            Iterator extendedFiles = collectionStorage.getExtendedDirectory().iterator();
            while (extendedFiles.hasNext()) {
                fileList.add(((String) extendedFiles.next()) + relativePath);
            }
        }
        return fileList.iterator();
    }

    /**
     * @param CollectionID
     * @param extendedDir
     * @throws ChaiDBException
     */

    public synchronized void addExtendedDirectory(int CollectionID, String extendedDir) throws ChaiDBException {
        CollectionStorage collectionStorage = null;

        collectionStorage = (CollectionStorage) colStorageMap.get(new Integer(CollectionID));
        if (collectionStorage == null) {
            collectionStorage = new CollectionStorage(defaultPrimaryDir);
            collectionStorage.addExtendedDir(extendedDir);
            colStorageMap.put(new Integer(CollectionID), collectionStorage);

        } else {
            collectionStorage.addExtendedDir(extendedDir);
        }
        writeToDisk();
    }

    /**
     * @param CollectionID
     * @param primaryDir
     * @param extendedDir
     * @throws ChaiDBException
     */
    public synchronized void addExtendedDirectory(int CollectionID, String primaryDir, String extendedDir) throws ChaiDBException {
        CollectionStorage collectionStorage = null;

        collectionStorage = (CollectionStorage) colStorageMap.get(new Integer(CollectionID));
        if (collectionStorage == null) {
            collectionStorage = new CollectionStorage(primaryDir);
            collectionStorage.addExtendedDir(extendedDir);
            colStorageMap.put(new Integer(CollectionID), collectionStorage);

        } else {
            collectionStorage.addExtendedDir(extendedDir);
        }
        writeToDisk();
    }

    /**
     * @param collectionID
     * @return
     */
    public synchronized String listCollectionDir(int collectionID) {
        CollectionStorage colStorage = null;
        StringBuffer buff = new StringBuffer();
        colStorage = (CollectionStorage) colStorageMap.get(new Integer(collectionID));
        if (colStorage == null) {
            colStorage = new CollectionStorage(defaultPrimaryDir);
        }
        buff.append(PRIMARY_DIRECTORY).append("=").append("\"").append(colStorage.getPrimaryDirectory()).append("\"").append(" ");
        buff.append(CURRENT_DIRECTORY).append("=").append("\"").append(colStorage.getCurrentDirectory()).append("\"").append(" ");
        buff.append(NEW_LINE);
        Iterator dires = colStorage.getExtendedDirectory().iterator();
        while (dires.hasNext()) {
            buff.append(EXTENDED_DIRECTORY).append(" ");
            buff.append(EXTENDED_PATH).append("=").append("\"").append((String) dires.next()).append("\"").append(" ");
            buff.append(NEW_LINE);
        }
        return buff.toString();
    }

    public synchronized Iterator listColDirs(int colId) throws ChaiDBException {
        CollectionStorage colStorage = null;
        String colPath = Integer.toString(colId);
        LinkedList colDirs = new LinkedList();

        colStorage = (CollectionStorage) colStorageMap.get(new Integer(colId));
        if (colStorage == null) {
            colStorage = new CollectionStorage(defaultPrimaryDir);
        }
        colDirs.add(defaultPrimaryDir);
        Iterator dirs = colStorage.getExtendedDirectory().iterator();
        while (dirs.hasNext()) {
            colDirs.add((String) dirs.next() + File.separator + colPath);
        }
        return colDirs.iterator();
    }

    public synchronized Iterator removeExtendedColDirs(int colId) throws ChaiDBException {
        CollectionStorage colStorage = null;
        String colPath = Integer.toString(colId);
        LinkedList extendedColDirs = new LinkedList();

        colStorage = (CollectionStorage) colStorageMap.remove(new Integer(colId));
        if (colStorage == null) {
            colStorage = new CollectionStorage(defaultPrimaryDir);
        }
        Iterator dirs = colStorage.getExtendedDirectory().iterator();
        while (dirs.hasNext()) {
            extendedColDirs.add((String) dirs.next() + File.separator + colPath);
        }
        writeToDisk();
        return extendedColDirs.iterator();
    }

    /**
     * @param fileName
     * @return
     */
    public synchronized Integer getCollectionID(String fileName) {
        String colPath = null;
        String colName = null;
        int lastPosition = -1;

        if (fileName.indexOf(defaultPrimaryDir) == -1) return null;

        colPath = fileName.substring(defaultPrimaryDir.length());

        lastPosition = colPath.indexOf(File.separator);

        if (lastPosition == -1) {
            return null;
        } else {
            colName = colPath.substring(0, lastPosition);
            try {
                return new Integer(colName);
            } catch (Exception e) {
                return null;
            }
        }
    }

    /**
     * get btree file name on relative path
     *
     * @param fileName a virtual btree file name
     * @return relative path file name
     */
    private String getRelativePath(String fileName) {
        String colPath = null;
        int lastPosition = -1;
        int lastSecPosition = -1;

        lastPosition = fileName.lastIndexOf(File.separator);
        colPath = fileName.substring(0, lastPosition);

        lastSecPosition = colPath.lastIndexOf(File.separator);
        return fileName.substring(lastSecPosition + 1);
    }

    /**
     * for Dropping DB
     */
    public Set removeAllExtendedDirs() throws ChaiDBException {
        Set allDirs = new HashSet();
        Iterator allColStorage = colStorageMap.values().iterator();
        CollectionStorage colStorage = null;
        while (allColStorage.hasNext()) {
            colStorage = (CollectionStorage) allColStorage.next();
            allDirs.addAll(colStorage.getExtendedDirectory());
        }
        colStorageMap.clear();
        writeToDisk();
        return allDirs;
    }

    public CollectionStorage getColStorage(int collectionId) {
        CollectionStorage colStorage = (CollectionStorage) colStorageMap.get(new Integer(collectionId));
        if (colStorage == null) {
            colStorage = new CollectionStorage(defaultPrimaryDir);
        }
        return colStorage;
    }
}
TOP

Related Classes of org.chaidb.db.index.btree.bufmgr.StorageMeta

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.