Package org.chaidb.db.helper

Source Code of org.chaidb.db.helper.SafeUpdateUtils$DirLock

/*
* 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.helper;

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

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


/**
* This class is used for Backup/Archive/Restore/DataRep. It implements most
* common function like backupFile, lockDir, and synchronization.
*/
public class SafeUpdateUtils {
    private static final String DEFAULT_TEMP_EXT = "ibk";
    public static final Object bmObj = new Object();
    private boolean restoreBackuped = false;
    private String tempFileExt = DEFAULT_TEMP_EXT;
    private String[] nameList = new String[0];
    private static final Logger logger = Logger.getLogger(SafeUpdateUtils.class);

    public void backupFiles(String[] nameList, String tmpExt) throws IOException {
        tempFileExt = tmpExt;
        backupFiles(nameList);
    }

    private void backupFiles(String[] nameList) throws IOException {
        if (nameList == null) {
            return;
        }

        restoreBackuped = false;
        this.nameList = new String[nameList.length];
        System.arraycopy(nameList, 0, this.nameList, 0, nameList.length);

        try {
            for (int i = 0; i < nameList.length; i++) {
                FileUtil.backupFile(nameList[i], tempFileExt);
            }
        } catch (IOException e) {
            this.nameList = new String[0];
            throw e;
        }

        restoreBackuped = true;
    }

    public void restoreFiles() {
        if (nameList == null) {
            return;
        }

        if (!restoreBackuped) {
            return;
        }

        for (int i = 0; i < nameList.length; i++) {
            try {
                FileUtil.restoreFile(nameList[i], tempFileExt);
            } catch (IOException e) {
                logger.error(e);
                System.err.println(e.getMessage());
            }
        }

        restoreBackuped = false;
    }

    public void clearFiles() {
        if (nameList == null) {
            return;
        }

        if (!restoreBackuped) {
            return;
        }

        for (int i = 0; i < nameList.length; i++) {
            FileUtil.clearBackupFile(nameList[i], tempFileExt);
        }

        nameList = new String[0];
        restoreBackuped = false;
    }

    static Document parse(InputSource input) throws IOException, org.xml.sax.SAXException {
        DOMParser parser = new DOMParser();
        parser.parse(input);

        return parser.getDocument();
    }

    public static synchronized void writeToDisk(Object obj, String filename, boolean writeToTempFile) throws IOException {
        String diskfile = filename;

        if (writeToTempFile) {
            diskfile = filename + ".tmp";
        }

        FileOutputStream fo = null;

        try {
            fo = new FileOutputStream(diskfile);
            fo.write(getUTFBytes(obj.toString()));
            fo.flush();
        } catch (UnsupportedEncodingException e) {
            logger.error(e);
        } finally {
            if (fo != null) {
                fo.close();
            }
        }
    }

    public static synchronized void commitWrite(String filename) throws ChaiDBException {
        String tmpFilename = filename + "." + DEFAULT_TEMP_EXT;
        File tmpFile = new File(tmpFilename);
        File orgFile = new File(filename);

        if (orgFile.exists()) {
            orgFile.delete();
        }

        if (!tmpFile.renameTo(orgFile)) {
            throw new ChaiDBException(ErrorCode.BACKUP_FILE_COPY_ERROR, "Can't rename a temp file. The File is " + tmpFilename + ". You should rename it to " + filename + " manually.");
        }
    }

    public static synchronized void rollbackWrite(String filename) {
        String tmpFilename = filename + "." + DEFAULT_TEMP_EXT;
        File tmpFile = new File(tmpFilename);
        tmpFile.delete();
    }

    public static synchronized long genGUID() {
        Random rnd = new Random();

        return rnd.nextLong();
    }

    /**
     * lock a directory such as archive dir
     *
     * @param path  - the dir which need lock
     * @param share
     * @return lock Object of lock, need for release, null if can't get lock
     */
    public static DirLock lockDir(String path, boolean share) {
        if (!path.endsWith(File.separator)) {
            path += File.separator;
        }
        File file = new File(path);
        if (!file.exists() || !file.isDirectory()) {
            return null;
        }

        synchronized (path) {
            while (true) {
                RandomAccessFile lockfile = null;
                try {
                    /* If share is true, it called by read-only process
                     * if share is false, it called by main process, we
                     * should create the file if it does not exist in
                     * main process.
                     */
                    String mode = "rw";
                    if (share) {
                        mode = "r";
                    }
                    lockfile = new RandomAccessFile(path + DirLock.LOCK_FILE, mode);

                    //lockfile.getChannel().lock(0L, Long.MAX_VALUE, true);
                    if (lockfile.getChannel().tryLock(0L, Long.MAX_VALUE, share) != null) {
                        return new DirLock(lockfile, path);
                    } else {
                        lockfile.close();
                    }
                } catch (IOException e) {
                    if (lockfile != null) {
                        try {
                            lockfile.close();
                        } catch (IOException e1) {
                            e1.printStackTrace();
                        }
                        lockfile = null;
                    }
                    return null;
                }

                try {
                    Thread.sleep(2000);
                } catch (InterruptedException e) {
                    return null;
                }
            }
        }
    }

    private static byte[] getUTFBytes(String s) throws UnsupportedEncodingException {
        return s.getBytes("UTF-8");
    }

    public static class DirLock {
        public static final String LOCK_FILE = "~lockfile";
        String path;
        RandomAccessFile lock;

        public DirLock(RandomAccessFile lock, String path) {
            this.lock = lock;
            this.path = path;
        }

        public void release() {
            try {
                lock.close();

                //                new File(path + LOCK_FILE).delete();
            } catch (IOException e) {
                ;
            }
        }
    }
}
TOP

Related Classes of org.chaidb.db.helper.SafeUpdateUtils$DirLock

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.