KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > outerj > daisy > backuplock > impl > BackupLockerImpl


1 /*
2  * Copyright 2004 Outerthought bvba and Schaubroeck nv
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */

16 package org.outerj.daisy.backuplock.impl;
17
18 import org.outerj.daisy.backuplock.SuspendForBackupRegistrar;
19 import org.outerj.daisy.backuplock.SuspendableProcess;
20 import org.outerj.daisy.blobstore.BlobStore;
21 import org.outerj.daisy.jms.JmsClient;
22 import org.apache.avalon.framework.service.Serviceable;
23 import org.apache.avalon.framework.service.ServiceManager;
24 import org.apache.avalon.framework.service.ServiceException;
25 import org.apache.avalon.framework.activity.Initializable;
26 import org.apache.avalon.framework.activity.Disposable;
27
28 import javax.management.MBeanServer JavaDoc;
29 import javax.management.ObjectName JavaDoc;
30 import java.util.ArrayList JavaDoc;
31 import java.util.Iterator JavaDoc;
32 import java.util.List JavaDoc;
33
34 /**
35  * The purpose of the BackupLocker is to lock all operations that involve
36  * persistent modifications outside of the main SQL database. This way,
37  * a consistent backup can be taken of all these persistent stores.
38  *
39  * @avalon.component version="1.0" name="backuplocker" lifestyle="singleton"
40  * @avalon.service type="org.outerj.daisy.backuplock.SuspendForBackupRegistrar"
41  */

42 public class BackupLockerImpl implements SuspendForBackupRegistrar, Serviceable, Initializable, BackupLockerImplMBean,
43         Disposable {
44     private BlobStore blobStore;
45     private JmsClient jmsClient;
46     private List JavaDoc suspendableProcesses = new ArrayList JavaDoc();
47     private ServiceManager serviceManager;
48     private boolean locked = false;
49
50     /**
51      * @avalon.dependency key="blobstore" type="org.outerj.daisy.blobstore.BlobStore"
52      * @avalon.dependency key="jmsclient" type="org.outerj.daisy.jms.JmsClient"
53      * @avalon.dependency key="mbeanserver" type="javax.management.MBeanServer"
54      */

55     public void service(ServiceManager serviceManager) throws ServiceException {
56         this.serviceManager = serviceManager;
57         this.blobStore = (BlobStore)serviceManager.lookup("blobstore");
58         this.jmsClient = (JmsClient)serviceManager.lookup("jmsclient");
59     }
60
61     public void initialize() throws Exception JavaDoc {
62         MBeanServer JavaDoc mbeanServer = (MBeanServer JavaDoc)serviceManager.lookup("mbeanserver");
63         try {
64             mbeanServer.registerMBean(this, new ObjectName JavaDoc("Daisy:name=BackupLocker"));
65         } finally {
66             serviceManager.release(mbeanServer);
67         }
68
69         // Since the JMS client is not specific to the repository server, we register
70
// it ourselves instead of the other way around
71
suspendableProcesses.add(new ProcessInfo("JMS client", new SuspendableProcess() {
72             public boolean suspendExecution(long msecs) throws InterruptedException JavaDoc {
73                 return jmsClient.suspend(msecs);
74             }
75
76             public void resumeExecution() {
77                 jmsClient.resume();
78             }
79         }));
80         // The blob store should always be the last one to be shut down (since other
81
// processes might rely on it), so add it manually as the last one.
82
suspendableProcesses.add(new ProcessInfo("Blob store", new SuspendableProcess() {
83             public boolean suspendExecution(long msecs) throws InterruptedException JavaDoc {
84                 return blobStore.suspendWrites(msecs);
85             }
86
87             public void resumeExecution() {
88                 blobStore.resumeWrites();
89             }
90         }));
91     }
92
93     public synchronized void dispose() {
94         suspendableProcesses.clear();
95         serviceManager.release(blobStore);
96         serviceManager.release(jmsClient);
97     }
98
99     public synchronized void register(String JavaDoc descriptiveName, SuspendableProcess process) {
100         // Note: add at begin of list, so that it gets suspended before blobstore
101
suspendableProcesses.add(0, new ProcessInfo(descriptiveName, process));
102     }
103
104     public synchronized void unregister(SuspendableProcess process) {
105         for (int i = 0; i < suspendableProcesses.size(); i++) {
106             ProcessInfo processInfo = (ProcessInfo)suspendableProcesses.get(i);
107             if (processInfo.process == process) {
108                 suspendableProcesses.remove(i);
109                 return;
110             }
111         }
112     }
113
114     static class ProcessInfo {
115         String JavaDoc name;
116         SuspendableProcess process;
117
118         public ProcessInfo(String JavaDoc name, SuspendableProcess process) {
119             this.name = name;
120             this.process = process;
121         }
122     }
123
124     public synchronized void lock(long msecs) throws Exception JavaDoc {
125         if (locked)
126             throw new Exception JavaDoc("Already locked for backup.");
127
128         Iterator JavaDoc suspendableProcessesIt = suspendableProcesses.iterator();
129         while (suspendableProcessesIt.hasNext()) {
130             ProcessInfo processInfo = (ProcessInfo)suspendableProcessesIt.next();
131             boolean success = false;
132             try {
133                 success = processInfo.process.suspendExecution(msecs);
134             } catch (InterruptedException JavaDoc e) {
135                 // ignore
136
}
137             if (!success) {
138                 // call unlock to make sure everything is unlocked again.
139
unlock(true);
140                 throw new Exception JavaDoc("Failed to suspend execution of " + processInfo.name + " within the given time out of " + msecs + " msecs.");
141             }
142         }
143         locked = true;
144     }
145
146     public synchronized void unlock() throws Exception JavaDoc {
147         unlock(false);
148     }
149
150     private synchronized void unlock(boolean force) throws Exception JavaDoc {
151         if (!force && !locked)
152             throw new Exception JavaDoc("Cannot unlock, because currently not locked.");
153
154         Iterator JavaDoc suspendableProcessesIt = suspendableProcesses.iterator();
155         while (suspendableProcessesIt.hasNext()) {
156             ProcessInfo processInfo = (ProcessInfo)suspendableProcessesIt.next();
157             processInfo.process.resumeExecution();
158         }
159         locked = false;
160     }
161
162     public synchronized boolean isLocked() {
163         return locked;
164     }
165 }
166
Popular Tags