⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 filestoragefactory.java

📁 Java的面向对象数据库系统的源代码
💻 JAVA
字号:
// You can redistribute this software and/or modify it under the terms of// the Ozone Core License version 1 published by ozone-db.org.//// Copyright (C) 2003-@year@, Leo Mekenkamp. All rights reserved.//// $Id: FileStorageFactory.java,v 1.3 2004/03/21 21:05:51 leomekenkamp Exp $package org.ozoneDB.core.storage.gammaStore;import java.io.File;import java.io.IOException;import java.util.Collection;import java.util.LinkedList;import java.util.List;import java.util.Properties;import java.util.Random;import java.util.logging.Level;import java.util.logging.Logger;import org.ozoneDB.core.ConfigurationException;import org.ozoneDB.core.storage.PropertyConfigurable;import org.ozoneDB.core.storage.PropertyInfo;/** * Abstract base class for storage factories that use files.  * * @author <a href="mailto:leoATmekenkampD0Tcom">Leo Mekenkamp (mind the anti sp@m)</a> * @version $Id: FileStorageFactory.java,v 1.3 2004/03/21 21:05:51 leomekenkamp Exp $ */public abstract class FileStorageFactory implements StorageFactory, PropertyConfigurable {        private static Logger log = Logger.getLogger(FileStorageFactory.class.getName());        public static final PropertyInfo DIRECTORY = new PropertyInfo(        ".directory",        "string (path)",        null,        "directory, either relative to the database directory or an absolute path",        new String[] {            "/var/ozone/index (*nix absolute path)",            "c:\\ozoneFiles\\index (windows absolute path)",            "index (*nix or windows relative path in database dir)",            "./index (*nix relative path in database dir)",            ".\\index (windows relative path in database dir)",        }    );    private static final String SUBDIRECTORYDEPTH_KEY = ".subdirectoryDepth";    private static final String SUBDIRECTORYCOUNT_KEY = ".subdirectoryCount";    public static final PropertyInfo SUBDIRECTORYDEPTH = new PropertyInfo(        SUBDIRECTORYDEPTH_KEY,        "integer (>=0)",        "1",        "depth of subdirectories to use, to prevent too much files in the " +        "directory specified by '.directory' (see: " + SUBDIRECTORYCOUNT_KEY + ")",        new String[] {            "/var/ozone/index (*nix absolute path)",            "c:\\ozoneFiles\\index (windows absolute path)",            "index (*nix or windows relative path in database dir)",            "./index (*nix relative path in database dir)",            ".\\index (windows relative path in database dir)",        }    );    public static final PropertyInfo SUBDIRECTORYCOUNT = new PropertyInfo(        SUBDIRECTORYCOUNT_KEY,        "integer (>=2)",        "50",        "number of subdirectories to use when " + SUBDIRECTORYDEPTH_KEY +        " is greater than 0",        new String[] {            "/var/ozone/index (*nix absolute path)",            "c:\\ozoneFiles\\index (windows absolute path)",            "index (*nix or windows relative path in database dir)",            "./index (*nix relative path in database dir)",            ".\\index (windows relative path in database dir)",        }    );    /**     * <p>Used to name directories. We could take any value from 2 to      * <code>Character.MAX_RADIX</code> (36) here, but we settle for 16 because     * it looks nice and nerdy. 36 would look less nice because that could     * lead to directories with very nasty words in them when SUBDIRECTORYCOUNT     * is large enough.     */    private static final int NAMECONVERTRADIX = 16;    private File directory;        private String prefix;        private int subdirectoryDepth;    private int subdirectoryCount;        /**     * As prescribed by the <code>PropertyConfigurable</code> interface.     */    protected FileStorageFactory(Properties properties, String prefix) {        setPrefix(prefix);        String property = getPrefix() + DIRECTORY.getKey();        String dirName = properties.getProperty(property);        if (dirName == null) {            String msg = "could not find property: '" + property + "'";            if (log.isLoggable(Level.SEVERE)) log.severe(msg + "\ncould find: " + properties.entrySet());                        throw new ConfigurationException(msg);        }        File directory = new File(dirName);        if (!directory.isAbsolute()) {            File databaseRoot = new File(properties.getProperty(GammaStore.DIRECTORY.getKey()));            directory = new File(databaseRoot, dirName);        }        if (!directory.isDirectory() && !directory.mkdir()) {            String msg = "could not find nor create directory: '" + dirName + "'";            if (log.isLoggable(Level.SEVERE)) log.severe(msg);            throw new ConfigurationException(msg);        } else {                        if (log.isLoggable(Level.CONFIG)) log.config(getPrefix() + " using directory " + directory);        }        setDirectory(directory);                // find out the current directory depth by counting the number of dirs        // we have to go to find the first file        subdirectoryDepth = findDepth(getDirectory(), 0);        log.config("current directoryDepth: " + subdirectoryDepth);        int newDepth = Integer.parseInt(properties.getProperty(getPrefix() + SUBDIRECTORYDEPTH.getKey(), SUBDIRECTORYDEPTH.getDefaultValue()));        log.config("new directoryDepth: " + newDepth);        try {            setSubdirectoryDepth(newDepth);        } catch (IOException e) {            ConfigurationException ee = new ConfigurationException("could not change directory depth to " + newDepth, e);            log.severe(ee.getMessage());            throw ee;        }        int newCount = Integer.parseInt(properties.getProperty(getPrefix() + SUBDIRECTORYCOUNT.getKey(), SUBDIRECTORYCOUNT.getDefaultValue()));        setSubdirectoryCount(newCount);    }        private int findDepth(File directory, int startDepth) {        File[] files = directory.listFiles();        for (int i = 0; i < files.length; i++) {            if (files[i].isDirectory()) {                int result = findDepth(files[i], startDepth + 1);                if (result > startDepth) {                    return result;                }            }        }        for (int i = 0; i < files.length; i++) {            if (files[i].isFile()) {                return startDepth;            }        }        return 0;    }        public void delete(String name) throws IOException {        File file = nameToFile(name);        if (file.exists() && !file.delete()) {            String msg = "could not delete file '" + file + "'";            if (log.isLoggable(Level.SEVERE)) log.severe(msg);            throw new IOException(msg);        }    }        public void deleteAll() throws IOException {        deleteDirectory(getDirectory());    }        /**     * deletes all files and subdirectories in the specified directory, but     * does _not_ delete the specified directory     */    private void deleteDirectory(File directory) throws IOException {        File[] files = directory.listFiles();        for (int i = 0; i < files.length; i++) {            if (files[i].isDirectory()) {                deleteDirectory(files[i]);            }            if (!files[i].delete()) {                String msg = "could not delete '" + files[i] + "'";                if (log.isLoggable(Level.SEVERE)) log.severe(msg);                throw new IOException(msg);            }        }    }     /**     * <p>Sets the depth of subdirectories to use. You must make sure that no     * reading or writing is taking place in the directory specified by     * <code>getDirectory()</code>, either by this class, or outside this class     * (for instance with 'cat' or 'type' in a shell / cmd window)</p>.     * <p>The whole directory structure is changed when this method is called,     * so it may take some time to complete.</p>     */    private void setSubdirectoryDepth(int depth) throws IOException {        if (depth != subdirectoryDepth) {            // needs to be debugged or removed altogether//            moveFiles(getDirectory(), depth, depth);            subdirectoryDepth = depth;        }    }        // DOES NOT WORK!    private void moveFiles(File directory, int relDepth, int targetDepth, int targetCount) throws IOException {        File[] files = directory.listFiles();        if (relDepth == 0) {            for (int i = 0; i < files.length; i++) {                File dest = nameToFile(files[i].getName(), targetDepth, targetCount);                ensureParentsExist(dest);                files[i].renameTo(dest);            }            recursiveDeleteIfEmpty(directory);        } else {            for (int i = 0; i < files.length; i++) {                if (files[i].isDirectory()) {                    moveFiles(files[i], relDepth - 1, targetDepth, targetCount);                }            }        }    }        private void recursiveDeleteIfEmpty(File directory) throws IOException {        if (directory.isDirectory() && directory.list().length == 0) {            if (!directory.delete()) {                throw new IOException("could not delete directory " + directory);            }            recursiveDeleteIfEmpty(directory.getParentFile());        }    }        private int getSubdirectoryDepth() {        return subdirectoryDepth;    }        public String getPrefix() {        return prefix;    }            /**     * Returns the <code>File</code> that corresponds to the given name and     * depth.     */    protected File nameToFile(String name, int depth, int count) {        StringBuffer subPath = new StringBuffer();                long code = 1;        // together with the randomizer, this gives a nice even spread of files        // in subdirectories        for (int i = 0; i < name.length(); i++) {            code = 1 + (code * name.charAt(i)) + (name.charAt(i) * i);        }        Random random = new Random();        for (int i = 0; i < depth; i++) {            // all algorithms are fixed across all implementations of the java            // specs, so 'random' will generate the same number in every jvm            random.setSeed(code * (i + 1));            int dirName = Math.abs(random.nextInt() % count);            subPath.append(Integer.toString(dirName, NAMECONVERTRADIX));            subPath.append(File.separatorChar);        }        subPath.append(name);        File result = new File(getDirectory(), subPath.toString());        return result;    }        protected File nameToFile(String name) {        return nameToFile(name, getSubdirectoryDepth(), getSubdirectoryCount());    }        protected void ensureParentsExist(File file) throws IOException {        File parent = file.getParentFile();        if (!parent.exists() && !parent.mkdirs()) {            throw new IOException("could not create directory " + parent);        }    }            // private so it can be inlined    private void setPrefix(String prefix) {        this.prefix = prefix;    }        protected File getDirectory() {        return directory;    }        // private so it can be inlined    private void setDirectory(File directory) {        this.directory = directory;    }        /**     * Implementing classes should override this method, call super and add     * their own specific properties.     */    public Collection getPropertyInfos() {        Collection result = new LinkedList();        result.add(DIRECTORY);        result.add(SUBDIRECTORYDEPTH);        result.add(SUBDIRECTORYCOUNT);        return result;    }        private int getSubdirectoryCount() {        return subdirectoryCount;    }        private void setSubdirectoryCount(int subdirectoryCount) {        this.subdirectoryCount = subdirectoryCount;    }    }

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -