001/**
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements.  See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License.  You may obtain a copy of the License at
008 *
009 *      http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017package org.apache.activemq.store;
018
019import org.apache.activemq.broker.AbstractLocker;
020import org.apache.activemq.util.LockFile;
021import org.apache.activemq.util.ServiceStopper;
022import org.slf4j.Logger;
023import org.slf4j.LoggerFactory;
024
025import java.io.File;
026import java.io.IOException;
027
028/**
029 * Represents an exclusive lock on a database to avoid multiple brokers running
030 * against the same logical database.
031 *
032 * @org.apache.xbean.XBean element="shared-file-locker"
033 *
034 */
035public class SharedFileLocker extends AbstractLocker {
036
037    public static final File DEFAULT_DIRECTORY = new File("KahaDB");
038    private static final Logger LOG = LoggerFactory.getLogger(SharedFileLocker.class);
039
040    private LockFile lockFile;
041    protected File directory = DEFAULT_DIRECTORY;
042
043    @Override
044    public void doStart() throws Exception {
045        if (lockFile == null) {
046            File lockFileName = new File(directory, "lock");
047            lockFile = new LockFile(lockFileName, true);
048            if (failIfLocked) {
049                lockFile.lock();
050            } else {
051                boolean locked = false;
052                while ((!isStopped()) && (!isStopping())) {
053                    try {
054                        lockFile.lock();
055                        locked = keepAlive();
056                        break;
057                    } catch (IOException e) {
058                        LOG.info("Database "
059                                + lockFileName
060                                + " is locked... waiting "
061                                + (lockAcquireSleepInterval / 1000)
062                                + " seconds for the database to be unlocked. Reason: "
063                                + e);
064                        try {
065                            Thread.sleep(lockAcquireSleepInterval);
066                        } catch (InterruptedException e1) {
067                        }
068                    }
069                }
070                if (!locked) {
071                    throw new IOException("attempt to obtain lock aborted due to shutdown");
072                }
073            }
074        }
075    }
076
077    @Override
078    public boolean keepAlive() {
079        return lockFile != null && lockFile.keepAlive();
080    }
081
082    @Override
083    public void doStop(ServiceStopper stopper) throws Exception {
084        lockFile.unlock();
085        lockFile=null;
086    }
087
088    public File getDirectory() {
089        return directory;
090    }
091
092    public void setDirectory(File directory) {
093        this.directory = directory;
094    }
095
096    @Override
097    public void configure(PersistenceAdapter persistenceAdapter) throws IOException {
098        this.setDirectory(persistenceAdapter.getDirectory());
099    }
100}