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     */
017    package org.apache.activemq.store;
018    
019    import org.apache.activemq.broker.AbstractLocker;
020    import org.apache.activemq.store.kahadb.MessageDatabase;
021    import org.apache.activemq.util.ServiceStopper;
022    import org.apache.kahadb.util.LockFile;
023    import org.slf4j.Logger;
024    import org.slf4j.LoggerFactory;
025    
026    import java.io.File;
027    import java.io.IOException;
028    
029    /**
030     * Represents an exclusive lock on a database to avoid multiple brokers running
031     * against the same logical database.
032     *
033     * @org.apache.xbean.XBean element="shared-file-locker"
034     *
035     */
036    public class SharedFileLocker extends AbstractLocker {
037    
038        private static final Logger LOG = LoggerFactory.getLogger(SharedFileLocker.class);
039    
040        private LockFile lockFile;
041        protected File directory = MessageDatabase.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 = true;
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 void doStop(ServiceStopper stopper) throws Exception {
079            lockFile.unlock();
080            lockFile=null;
081        }
082    
083        public File getDirectory() {
084            return directory;
085        }
086    
087        public void setDirectory(File directory) {
088            this.directory = directory;
089        }
090    
091        @Override
092        public void configure(PersistenceAdapter persistenceAdapter) throws IOException {
093            this.setDirectory(persistenceAdapter.getDirectory());
094        }
095    }