001/* 002 * jPOS Project [http://jpos.org] 003 * Copyright (C) 2000-2026 jPOS Software SRL 004 * 005 * This program is free software: you can redistribute it and/or modify 006 * it under the terms of the GNU Affero General Public License as 007 * published by the Free Software Foundation, either version 3 of the 008 * License, or (at your option) any later version. 009 * 010 * This program is distributed in the hope that it will be useful, 011 * but WITHOUT ANY WARRANTY; without even the implied warranty of 012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 013 * GNU Affero General Public License for more details. 014 * 015 * You should have received a copy of the GNU Affero General Public License 016 * along with this program. If not, see <http://www.gnu.org/licenses/>. 017 */ 018 019package org.jpos.q2.qbean; 020 021import java.io.File; 022import java.io.FileOutputStream; 023import java.io.RandomAccessFile; 024import java.nio.channels.FileChannel; 025import java.nio.channels.FileLock; 026 027import org.jpos.q2.QBeanSupport; 028 029/** 030 * QBean that enforces a single live Q2 instance by acquiring an exclusive 031 * file lock on a configured lockfile; a second instance fails to start when 032 * the file is already locked. 033 */ 034public class QSingleInstanceFileBasedManager extends QBeanSupport { 035 /** Default constructor; no instance state to initialise. */ 036 public QSingleInstanceFileBasedManager() {} 037 038 File lockFile; 039 FileChannel lockChannel; 040 FileLock lock; 041 FileOutputStream lockFileOS; 042 043 /* 044 * (non-Javadoc) 045 * 046 * @see org.jpos.q2.QBeanSupport#initService() 047 */ 048 @Override 049 protected void initService() throws Exception { 050 051 try { 052 lockFile = new File("./" + getServer().getDeployDir(), "instance.lock"); 053 if (lockFile.exists()) { 054 // Either an orphan lock or lock from another instance. Orphan 055 // lock will get deleted, the latter will not get a lock on it. 056 lockFile.delete(); 057 } 058 lockFileOS = new FileOutputStream(lockFile); 059 lockFileOS.close(); 060 lockChannel = new RandomAccessFile(lockFile, "rw").getChannel(); 061 lock = lockChannel.tryLock(); 062 if (lock == null) { 063 throw new Exception("Unable to obtain lock"); 064 } 065 } 066 catch (Exception e) { 067 getLog().error("An instance of Q2 is already running. Shutting this instance"); 068 if (lock != null) { 069 lock.release(); 070 } 071 if (lockChannel != null) { 072 lockChannel.close(); 073 } 074 if (lockFile != null) { 075 lockFile.delete(); 076 } 077 getServer().shutdown(); 078 } 079 080 } 081 082 @Override 083 protected void stopService() throws Exception { 084 085 lock.release(); 086 lockChannel.close(); 087 lockFile.delete(); 088 } 089 090}