Package com.asakusafw.runtime.util.lock

Source Code of com.asakusafw.runtime.util.lock.LocalFileLockProvider

/**
* Copyright 2011-2014 Asakusa Framework Team.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*     http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.asakusafw.runtime.util.lock;

import java.io.File;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.nio.channels.FileLock;
import java.nio.channels.OverlappingFileLockException;
import java.nio.charset.Charset;
import java.text.MessageFormat;

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

/**
* An implementation of {@link LockProvider} using local file lock.
* @param <T> the lock target type
* @since 0.7.0
*/
public class LocalFileLockProvider<T> implements LockProvider<T> {

    static final Log LOG = LogFactory.getLog(LocalFileLockProvider.class);

    private static final Charset ENCODING = Charset.forName("UTF-8");

    private final File baseDirectory;

    /**
     * Creates a new instance.
     * @param baseDirectory the local lock file base directory
     */
    public LocalFileLockProvider(File baseDirectory) {
        this.baseDirectory = baseDirectory;
    }

    @Override
    public LocalFileLockObject<T> tryLock(T target) throws IOException {
        if (baseDirectory.mkdirs() == false && baseDirectory.isDirectory() == false) {
            throw new IOException(MessageFormat.format(
                    "Failed to create lock directory: {0}",
                    baseDirectory));
        }
        String fileName = String.format("%08x.lck", target == null ? -1 : target.hashCode());
        File lockFile = new File(baseDirectory, fileName);
        RandomAccessFile fd = new RandomAccessFile(lockFile, "rw"); //$NON-NLS-1$
        boolean success = false;
        try {
            if (LOG.isDebugEnabled()) {
                LOG.debug(MessageFormat.format(
                        "Start to acquire lock for \"{0}\" ({1})",
                        target,
                        lockFile));
            }
            FileLock lockEntity = getLock(target, lockFile, fd);
            if (lockEntity == null) {
                return null;
            } else {
                if (LOG.isDebugEnabled()) {
                    LOG.debug(MessageFormat.format(
                            "Finished to acquire lock for \"{0}\" ({1})",
                            target,
                            lockFile));
                }
                try {
                    fd.seek(0L);
                    fd.setLength(0L);
                    fd.write(String.valueOf(target).getBytes(ENCODING));
                    success = true;
                    return new LocalFileLockObject<T>(target, lockFile, fd, lockEntity);
                } finally {
                    if (success == false) {
                        lockEntity.release();
                    }
                }
            }
        } finally {
            if (success == false) {
                fd.close();
            }
        }
    }

    private FileLock getLock(T target, File lockFile, RandomAccessFile fd) throws IOException {
        try {
            FileLock result = fd.getChannel().tryLock();
            if (result == null) {
                if (LOG.isDebugEnabled()) {
                    LOG.debug(MessageFormat.format(
                            "Failed to acquire lock for \"{0}\" ({1})",
                            target,
                            lockFile));
                }
            }
            return result;
        } catch (OverlappingFileLockException e) {
            if (LOG.isDebugEnabled()) {
                LOG.debug(MessageFormat.format(
                        "Failed to acquire lock for \"{0}\" ({1})",
                        target,
                        lockFile)/*, e*/);
            }
            return null;
        }
    }
}
TOP

Related Classes of com.asakusafw.runtime.util.lock.LocalFileLockProvider

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.