com.asakusafw.runtime.util.lock.LocalFileLockProvider.java Source code

Java tutorial

Introduction

Here is the source code for com.asakusafw.runtime.util.lock.LocalFileLockProvider.java

Source

/**
 * Copyright 2011-2017 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.nio.charset.StandardCharsets;
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 = StandardCharsets.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()); //$NON-NLS-1$
        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})", //$NON-NLS-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})", //$NON-NLS-1$
                            target, lockFile));
                }
                try {
                    fd.seek(0L);
                    fd.setLength(0L);
                    fd.write(String.valueOf(target).getBytes(ENCODING));
                    success = true;
                    return new LocalFileLockObject<>(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})", //$NON-NLS-1$
                            target, lockFile));
                }
            }
            return result;
        } catch (OverlappingFileLockException e) {
            if (LOG.isDebugEnabled()) {
                LOG.debug(MessageFormat.format("Failed to acquire lock for \"{0}\" ({1})", //$NON-NLS-1$
                        target, lockFile)/*, e*/);
            }
            return null;
        }
    }
}