org.dbmfs.DatabaseFilesystem.java Source code

Java tutorial

Introduction

Here is the source code for org.dbmfs.DatabaseFilesystem.java

Source

package org.dbmfs;

import java.io.*;
import java.nio.*;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;

import fuse.*;

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

import org.dbmfs.query.*;
import org.dbmfs.params.*;

/**
 * DBMFS.<br>
 * FUSE-J?<br>
 *
 * @author okuyamaoo
 * @license Apache Lisence
 */
public class DatabaseFilesystem implements Filesystem3, XattrSupport {

    private static final Log log = LogFactory.getLog(DatabaseFilesystem.class);

    public volatile static int blockSize = 1024 * 64;
    public volatile static boolean useRealSize = true;

    private volatile static boolean readOnlyMount = false;

    private FuseStatfs statfs;

    private volatile static int maxShowFiles = 100; // 1??

    public static String driverName = null;
    public static String databaseUrl = null;
    public static String databaseAddress = null;
    public static int databasePort = -1;
    public static String databaseName = null;
    public static String user = null;
    public static String password = null;
    public static List<String> mountTableNames = null;

    private Map<Object, Map> bufferedSaveData = new HashMap(10);
    private static String bufferedDataBodyKey = "buf";
    private static String bufferedDataOffset = "offset";

    public volatile static String DEFAULT_JSON_ENCODING = "UTF-8";

    private Map openFileStatus = new Hashtable();

    private Object[] syncFileAccess = new Object[10000];

    DatabaseClient dbmfsCore = null;

    public volatile static int DATABASE_TYPE = 1; //1=MySQL, 2=PostgreSQL

    public BindQueryFolder bindQueryFolder = null;

    public DatabaseFilesystem(String driverName, String databaseAddress, int databasePort, String databaseName,
            String user, String password) throws IOException {
    }

    public DatabaseFilesystem(String driverName, String databaseUrl, String user, String password, String readOnly,
            String mountTables, BindQueryFolder bindQueryFolder) throws IOException {
        log.info("database file system mount start ....");

        int files = 0;
        int dirs = 0;
        int blocks = 0;

        DatabaseFilesystem.driverName = driverName;
        DatabaseFilesystem.databaseUrl = databaseUrl;
        DatabaseFilesystem.user = user;
        DatabaseFilesystem.password = password;
        if (readOnly.equals("1"))
            readOnlyMount = true;

        if (mountTables != null && !mountTables.trim().equals("")) {
            // ???????
            // ????
            mountTableNames = DbmfsUtil.buildMountTableNames(mountTables);
        }

        this.bindQueryFolder = bindQueryFolder;

        statfs = new FuseStatfs();
        statfs.blocks = Integer.MAX_VALUE;
        statfs.blockSize = 1024 * 64;
        statfs.blocksFree = Integer.MAX_VALUE;
        statfs.files = files + dirs;
        statfs.filesFree = Integer.MAX_VALUE;
        statfs.namelen = 2048;
        try {
            for (int idx = 0; idx < this.syncFileAccess.length; idx++) {
                this.syncFileAccess[idx] = new Object();
            }

            Class.forName(DatabaseFilesystem.driverName);

            if (DatabaseFilesystem.driverName.indexOf("mysql") != -1) {
                DatabaseFilesystem.DATABASE_TYPE = 1;
            } else if (DatabaseFilesystem.driverName.indexOf("postgresql") != -1) {
                DatabaseFilesystem.DATABASE_TYPE = 2;
            }

            DatabaseAccessor.initDatabaseAccessor();

            dbmfsCore = new DatabaseClient(this.bindQueryFolder);
        } catch (Exception e) {

            throw new IOException(e);
        }
        log.info("database file system mouted ....");
    }

    public int chmod(String path, int mode) throws FuseException {
        log.info("chmod " + path + " " + mode);
        throw new FuseException("No Support Method").initErrno(FuseException.EACCES);
    }

    public int chown(String path, int uid, int gid) throws FuseException {
        log.info("chown " + path + " " + uid + " " + gid);
        throw new FuseException("No Support Method").initErrno(FuseException.EACCES);
    }

    public int getattr(String path, FuseGetattrSetter getattrSetter) throws FuseException {
        log.info("getattr " + path);

        String[] pathInfo = null;
        String[] setInfo = new String[11];

        try {
            if (DbmfsUtil.isTopDirectoryPath(path)) {

                setInfo[1] = new Integer(FuseFtypeConstants.TYPE_DIR | 0777).toString();
                pathInfo = new String[9];
                pathInfo[1] = "0";
                pathInfo[2] = "0";
                pathInfo[3] = "0";
                pathInfo[4] = "0";
                pathInfo[5] = "0";
                pathInfo[6] = "0";
                pathInfo[8] = "0";
            } else {

                // ???????

                // ????offse limit???
                path = DbmfsUtil.convertRealPath(path.trim());
                String infomationString = dbmfsCore.getInfomation(path);

                //   /a       = dir    1  0  0  0  1435098875  0  493    0  24576974580222
                //   /a/1.txt = file  1  0  0  0  1435098888  0  33188  0  24589836752449  -1
                //   /a/2.txt = file  1  0  0  0  1435098890  0  33188  0  24591395798630  -1

                // File : file  1  0  0  0  1435097370  0  33188  0  23071466454130  -1
                // Dir  : dir    1  0  0  0  1435097353  0  493    0  23055035971442
                //        0     1 2 3 4 5           6 7     8 9                10
                // System.out.println( DbmfsUtil.isTableName(path));
                if (infomationString == null || infomationString.trim().equals("")) {
                    // ?

                    if (path.indexOf("json") == -1 && DbmfsUtil.countPathSeparator(path) == 1
                            && DbmfsUtil.isTableName(path)) {

                        if (dbmfsCore.exsistTmpDir(path)) {

                            // ?????(mkdir????)
                            setInfo[1] = new Integer(FuseFtypeConstants.TYPE_DIR | 0777).toString();
                            pathInfo = new String[9];
                            pathInfo[1] = "0";
                            pathInfo[2] = "0";
                            pathInfo[3] = "0";
                            pathInfo[4] = "0";
                            pathInfo[5] = "0";
                            pathInfo[6] = "0";
                            pathInfo[8] = "0";
                        } else {
                            return Errno.ENOENT;
                        }
                    } else {
                        return Errno.ENOENT;
                    }
                } else {
                    // 
                    pathInfo = DbmfsUtil.deserializeInfomationString(infomationString);
                    if (pathInfo[0].equals("file")) {
                        setInfo[1] = new Integer(FuseFtypeConstants.TYPE_FILE | new Integer(pathInfo[7]).intValue())
                                .toString();
                    } else if (pathInfo[0].equals("dir")) {
                        setInfo[1] = new Integer(FuseFtypeConstants.TYPE_DIR | new Integer(pathInfo[7]).intValue())
                                .toString();
                    }
                }
            }
            // ?
            setInfo[0] = new Integer(path.hashCode()).toString();
            setInfo[2] = pathInfo[1];
            setInfo[3] = pathInfo[2];
            setInfo[4] = pathInfo[3];
            setInfo[5] = pathInfo[8];
            setInfo[6] = pathInfo[4];
            long blockCnt = Long.parseLong(setInfo[6]) / 4096;
            if (Long.parseLong(setInfo[6]) % 4096 > 0)
                blockCnt++;
            setInfo[8] = pathInfo[5];
            setInfo[9] = pathInfo[5];
            setInfo[10] = pathInfo[5];

            getattrSetter.set(new Long(setInfo[0]).longValue(), new Integer(setInfo[1]).intValue(),
                    new Integer(setInfo[2]).intValue(), new Integer(setInfo[3]).intValue(),
                    new Integer(setInfo[4]).intValue(), new Integer(setInfo[5]).intValue(),
                    new Long(setInfo[6]).longValue(), blockCnt, new Integer(setInfo[8]).intValue(),
                    new Integer(setInfo[9]).intValue(), new Integer(setInfo[10]).intValue());

        } catch (FuseException fe) {
            fe.printStackTrace();
            throw fe;
        } catch (Exception e) {
            e.printStackTrace();
            new FuseException(e).initErrno(FuseException.EACCES);
        }
        return 0;
    }

    public int getdir(String path, FuseDirFiller dirFiller) throws FuseException {
        log.info("getdir " + path);

        try {

            // /a = {/a/1.txt=file, /a/2.txt=file}
            // / = {/a=dir, /3.txt=file}

            // path???????
            // DbmfsUtil.parseLimitOffsetCharacter(); TODO:??????limit offset??????
            TargetDirectoryParams targetDirectoryParams = DbmfsUtil.parseTargetDirectoryPath(path);

            Map dirChildMap = null;
            if (targetDirectoryParams.hasLimitOffsetParams()) {
                dirChildMap = dbmfsCore.getDirectoryInObjects(targetDirectoryParams.tableName,
                        targetDirectoryParams.offset, targetDirectoryParams.limit);
            } else {
                dirChildMap = dbmfsCore.getDirectoryInObjects(targetDirectoryParams.tableName);
            }
            if (dirChildMap == null)
                return Errno.ENOTDIR;

            Set entrySet = dirChildMap.entrySet();
            Iterator entryIte = entrySet.iterator();

            // ?100????"100_"?????
            int nowCount = 0;
            while (entryIte.hasNext()) {

                nowCount++;
                // offset limit??????break;
                if (maxShowFiles < nowCount && targetDirectoryParams.hasLimitOffsetParams() == false)
                    break;

                Map.Entry obj = (Map.Entry) entryIte.next();

                String name = (String) obj.getKey();
                String objType = (String) obj.getValue();
                String[] nameCnv = name.split("/");

                if (objType.equals("file")) {
                    dirFiller.add(nameCnv[nameCnv.length - 1], 0L, FuseFtype.TYPE_FILE);
                } else if (objType.equals("dir")) {
                    dirFiller.add(nameCnv[nameCnv.length - 1], 0L, FuseFtype.TYPE_DIR);
                }
            }
            // ?"100_"?
            if (dirChildMap.size() > maxShowFiles && targetDirectoryParams.hasLimitOffsetParams() == false)
                dirFiller.add(maxShowFiles + "_", 0L, FuseFtype.TYPE_DIR);
        } catch (FuseException fe) {
            throw fe;
        } catch (Exception e) {
            throw new FuseException(e);
        }
        return 0;
    }

    public int link(String from, String to) throws FuseException {
        log.info("link " + from + " " + to);
        return Errno.EACCES;
    }

    public int mkdir(String path, int mode) throws FuseException {
        log.info("mkdir " + path + " " + mode);
        if (readOnlyMount)
            throw new FuseException("Read Only").initErrno(FuseException.EACCES);
        dbmfsCore.createTmpDir(path.trim());
        return 0;
        //throw new FuseException("Read Only").initErrno(FuseException.EACCES);
    }

    public int mknod(String path, int mode, int rdev) throws FuseException {
        log.info("mknod " + path + " " + mode + " " + rdev);
        if (readOnlyMount)
            throw new FuseException("Read Only").initErrno(FuseException.EACCES);

        // ?"."?????????
        if (DbmfsUtil.isHiddenFile(path)) {
            //System.out.println(path + " is hidden file");
            return 0;
        }

        // ????offset limit???
        path = DbmfsUtil.convertRealPath(path.trim());

        String modeStr = Integer.toOctalString(mode);
        String pathType = "";
        String fileBlockIdx = null;
        if (modeStr.indexOf("100") == 0) {

            // Regular File
            pathType = "file";
            fileBlockIdx = "-1";
        } else if (modeStr.indexOf("40") == 0) {

            // Directory
            pathType = "dir";
            throw new FuseException("Directory not created").initErrno(FuseException.EACCES);
        } else {

            return Errno.EINVAL;
        }

        StringBuilder infomationBuf = new StringBuilder();
        infomationBuf.append(pathType);
        infomationBuf.append("\t").append("1");
        infomationBuf.append("\t").append("0");
        infomationBuf.append("\t").append("0");
        infomationBuf.append("\t").append("0");
        infomationBuf.append("\t").append((System.currentTimeMillis() / 1000L));
        infomationBuf.append("\t").append("0");
        infomationBuf.append("\t").append(mode);
        infomationBuf.append("\t").append(rdev);
        infomationBuf.append("\t").append(System.nanoTime());
        if (fileBlockIdx != null) {
            infomationBuf.append("\t").append(fileBlockIdx);
        }

        try {
            String checkInfomation = dbmfsCore.getInfomation(path);

            if (checkInfomation != null && !checkInfomation.trim().equals(""))
                return Errno.EEXIST;
            if (!dbmfsCore.createTmpiNode(path.trim(), infomationBuf.toString()))
                return Errno.EEXIST;

        } catch (FuseException fe) {

            throw fe;
        } catch (Exception e) {

            new FuseException(e);
        }

        return 0;
    }

    public int open(String path, int flags, FuseOpenSetter openSetter) throws FuseException {
        log.info("open " + path + " " + flags);
        long fileDp = System.nanoTime();

        try {
            // ????offset limit???
            path = DbmfsUtil.convertRealPath(path.trim());

            String pathInfo = dbmfsCore.getInfomation(path.trim());
            if (pathInfo == null || pathInfo.trim().equals(""))
                return Errno.ENOENT;

            Map<String, Object> openDt = new HashMap();

            openDt.put("filedp", fileDp);
            openDt.put("pathInfoStr", pathInfo);
            openFileStatus.put(path.trim(), openDt);

            openSetter.setFh(openDt);
        } catch (FuseException fe) {
            throw fe;
        } catch (Exception e) {
            e.printStackTrace();
            new FuseException(e);
        }
        return 0;
    }

    public int rename(String from, String to) throws FuseException {
        log.info("rename " + from + " " + to);
        throw new FuseException("No Support Method").initErrno(FuseException.EACCES);
    }

    public int rmdir(String path) throws FuseException {
        log.info("rmdir " + path);
        throw new FuseException("No Support Method").initErrno(FuseException.EACCES);
    }

    public int statfs(FuseStatfsSetter statfsSetter) throws FuseException {
        log.info("statfs " + statfsSetter);
        statfsSetter.set(blockSize, Integer.MAX_VALUE, Integer.MAX_VALUE, Integer.MAX_VALUE, 0, Integer.MAX_VALUE,
                2000);
        return 0;
    }

    public int symlink(String from, String to) throws FuseException {
        log.info("symlink " + from + " " + to);
        throw new FuseException("No Support Method").initErrno(FuseException.EACCES);
    }

    public int truncate(String path, long size) throws FuseException {
        log.info("truncate " + path + " " + size);
        if (readOnlyMount)
            throw new FuseException("Read Only").initErrno(FuseException.EACCES);

        //throw new FuseException("Read Only").initErrno(FuseException.EACCES);
        try {
            //dbmfsCore.deleteData(path, null);
            /*} catch (FuseException fe) {
                throw fe;*/
        } catch (Exception e) {
            new FuseException(e);
        }
        return 0;
    }

    public int unlink(String path) throws FuseException {
        log.info("unlink " + path);
        if (readOnlyMount)
            throw new FuseException("Read Only").initErrno(FuseException.EACCES);
        //throw new FuseException("Read Only").initErrno(FuseException.EACCES);
        try {
            // ????offset limit???
            path = DbmfsUtil.convertRealPath(path.trim());

            dbmfsCore.deleteData(path);
        } catch (FuseException fe) {
            throw fe;
        } catch (Exception e) {
            new FuseException(e);
        }
        return 0;
    }

    public int utime(String path, int atime, int mtime) throws FuseException {
        log.info("utime " + path + " " + atime + " " + mtime);
        return 0;
    }

    public int readlink(String path, CharBuffer link) throws FuseException {
        log.info("readlink " + path);
        link.append(path);
        return 0;
    }

    public int write(String path, Object fh, boolean isWritepage, ByteBuffer buf, long offset)
            throws FuseException {
        log.info("write  path:" + path + " offset:" + offset + " isWritepage:" + isWritepage + " buf.limit:"
                + buf.limit());
        if (readOnlyMount)
            throw new FuseException("Read Only").initErrno(FuseException.EACCES);
        try {

            if (fh == null)
                return Errno.EBADE;

            // ????offset limit???
            path = DbmfsUtil.convertRealPath(path.trim());

            synchronized (syncFileAccess[((path.hashCode() << 1) >>> 1) % syncFileAccess.length]) {

                if (bufferedSaveData.containsKey(fh)) {

                    Map bufferedData = bufferedSaveData.get(fh);
                    ByteArrayOutputStream bufferedByteData = (ByteArrayOutputStream) bufferedData
                            .get(bufferedDataBodyKey);
                    long bOffset = ((Long) bufferedData.get(bufferedDataOffset)).longValue();

                    if ((bOffset + bufferedByteData.size()) == offset) {

                        byte[] nowWriteBytes = new byte[buf.limit()];
                        buf.get(nowWriteBytes);
                        bufferedByteData.write(nowWriteBytes);

                        return 0;
                    }
                } else {

                    Map bufferedData = new HashMap();

                    bufferedData.put("path", path);
                    bufferedData.put("fh", fh);
                    bufferedData.put("isWritepage", isWritepage);

                    ByteArrayOutputStream bufferedByteData = new ByteArrayOutputStream(1024 * 1024 * 2);
                    byte[] nowWriteBytes = new byte[buf.limit()];
                    buf.get(nowWriteBytes);

                    bufferedByteData.write(nowWriteBytes);
                    bufferedData.put(bufferedDataBodyKey, bufferedByteData);
                    bufferedData.put(bufferedDataOffset, offset);

                    this.bufferedSaveData.put(fh, bufferedData);
                    return 0;
                }
            }
        } catch (Exception e) {

            throw new FuseException(e);
        }
        return 0;
    }

    public int saveData(String path, Object fh, boolean isWritepage, byte[] writeData, long offset)
            throws FuseException {
        log.info("saveData  path:" + path + " offset:" + offset + " isWritepage:" + isWritepage + " buf.limit:"
                + writeData.length);

        if (fh == null)
            return Errno.EBADE;

        try {

            if (writeData == null || writeData.length < 1) {
                return Errno.EBADE;
            } else {

                if (!dbmfsCore.saveData(path.trim(), new String(writeData, DEFAULT_JSON_ENCODING))) {
                    return Errno.EBADE;
                }
            }
        } catch (FuseException fe) {
            throw fe;
        } catch (Exception e) {
            new FuseException(e);
        }
        return 0;
    }

    public int read(String path, Object fh, ByteBuffer buf, long offset) throws FuseException {
        log.info("read:" + path + " offset:" + offset + " buf.limit:" + buf.limit());
        if (fh == null)
            return Errno.EBADE;
        try {
            // ????offset limit???
            path = DbmfsUtil.convertRealPath(path.trim());

            int readLen = dbmfsCore.readValue(path, offset, buf.limit(), buf);
        } catch (FuseException fe) {
            throw fe;
        } catch (Exception e) {
            new FuseException(e);
        }
        return 0;
    }

    public int release(String path, Object fh, int flags) throws FuseException {
        log.info("release " + path + " " + fh + " " + flags);
        // ????offset limit???
        path = DbmfsUtil.convertRealPath(path.trim());

        synchronized (this.syncFileAccess[((path.hashCode() << 1) >>> 1) % syncFileAccess.length]) {

            openFileStatus.remove(path.trim());
            saveBufferedData(fh);
        }
        return 0;
    }

    public int flush(String path, Object fh) throws FuseException {
        log.info("flush " + path + " " + fh);
        // ????offset limit???
        path = DbmfsUtil.convertRealPath(path.trim());

        synchronized (this.syncFileAccess[((path.hashCode() << 1) >>> 1) % syncFileAccess.length]) {
            openFileStatus.remove(path.trim());
            saveBufferedData(fh);
        }
        return 0;
    }

    public int fsync(String path, Object fh, boolean isDatasync) throws FuseException {
        log.info("fsync " + path + " " + fh + " " + isDatasync);
        // ????offset limit???
        path = DbmfsUtil.convertRealPath(path.trim());

        synchronized (this.syncFileAccess[((path.hashCode() << 1) >>> 1) % syncFileAccess.length]) {
            openFileStatus.remove(path.trim());
            saveBufferedData(fh);
        }
        return 0;
    }

    private int saveBufferedData(Object fh) throws FuseException {
        log.info("saveBufferedData " + fh);

        if (bufferedSaveData.containsKey(fh)) {
            Map bufferedData = bufferedSaveData.remove(fh);
            if (bufferedData != null) {
                String path = (String) bufferedData.get("path");
                Object bufferedFh = (Object) bufferedData.get("fh");
                boolean isWritepage = ((Boolean) bufferedData.get("isWritepage")).booleanValue();
                ByteArrayOutputStream buf = (ByteArrayOutputStream) bufferedData.get(bufferedDataBodyKey);
                long offset = ((Long) bufferedData.get(bufferedDataOffset)).longValue();

                int realWriteRet = saveData(path, bufferedFh, isWritepage, buf.toByteArray(), offset);
            }
        }
        return 0;
    }

    public int getxattr(String path, String name, ByteBuffer dst) throws FuseException, BufferOverflowException {
        return 0;
    }

    public int setxattr(String path, String name, ByteBuffer value, int flags) throws FuseException {
        return 0;
    }

    public int getxattrsize(String path, String name, FuseSizeSetter sizeSetter) throws FuseException {
        return 0;
    }

    public int listxattr(String path, XattrLister lister) throws FuseException {
        return 0;
    }

    public int removexattr(String path, String name) throws FuseException {
        return 0;
    }

}