Mercurial > hg > blitz_stable
comparison src/org/dancres/blitz/remote/BlitzServiceImpl.java @ 0:3dc0c5604566
Initial checkin of blitz 2.0 fcs - no installer yet.
author | Dan Creswell <dan.creswell@gmail.com> |
---|---|
date | Sat, 21 Mar 2009 11:00:06 +0000 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:3dc0c5604566 |
---|---|
1 package org.dancres.blitz.remote; | |
2 | |
3 import java.io.IOException; | |
4 | |
5 import java.rmi.RemoteException; | |
6 import java.rmi.MarshalledObject; | |
7 import java.rmi.RMISecurityManager; | |
8 import java.rmi.NoSuchObjectException; | |
9 | |
10 import java.rmi.activation.ActivationID; | |
11 import java.rmi.activation.ActivationException; | |
12 import java.rmi.activation.ActivationSystem; | |
13 import java.rmi.activation.Activatable; | |
14 | |
15 import java.util.ArrayList; | |
16 import java.util.List; | |
17 | |
18 import java.util.logging.Logger; | |
19 import java.util.logging.Level; | |
20 | |
21 import java.security.PrivilegedExceptionAction; | |
22 import java.security.PrivilegedActionException; | |
23 import java.net.InetSocketAddress; | |
24 | |
25 import javax.security.auth.Subject; | |
26 import javax.security.auth.login.LoginContext; | |
27 import javax.security.auth.login.LoginException; | |
28 | |
29 import net.jini.security.ProxyPreparer; | |
30 import net.jini.security.TrustVerifier; | |
31 | |
32 import net.jini.security.proxytrust.ServerProxyTrust; | |
33 | |
34 import net.jini.lookup.JoinManager; | |
35 | |
36 import net.jini.config.ConfigurationException; | |
37 import net.jini.config.Configuration; | |
38 | |
39 import net.jini.export.ProxyAccessor; | |
40 import net.jini.export.Exporter; | |
41 | |
42 import net.jini.activation.ActivationExporter; | |
43 import net.jini.activation.ActivationGroup; | |
44 | |
45 import net.jini.jeri.BasicILFactory; | |
46 import net.jini.jeri.BasicJeriExporter; | |
47 | |
48 import net.jini.jeri.tcp.TcpServerEndpoint; | |
49 | |
50 import net.jini.core.transaction.Transaction; | |
51 import net.jini.core.transaction.UnknownTransactionException; | |
52 import net.jini.core.transaction.TransactionException; | |
53 | |
54 import net.jini.core.transaction.server.TransactionManager; | |
55 | |
56 import net.jini.core.event.RemoteEventListener; | |
57 import net.jini.core.event.EventRegistration; | |
58 | |
59 import net.jini.core.lease.Lease; | |
60 import net.jini.core.lease.UnknownLeaseException; | |
61 import net.jini.core.lease.LeaseDeniedException; | |
62 | |
63 import net.jini.core.discovery.LookupLocator; | |
64 | |
65 import net.jini.core.entry.Entry; | |
66 | |
67 import net.jini.discovery.DiscoveryLocatorManagement; | |
68 import net.jini.discovery.DiscoveryGroupManagement; | |
69 import net.jini.discovery.DiscoveryManagement; | |
70 | |
71 import net.jini.space.JavaSpace; | |
72 | |
73 import com.sun.jini.start.LifeCycle; | |
74 | |
75 import org.dancres.blitz.mangler.MangledEntry; | |
76 | |
77 import org.dancres.blitz.lease.SpaceUID; | |
78 import org.dancres.blitz.lease.LeaseBounds; | |
79 | |
80 import org.dancres.blitz.config.ConfigurationFactory; | |
81 | |
82 import org.dancres.blitz.notify.RemoteEventDispatcher; | |
83 | |
84 import org.dancres.blitz.Logging; | |
85 import org.dancres.blitz.SpaceImpl; | |
86 import org.dancres.blitz.RegTicket; | |
87 import org.dancres.blitz.WriteTicket; | |
88 import org.dancres.blitz.EntryChit; | |
89 import org.dancres.blitz.EntryView; | |
90 | |
91 import org.dancres.blitz.txn.StoragePersonalityFactory; | |
92 import org.dancres.blitz.txn.StoragePersonality; | |
93 | |
94 import org.dancres.blitz.stats.Stat; | |
95 import org.dancres.blitz.stats.Switch; | |
96 import org.dancres.blitz.stats.StatsBoard; | |
97 import org.dancres.blitz.stats.SwitchSettings; | |
98 | |
99 import org.dancres.blitz.remote.view.EntryViewFactory; | |
100 import org.dancres.blitz.remote.view.ViewRegistration; | |
101 import org.dancres.blitz.remote.view.EntryViewUID; | |
102 import org.dancres.blitz.remote.txn.TransactionManagerImpl; | |
103 import org.dancres.blitz.remote.user.ColocatedAgent; | |
104 | |
105 /** | |
106 <p> The remote layer implementation for Blitz supporting both transient and | |
107 activatable modes of operation. Needs to implement ProxyAccessor to | |
108 provide a means of accessing it's core remote ref for the purposes of | |
109 converting this remote service implementation to a stub at appropriate | |
110 moments in the activation process </p>. | |
111 | |
112 <p> We need to publish a proxy for the Javaspace itself. If we implement | |
113 Administrable, this proxy should call back to the server's getAdmin() to | |
114 recovery an admin proxy which contains a remote stub to the admin methods. | |
115 The final proxy, for transactionparticipant can actually be a naked ref, | |
116 not even a proxy but this would allow immediate access to the other | |
117 interfaces of the stub which could be bad. </p> | |
118 | |
119 <p> JoinAdmin should be implemented by the admin proxy and the server | |
120 back end. Storage/manipulation of the JoinManager should be delegated to | |
121 a descendent of the JINIExporter LookupStorage code which should store | |
122 it's data in a Blitz meta registry. This means no configuration required | |
123 and keeps all the meta data in one neat place.</p> | |
124 */ | |
125 public class BlitzServiceImpl implements ServerProxyTrust, | |
126 ProxyAccessor, BlitzServer { | |
127 | |
128 static final Logger theLogger = | |
129 Logging.newLogger("org.dancres.blitz.remote", Level.INFO); | |
130 | |
131 private static BlitzServiceImpl theServiceImpl; | |
132 | |
133 private ActivationID theActivationID; | |
134 private ActivationSystem theActivationSystem; | |
135 | |
136 private LookupStorage theLookupStore; | |
137 | |
138 private Exporter theExporter; | |
139 | |
140 private BlitzServer theStub; | |
141 | |
142 private BlitzProxy theSpaceProxy; | |
143 | |
144 private JoinManager theJoinManager; | |
145 | |
146 private TxnGatewayImpl theTxnGate; | |
147 | |
148 private SpaceImpl theSpace; | |
149 | |
150 private AdminProxy theAdminProxy; | |
151 | |
152 private TxnParticipantProxy theTxnProxy; | |
153 | |
154 private LifeCycle theLifecycle; | |
155 | |
156 private boolean isStopped = false; | |
157 | |
158 private LoginContext theLoginContext; | |
159 | |
160 private boolean doCompatDestroy = false; | |
161 | |
162 private TransactionManagerImpl theLoopbackTxnMgr; | |
163 | |
164 /** | |
165 This constructor is required to use | |
166 com.sun.jini.start.NonActivatableServiceDescriptor. | |
167 */ | |
168 public BlitzServiceImpl(String [] anArgs, LifeCycle aLifeCycle) | |
169 throws RemoteException, ConfigurationException { | |
170 | |
171 try { | |
172 theLifecycle = aLifeCycle; | |
173 init(anArgs, true); | |
174 } catch (ConfigurationException aCE) { | |
175 destroyImpl(false); | |
176 throw aCE; | |
177 } catch (RemoteException anRE) { | |
178 destroyImpl(false); | |
179 throw anRE; | |
180 } | |
181 | |
182 /* | |
183 Keep a static reference to ourselves in order to avoid premature | |
184 GC | |
185 */ | |
186 theServiceImpl = this; | |
187 } | |
188 | |
189 /** | |
190 This constructor is required to use | |
191 com.sun.jini.start.SharedActivatableServiceDescriptor which invokes | |
192 on ActivateWrapper which will call this constructor. | |
193 SharedActivatabkeServiceDescriptor's serverConfigArgs are wrapped | |
194 into a MarshalledObject and pass in with the ActivationID. | |
195 */ | |
196 public BlitzServiceImpl(ActivationID anActivationID, | |
197 MarshalledObject aData) | |
198 throws RemoteException, ConfigurationException { | |
199 | |
200 theActivationID = anActivationID; | |
201 | |
202 String[] myArgs = null; | |
203 | |
204 try { | |
205 myArgs = (String[]) aData.get(); | |
206 } catch (Exception anE) { | |
207 theLogger.log(Level.SEVERE, "Failed to unpacked marshalled args", | |
208 anE); | |
209 throw new RemoteException("Failed to unpack marshalled args"); | |
210 } | |
211 | |
212 try { | |
213 init(myArgs, true); | |
214 } catch (ConfigurationException aCE) { | |
215 destroyImpl(false); | |
216 throw aCE; | |
217 } catch (RemoteException anRE) { | |
218 destroyImpl(false); | |
219 throw anRE; | |
220 } | |
221 | |
222 theServiceImpl = this; | |
223 } | |
224 | |
225 /** | |
226 * Use this to construct a local instance of blitz. When you have | |
227 * completed your usage of this local instance invoke either: | |
228 * | |
229 * <ul> | |
230 * <li>Shutdown - which will cleanly shutdown the instance retaining state | |
231 * (assuming you're running blitz in persistent mode).</li> | |
232 * <li>Destroy - which will cleanly shutdown the instance whilst discarding | |
233 * state as defined in the Jini DestroyAdmin specifications (note you can | |
234 * cause destroy to behave similarly to shutdown via appropriate | |
235 * configuration.</li> | |
236 * </ul> | |
237 */ | |
238 public BlitzServiceImpl() throws RemoteException, ConfigurationException { | |
239 init(new String[] {}, false); | |
240 } | |
241 | |
242 private void init(String[] anArgs, boolean doExport) | |
243 throws ConfigurationException, RemoteException { | |
244 | |
245 if (doExport) { | |
246 if (System.getSecurityManager() == null) | |
247 System.setSecurityManager(new RMISecurityManager()); | |
248 } | |
249 | |
250 if ((anArgs != null) && (anArgs.length > 0)) { | |
251 ConfigurationFactory.setup(anArgs); | |
252 } | |
253 | |
254 try { | |
255 doCompatDestroy = | |
256 ((Boolean) ConfigurationFactory.getEntry("compliantDestroy", | |
257 Boolean.class, | |
258 new Boolean(false))).booleanValue(); | |
259 | |
260 theLoginContext = (LoginContext) | |
261 ConfigurationFactory.getEntry("loginContext", | |
262 LoginContext.class, null); | |
263 | |
264 if (theLoginContext != null) { | |
265 try { | |
266 theLoginContext.login(); | |
267 } catch (LoginException aLE) { | |
268 theLogger.log(Level.SEVERE, "Couldn't login", aLE); | |
269 throw new ConfigurationException("Login invalid", aLE); | |
270 } | |
271 } | |
272 | |
273 doPriv(new PrivilegedInitImpl(doExport)); | |
274 } catch (Exception anE) { | |
275 theLogger.log(Level.SEVERE, "Oops privilege problem?", anE); | |
276 throw new ConfigurationException("loginContext has insufficient privileges", anE); | |
277 } | |
278 } | |
279 | |
280 private Object doPriv(PrivilegedExceptionAction aPAE) | |
281 throws Exception { | |
282 | |
283 if (theLoginContext != null) { | |
284 return Subject.doAsPrivileged(theLoginContext.getSubject(), | |
285 aPAE, null); | |
286 } else | |
287 return aPAE.run(); | |
288 } | |
289 | |
290 private class PrivilegedInitImpl implements PrivilegedExceptionAction { | |
291 private boolean doExport; | |
292 | |
293 PrivilegedInitImpl(boolean shouldExport) { | |
294 doExport = shouldExport; | |
295 } | |
296 | |
297 public Object run() throws Exception { | |
298 try { | |
299 initImpl(doExport); | |
300 } catch (Exception anE) { | |
301 theLogger.log(Level.SEVERE, "Could init with subject", anE); | |
302 throw anE; | |
303 } | |
304 return null; | |
305 } | |
306 } | |
307 | |
308 private void initImpl(boolean doExport) | |
309 throws ConfigurationException, RemoteException { | |
310 | |
311 /* | |
312 Create space with a TxnGatewayImpl | |
313 Once we've got as far as export'ing, invoke setParticipantStub | |
314 on TxnGatewayImpl so it can bundle things up appropriately. | |
315 */ | |
316 | |
317 // Make sure storage is able to initialize before we do anything | |
318 // | |
319 StoragePersonalityFactory.getPersonality(); | |
320 | |
321 theLookupStore = new LookupStorage(); | |
322 theLookupStore.init(ConfigurationFactory.getConfig()); | |
323 | |
324 Configuration myConfig = ConfigurationFactory.getConfig(); | |
325 | |
326 Exporter myDefaultExporter = | |
327 new BasicJeriExporter(TcpServerEndpoint.getInstance(0), | |
328 new BasicILFactory(), false, true); | |
329 | |
330 if (theActivationID == null) { | |
331 theExporter = | |
332 (Exporter) ConfigurationFactory.getEntry("serverExporter", | |
333 Exporter.class, | |
334 myDefaultExporter); | |
335 } else { | |
336 ProxyPreparer myIDPreparer = | |
337 ConfigurationFactory.getPreparer("activationIdPreparer"); | |
338 | |
339 ProxyPreparer mySysPreparer = | |
340 ConfigurationFactory.getPreparer("activationSysPreparer"); | |
341 | |
342 theActivationID = | |
343 (ActivationID) myIDPreparer.prepareProxy(theActivationID); | |
344 | |
345 try { | |
346 theActivationSystem = | |
347 (ActivationSystem) mySysPreparer.prepareProxy(ActivationGroup.getSystem()); | |
348 } catch (ActivationException anAE) { | |
349 throw new RemoteException("Unable to locate ActivationSystem"); | |
350 } | |
351 | |
352 ActivationExporter myDefActExp = | |
353 new ActivationExporter(theActivationID, myDefaultExporter); | |
354 | |
355 theExporter = | |
356 (Exporter) ConfigurationFactory.getEntry("serverExporter", | |
357 Exporter.class, | |
358 myDefActExp, | |
359 theActivationID); | |
360 } | |
361 | |
362 if (theExporter == null) { | |
363 throw new ConfigurationException("serverExporter must be non-null if it's specified"); | |
364 } | |
365 | |
366 theLogger.log(Level.INFO, "Using exporter: " + theExporter); | |
367 | |
368 if (doExport) | |
369 theStub = (BlitzServer) theExporter.export(this); | |
370 else { | |
371 // Don't need this - so clear it down.... | |
372 // | |
373 theExporter = null; | |
374 | |
375 theStub = this; | |
376 } | |
377 | |
378 Class[] myInterfaces = theStub.getClass().getInterfaces(); | |
379 | |
380 for (int i = 0; i < myInterfaces.length; i++) { | |
381 theLogger.log(Level.INFO, | |
382 "Stub supports: " + myInterfaces[i].getName()); | |
383 } | |
384 | |
385 theAdminProxy = | |
386 ProxyFactory.newAdminProxy(theStub, theLookupStore.getUuid()); | |
387 | |
388 theSpaceProxy = | |
389 ProxyFactory.newBlitzProxy(theStub, theLookupStore.getUuid()); | |
390 | |
391 theTxnProxy = | |
392 ProxyFactory.newTxnParticipantProxy(theStub, | |
393 theLookupStore.getUuid()); | |
394 theTxnGate = | |
395 new TxnGatewayImpl(theTxnProxy); | |
396 | |
397 RemoteEventDispatcher.setSource(theSpaceProxy); | |
398 | |
399 try { | |
400 theSpace = new SpaceImpl(theTxnGate); | |
401 | |
402 // Now run the user initializers | |
403 // | |
404 ColocatedAgent[] myInitializers = | |
405 (ColocatedAgent[]) | |
406 ConfigurationFactory.getEntry( | |
407 "agents", ColocatedAgent[].class, | |
408 new ColocatedAgent[0]); | |
409 | |
410 for (int i = 0; i < myInitializers.length; i++) { | |
411 myInitializers[i].init(theSpaceProxy); | |
412 } | |
413 | |
414 } catch (Exception anE) { | |
415 theLogger.log(Level.SEVERE, "Failed to start space", anE); | |
416 throw new RemoteException("Failed to start space", anE); | |
417 } | |
418 | |
419 if (doExport) { | |
420 theLogger.log(Level.INFO, "Space core is up, starting JoinManager"); | |
421 | |
422 try { | |
423 theJoinManager = new JoinManager(theSpaceProxy, | |
424 theLookupStore.getAttributes(), | |
425 theLookupStore.getServiceID(), | |
426 theLookupStore.getDiscMgt(), | |
427 null, | |
428 myConfig); | |
429 } catch (IOException anIOE) { | |
430 theLogger.log(Level.SEVERE, "Failed to init JoinManager", | |
431 anIOE); | |
432 | |
433 throw new RemoteException("Failed to init JoinManager", | |
434 anIOE); | |
435 } | |
436 } | |
437 | |
438 try { | |
439 theLoopbackTxnMgr = | |
440 new TransactionManagerImpl(theStub, theLookupStore.getUuid()); | |
441 } catch (IOException anIOE) { | |
442 throw new RemoteException("Failed to init loopback txn manager", | |
443 anIOE); | |
444 } | |
445 } | |
446 | |
447 public JavaSpace getSpaceProxy() { | |
448 return theSpaceProxy; | |
449 } | |
450 | |
451 public SpaceImpl getSpace() { | |
452 return theSpace; | |
453 } | |
454 | |
455 public LeaseImpl write(MangledEntry anEntry, Transaction aTxn, | |
456 long aLeaseTime) | |
457 throws RemoteException, TransactionException { | |
458 | |
459 stopBarrier(); | |
460 | |
461 try { | |
462 WriteTicket myTicket = theSpace.write(anEntry, aTxn, aLeaseTime); | |
463 | |
464 return | |
465 ProxyFactory.newEntryLeaseImpl(theStub, theLookupStore.getUuid(), | |
466 myTicket.getUID(), | |
467 myTicket.getExpirationTime()); | |
468 } catch (IOException anIOE) { | |
469 theLogger.log(Level.SEVERE, "SpaceImpl has disk problems", anIOE); | |
470 throw new RemoteException("Space has disk problems", anIOE); | |
471 } | |
472 } | |
473 | |
474 public MangledEntry take(MangledEntry anEntry, Transaction aTxn, | |
475 long aWaitTime) | |
476 throws RemoteException, TransactionException { | |
477 | |
478 stopBarrier(); | |
479 | |
480 try { | |
481 return theSpace.take(anEntry, aTxn, aWaitTime); | |
482 } catch (IOException anIOE) { | |
483 theLogger.log(Level.SEVERE, "SpaceImpl has disk problems", anIOE); | |
484 throw new RemoteException("Space has disk problems", anIOE); | |
485 } | |
486 } | |
487 | |
488 public MangledEntry read(MangledEntry anEntry, Transaction aTxn, | |
489 long aWaitTime) | |
490 throws RemoteException, TransactionException { | |
491 | |
492 stopBarrier(); | |
493 | |
494 try { | |
495 return theSpace.read(anEntry, aTxn, aWaitTime); | |
496 } catch (IOException anIOE) { | |
497 theLogger.log(Level.SEVERE, "SpaceImpl has disk problems", anIOE); | |
498 throw new RemoteException("Space has disk problems", anIOE); | |
499 } | |
500 } | |
501 | |
502 public MangledEntry takeIfExists(MangledEntry anEntry, Transaction aTxn, | |
503 long aWaitTime) | |
504 throws RemoteException, TransactionException { | |
505 | |
506 stopBarrier(); | |
507 | |
508 try { | |
509 return theSpace.takeIfExists(anEntry, aTxn, aWaitTime); | |
510 } catch (IOException anIOE) { | |
511 theLogger.log(Level.SEVERE, "SpaceImpl has disk problems", anIOE); | |
512 throw new RemoteException("Space has disk problems", anIOE); | |
513 } | |
514 } | |
515 | |
516 public MangledEntry readIfExists(MangledEntry anEntry, Transaction aTxn, | |
517 long aWaitTime) | |
518 throws RemoteException, TransactionException { | |
519 | |
520 stopBarrier(); | |
521 | |
522 try { | |
523 return theSpace.readIfExists(anEntry, aTxn, aWaitTime); | |
524 } catch (IOException anIOE) { | |
525 theLogger.log(Level.SEVERE, "SpaceImpl has disk problems", anIOE); | |
526 throw new RemoteException("Space has disk problems", anIOE); | |
527 } | |
528 } | |
529 | |
530 public EventRegistration notify(MangledEntry anEntry, Transaction aTxn, | |
531 RemoteEventListener aListener, | |
532 long aLeaseTime, | |
533 MarshalledObject aHandback) | |
534 throws RemoteException, TransactionException { | |
535 | |
536 stopBarrier(); | |
537 | |
538 try { | |
539 RegTicket myTicket = | |
540 theSpace.notify(anEntry, aTxn, aListener, aLeaseTime, | |
541 aHandback); | |
542 | |
543 LeaseImpl myLease = | |
544 ProxyFactory.newLeaseImpl(theStub, theLookupStore.getUuid(), | |
545 myTicket.getUID(), | |
546 myTicket.getExpirationTime()); | |
547 | |
548 return new EventRegistration(myTicket.getSourceId(), theSpaceProxy, | |
549 myLease, myTicket.getSeqNum()); | |
550 } catch (IOException anIOE) { | |
551 theLogger.log(Level.SEVERE, "SpaceImpl has disk problems", anIOE); | |
552 throw new RemoteException("Space has disk problems", anIOE); | |
553 } | |
554 } | |
555 | |
556 /* ********************************************************************* | |
557 * ProxyAccessor stuff | |
558 ******************************************************************** */ | |
559 | |
560 public Object getProxy() { | |
561 return theStub; | |
562 } | |
563 | |
564 /* ********************************************************************* | |
565 * ServerProxyTrust stuff | |
566 ******************************************************************** */ | |
567 | |
568 /** | |
569 <p> Blitz can be run as a secure service, in which case, it exports | |
570 various ConstrainedProxy instances which support RemoteMethodControl. | |
571 Such proxy instances are exported only when the original stub supports | |
572 RemoteMethodControl. </p> | |
573 | |
574 <p> As Blitz uses custom proxies as opposed to JERI stubs, we must | |
575 do some additional work to support TrustVerification. Assuming the | |
576 stub has been generated using ProxyTrustILFactory it supports the | |
577 bootstrap step. For bootstrap to work, the remote server must support | |
578 ServerProxyTrust which will be invoked as part of the bootstrap process | |
579 supported in the stub. </p> | |
580 */ | |
581 public TrustVerifier getProxyVerifier() throws RemoteException { | |
582 stopBarrier(); | |
583 | |
584 return new ProxyVerifier(theStub, theLookupStore.getUuid()); | |
585 } | |
586 | |
587 /* ********************************************************************* | |
588 * Transaction participant stuff | |
589 ******************************************************************** */ | |
590 | |
591 public int prepare(TransactionManager mgr, long id) | |
592 throws UnknownTransactionException, RemoteException { | |
593 | |
594 stopBarrier(); | |
595 | |
596 return theSpace.getTxnControl().prepare(mgr, id); | |
597 } | |
598 | |
599 public void commit(TransactionManager mgr, long id) | |
600 throws UnknownTransactionException, RemoteException { | |
601 | |
602 stopBarrier(); | |
603 | |
604 theSpace.getTxnControl().commit(mgr, id); | |
605 } | |
606 | |
607 public void abort(TransactionManager mgr, long id) | |
608 throws UnknownTransactionException, RemoteException { | |
609 | |
610 stopBarrier(); | |
611 | |
612 theSpace.getTxnControl().abort(mgr, id); | |
613 } | |
614 | |
615 public int prepareAndCommit(TransactionManager mgr, long id) | |
616 throws UnknownTransactionException, RemoteException { | |
617 | |
618 stopBarrier(); | |
619 | |
620 return theSpace.getTxnControl().prepareAndCommit(mgr, id); | |
621 } | |
622 | |
623 /* ********************************************************************* | |
624 * Landlord | |
625 ******************************************************************** */ | |
626 public long renew(SpaceUID aUID, long aDuration) | |
627 throws UnknownLeaseException, LeaseDeniedException, RemoteException { | |
628 | |
629 // System.out.println("Renew: " + aUID + ", " + aDuration); | |
630 | |
631 stopBarrier(); | |
632 | |
633 try { | |
634 long myResult = theSpace.getLeaseControl().renew(aUID, aDuration); | |
635 | |
636 // System.out.println("Renew: " + myResult); | |
637 | |
638 return myResult; | |
639 } catch (IOException anIOE) { | |
640 theLogger.log(Level.SEVERE, "Space has disk problems", anIOE); | |
641 throw new RemoteException("Space has disk problems", anIOE); | |
642 } | |
643 } | |
644 | |
645 public void cancel(SpaceUID aUID) | |
646 throws UnknownLeaseException, RemoteException { | |
647 | |
648 stopBarrier(); | |
649 | |
650 try { | |
651 theSpace.getLeaseControl().cancel(aUID); | |
652 } catch (IOException anIOE) { | |
653 theLogger.log(Level.SEVERE, "Space has disk problems", anIOE); | |
654 throw new RemoteException("Space has disk problems", anIOE); | |
655 } | |
656 } | |
657 | |
658 public LeaseResults renew(SpaceUID[] aLeases, long[] aDurations) | |
659 throws RemoteException { | |
660 | |
661 stopBarrier(); | |
662 | |
663 long[] myNewDurations = new long[aLeases.length]; | |
664 Exception[] myFails = null; | |
665 | |
666 for (int i = 0; i < aLeases.length; i++) { | |
667 try { | |
668 myNewDurations[i] = | |
669 theSpace.getLeaseControl().renew(aLeases[i], | |
670 aDurations[i]); | |
671 } catch (LeaseDeniedException anLDE) { | |
672 if (myFails == null) | |
673 myFails = initFails(aLeases.length, i); | |
674 | |
675 myNewDurations[i] = -1; | |
676 myFails[i] = anLDE; | |
677 } catch (UnknownLeaseException anULE) { | |
678 if (myFails == null) | |
679 myFails = initFails(aLeases.length, i); | |
680 | |
681 myNewDurations[i] = -1; | |
682 myFails[i] = anULE; | |
683 } catch (IOException anIOE) { | |
684 theLogger.log(Level.SEVERE, "Space has disk problems", anIOE); | |
685 throw new RemoteException("Space has disk problems", anIOE); | |
686 } | |
687 } | |
688 | |
689 return new LeaseResults(myNewDurations, myFails); | |
690 } | |
691 | |
692 public LeaseResults cancel(SpaceUID[] aLeases) | |
693 throws RemoteException { | |
694 | |
695 stopBarrier(); | |
696 | |
697 Exception[] myFails = null; | |
698 | |
699 for (int i = 0; i < aLeases.length; i++) { | |
700 try { | |
701 theSpace.getLeaseControl().cancel(aLeases[i]); | |
702 } catch (UnknownLeaseException aULE) { | |
703 if (myFails == null) | |
704 myFails = initFails(aLeases.length, i); | |
705 | |
706 myFails[i] = aULE; | |
707 } catch (IOException anIOE) { | |
708 theLogger.log(Level.SEVERE, "Space has disk problems", anIOE); | |
709 throw new RemoteException("Space has disk problems", anIOE); | |
710 } | |
711 } | |
712 | |
713 if (myFails != null) | |
714 return new LeaseResults(null, myFails); | |
715 else | |
716 return null; | |
717 } | |
718 | |
719 private Exception[] initFails(int aLength, int anOffset) { | |
720 return new Exception[aLength]; | |
721 } | |
722 | |
723 /* ********************************************************************* | |
724 * ServiceProxyAccessor | |
725 ******************************************************************** */ | |
726 | |
727 public Object getServiceProxy() throws RemoteException { | |
728 stopBarrier(); | |
729 | |
730 return theSpaceProxy; | |
731 } | |
732 | |
733 /* ********************************************************************* | |
734 * Administrable::getAdmin support | |
735 ******************************************************************** */ | |
736 | |
737 public Object getAdmin() throws RemoteException { | |
738 stopBarrier(); | |
739 | |
740 return theAdminProxy; | |
741 } | |
742 | |
743 /* ********************************************************************* | |
744 * JoinAdmin | |
745 ******************************************************************** */ | |
746 /** | |
747 * Get the current attribute sets for the service. | |
748 * | |
749 * @return the current attribute sets for the service | |
750 * @throws java.rmi.RemoteException | |
751 */ | |
752 public Entry[] getLookupAttributes() throws RemoteException { | |
753 stopBarrier(); | |
754 | |
755 return theJoinManager.getAttributes(); | |
756 } | |
757 | |
758 /** | |
759 * Add attribute sets for the service. The resulting set will be used | |
760 * for all future joins. The attribute sets are also added to all | |
761 * currently-joined lookup services. | |
762 * | |
763 * @param attrSets the attribute sets to add | |
764 * @throws java.rmi.RemoteException | |
765 */ | |
766 public void addLookupAttributes(Entry[] attrSets) throws RemoteException { | |
767 stopBarrier(); | |
768 | |
769 theJoinManager.addAttributes(attrSets); | |
770 syncStore(); | |
771 } | |
772 | |
773 /** | |
774 * Modify the current attribute sets, using the same semantics as | |
775 * ServiceRegistration.modifyAttributes. The resulting set will be used | |
776 * for all future joins. The same modifications are also made to all | |
777 * currently-joined lookup services. | |
778 * | |
779 * @param attrSetTemplates the templates for matching attribute sets | |
780 * @param attrSets the modifications to make to matching sets | |
781 * @throws java.rmi.RemoteException | |
782 * | |
783 * @see net.jini.core.lookup.ServiceRegistration#modifyAttributes | |
784 */ | |
785 public void modifyLookupAttributes(Entry[] attrSetTemplates, | |
786 Entry[] attrSets) | |
787 throws RemoteException { | |
788 stopBarrier(); | |
789 | |
790 theJoinManager.modifyAttributes(attrSetTemplates, attrSets); | |
791 syncStore(); | |
792 } | |
793 | |
794 private DiscoveryGroupManagement getDGM() { | |
795 return (DiscoveryGroupManagement) theJoinManager.getDiscoveryManager(); | |
796 } | |
797 | |
798 /** | |
799 * Get the list of groups to join. An empty array means the service | |
800 * joins no groups (as opposed to "all" groups). | |
801 * | |
802 * @return an array of groups to join. An empty array means the service | |
803 * joins no groups (as opposed to "all" groups). | |
804 * @throws java.rmi.RemoteException | |
805 * @see #setLookupGroups | |
806 */ | |
807 public String[] getLookupGroups() throws RemoteException { | |
808 stopBarrier(); | |
809 | |
810 return getDGM().getGroups(); | |
811 } | |
812 | |
813 /** | |
814 * Add new groups to the set to join. Lookup services in the new | |
815 * groups will be discovered and joined. | |
816 * | |
817 * @param groups groups to join | |
818 * @throws java.rmi.RemoteException | |
819 * @see #removeLookupGroups | |
820 */ | |
821 public void addLookupGroups(String[] groups) throws RemoteException { | |
822 stopBarrier(); | |
823 | |
824 try { | |
825 getDGM().addGroups(groups); | |
826 } catch (IOException anIOE) { | |
827 throw new RemoteException("Got IOE changing groups", anIOE); | |
828 } | |
829 syncStore(); | |
830 } | |
831 | |
832 /** | |
833 * Remove groups from the set to join. Leases are cancelled at lookup | |
834 * services that are not members of any of the remaining groups. | |
835 * | |
836 * @param groups groups to leave | |
837 * @throws java.rmi.RemoteException | |
838 * @see #addLookupGroups | |
839 */ | |
840 public void removeLookupGroups(String[] groups) throws RemoteException { | |
841 stopBarrier(); | |
842 | |
843 getDGM().removeGroups(groups); | |
844 syncStore(); | |
845 } | |
846 | |
847 /** | |
848 * Replace the list of groups to join with a new list. Leases are | |
849 * cancelled at lookup services that are not members of any of the | |
850 * new groups. Lookup services in the new groups will be discovered | |
851 * and joined. | |
852 * | |
853 * @param groups groups to join | |
854 * @throws java.rmi.RemoteException | |
855 * @see #getLookupGroups | |
856 */ | |
857 public void setLookupGroups(String[] groups) throws RemoteException { | |
858 stopBarrier(); | |
859 | |
860 try { | |
861 getDGM().setGroups(groups); | |
862 } catch (IOException anIOE) { | |
863 throw new RemoteException("Got IOE changing groups", anIOE); | |
864 } | |
865 syncStore(); | |
866 } | |
867 | |
868 private DiscoveryLocatorManagement getDLM() { | |
869 return (DiscoveryLocatorManagement) | |
870 theJoinManager.getDiscoveryManager(); | |
871 } | |
872 | |
873 /** | |
874 *Get the list of locators of specific lookup services to join. | |
875 * | |
876 * @return the list of locators of specific lookup services to join | |
877 * @throws java.rmi.RemoteException | |
878 * @see #setLookupLocators | |
879 */ | |
880 public LookupLocator[] getLookupLocators() throws RemoteException { | |
881 stopBarrier(); | |
882 | |
883 return getDLM().getLocators(); | |
884 } | |
885 | |
886 /** | |
887 * Add locators for specific new lookup services to join. The new | |
888 * lookup services will be discovered and joined. | |
889 * | |
890 * @param locators locators of specific lookup services to join | |
891 * @throws java.rmi.RemoteException | |
892 * @see #removeLookupLocators | |
893 */ | |
894 public void addLookupLocators(LookupLocator[] locators) | |
895 throws RemoteException { | |
896 stopBarrier(); | |
897 | |
898 getDLM().addLocators(locators); | |
899 syncStore(); | |
900 } | |
901 | |
902 /** | |
903 * Remove locators for specific lookup services from the set to join. | |
904 * Any leases held at the lookup services are cancelled. | |
905 * | |
906 * @param locators locators of specific lookup services to leave | |
907 * @throws java.rmi.RemoteException | |
908 * @see #addLookupLocators | |
909 */ | |
910 public void removeLookupLocators(LookupLocator[] locators) | |
911 throws RemoteException { | |
912 stopBarrier(); | |
913 | |
914 getDLM().removeLocators(locators); | |
915 syncStore(); | |
916 } | |
917 | |
918 /** | |
919 * Replace the list of locators of specific lookup services to join | |
920 * with a new list. Leases are cancelled at lookup services that were | |
921 * in the old list but are not in the new list. Any new lookup services | |
922 * will be discovered and joined. | |
923 * | |
924 * @param locators locators of specific lookup services to join | |
925 * @throws java.rmi.RemoteException | |
926 * @see #getLookupLocators | |
927 */ | |
928 public void setLookupLocators(LookupLocator[] locators) | |
929 throws RemoteException { | |
930 stopBarrier(); | |
931 | |
932 getDLM().setLocators(locators); | |
933 syncStore(); | |
934 } | |
935 | |
936 private void syncStore() throws RemoteException { | |
937 try { | |
938 theLookupStore.sync(theJoinManager); | |
939 } catch (IOException anIOE) { | |
940 throw new RemoteException("Couldn't update saved state", anIOE); | |
941 } | |
942 } | |
943 | |
944 | |
945 /* ********************************************************************* | |
946 * DestroyAdmin | |
947 ******************************************************************** */ | |
948 | |
949 public void destroy() throws RemoteException { | |
950 destroyImpl(doCompatDestroy); | |
951 } | |
952 | |
953 private void destroyImpl(boolean doCleanup) throws RemoteException { | |
954 stopBarrier(); | |
955 | |
956 blockCalls(); | |
957 | |
958 // Load cleanup variable from config and construct accordingly | |
959 Thread myDestroyer = new DestroyThread(doCleanup); | |
960 myDestroyer.setDaemon(false); | |
961 myDestroyer.start(); | |
962 } | |
963 | |
964 private void blockCalls() { | |
965 synchronized(this) { | |
966 isStopped = true; | |
967 } | |
968 } | |
969 | |
970 private void unblockCalls() { | |
971 synchronized(this) { | |
972 isStopped = false; | |
973 } | |
974 } | |
975 | |
976 /** | |
977 Used to check whether calls are blocked and, if they are, throws | |
978 a RemoteException back to the client. | |
979 */ | |
980 private void stopBarrier() throws RemoteException { | |
981 synchronized(this) { | |
982 if (isStopped) | |
983 throw new RemoteException("Remote calls not permitted"); | |
984 } | |
985 } | |
986 | |
987 private class DestroyThread extends Thread { | |
988 private boolean doClean; | |
989 | |
990 private DestroyThread(boolean shouldClean) { | |
991 super("DestroyThread"); | |
992 doClean = shouldClean; | |
993 } | |
994 | |
995 public void run() { | |
996 theLogger.log(Level.SEVERE, "Shutdown in progress"); | |
997 | |
998 if (theLoopbackTxnMgr != null) { | |
999 theLogger.log(Level.SEVERE, "Stop LoopbackTxnMgr"); | |
1000 theLoopbackTxnMgr.terminate(); | |
1001 } | |
1002 | |
1003 if (theJoinManager != null) { | |
1004 theLogger.log(Level.SEVERE, "Stop JoinManager"); | |
1005 DiscoveryManagement myDGM = theJoinManager.getDiscoveryManager(); | |
1006 | |
1007 theJoinManager.terminate(); | |
1008 myDGM.terminate(); | |
1009 } | |
1010 | |
1011 if (theActivationID != null) { | |
1012 theLogger.log(Level.SEVERE, | |
1013 "De-registering from ActivationSystem"); | |
1014 | |
1015 try { | |
1016 theActivationSystem.unregisterObject(theActivationID); | |
1017 } catch (Exception anAE) { | |
1018 theLogger.log(Level.SEVERE, "Activation unregister failed", | |
1019 anAE); | |
1020 } | |
1021 } | |
1022 | |
1023 if ((theStub != null) && (theExporter != null)) { | |
1024 theLogger.log(Level.SEVERE, "Unexport - forced"); | |
1025 theExporter.unexport(true); | |
1026 } | |
1027 | |
1028 if (theSpace != null) { | |
1029 try { | |
1030 theLogger.log(Level.SEVERE, "Stopping space"); | |
1031 theSpace.stop(); | |
1032 } catch (Exception anE) { | |
1033 theLogger.log(Level.SEVERE, "Space failed to shutdown cleanly", | |
1034 anE); | |
1035 } | |
1036 } | |
1037 | |
1038 if (theActivationID != null) { | |
1039 theLogger.log(Level.SEVERE, "Notifying ActivationGroup"); | |
1040 | |
1041 try { | |
1042 Activatable.inactive(theActivationID); | |
1043 } catch (Exception anE) { | |
1044 theLogger.log(Level.SEVERE, "ActivationGroup complained", | |
1045 anE); | |
1046 } | |
1047 } | |
1048 | |
1049 if (theLifecycle != null) { | |
1050 theLogger.log(Level.SEVERE, "Lifecycle::unregister"); | |
1051 theLifecycle.unregister(theServiceImpl); | |
1052 } | |
1053 | |
1054 if (theLoginContext != null) { | |
1055 try { | |
1056 theLogger.log(Level.SEVERE, "Logout"); | |
1057 theLoginContext.logout(); | |
1058 } catch (LoginException aLE) { | |
1059 theLogger.log(Level.SEVERE, "Couldn't logout", aLE); | |
1060 } | |
1061 } | |
1062 | |
1063 theLogger.log(Level.SEVERE, "Shutdown complete"); | |
1064 | |
1065 /* | |
1066 Check config and optionally invoke Disk::clear on | |
1067 appropriate directories | |
1068 */ | |
1069 if (doClean) { | |
1070 StoragePersonality myPersonality = | |
1071 StoragePersonalityFactory.getPersonality(); | |
1072 | |
1073 /* | |
1074 It's possible that config is broken and thus we are | |
1075 performing destroy. If config *is* broken, we may not | |
1076 be able to create a personality..... | |
1077 */ | |
1078 if (myPersonality != null) { | |
1079 theLogger.log(Level.SEVERE, "Erasing disk state"); | |
1080 | |
1081 myPersonality.destroy(); | |
1082 } | |
1083 } | |
1084 } | |
1085 } | |
1086 | |
1087 /* ********************************************************************* | |
1088 * StatsAdmin | |
1089 ******************************************************************** */ | |
1090 | |
1091 public Stat[] getStats() throws RemoteException { | |
1092 stopBarrier(); | |
1093 | |
1094 return StatsBoard.get().getStats(); | |
1095 } | |
1096 | |
1097 public void setSwitches(Switch[] aListOfSwitches) throws RemoteException { | |
1098 stopBarrier(); | |
1099 | |
1100 SwitchSettings.get().update(aListOfSwitches); | |
1101 } | |
1102 | |
1103 /* ********************************************************************* | |
1104 * EntryViewAdmin | |
1105 ******************************************************************** */ | |
1106 public JavaSpace getJavaSpaceProxy() throws RemoteException { | |
1107 return theSpaceProxy; | |
1108 } | |
1109 | |
1110 public ViewResult newView(MangledEntry[] aTemplates, Transaction aTxn, | |
1111 long aLeaseDuration, boolean isJavaSpace05, | |
1112 long aLimit, int anInitialChunk) | |
1113 throws RemoteException, TransactionException { | |
1114 | |
1115 stopBarrier(); | |
1116 | |
1117 try { | |
1118 long myDuration = aLeaseDuration; | |
1119 | |
1120 /* | |
1121 Bound the lease if we're instructed to do so - we may not | |
1122 be required to if this is an emulation of the old | |
1123 JavaSpaceAdmin::contents call | |
1124 */ | |
1125 if (isJavaSpace05) | |
1126 myDuration = LeaseBounds.boundView(aLeaseDuration); | |
1127 | |
1128 /* | |
1129 * JavaSpace05 holds locks only for a non-null transaction. | |
1130 * JavaSpaceAdmin never holds locks but uses the transaction to | |
1131 * test visibility | |
1132 */ | |
1133 boolean holdLocks = | |
1134 (isJavaSpace05) ? (aTxn != null) : false; | |
1135 | |
1136 /* | |
1137 If we're being asked to do JavaSpace05, we're performing the new contents | |
1138 operation which means we should pass true for holdlocks, false otherwise | |
1139 */ | |
1140 ViewRegistration myReg = | |
1141 EntryViewFactory.get().newView(aTemplates, aTxn, holdLocks, | |
1142 myDuration, aLimit, theSpace); | |
1143 | |
1144 /* | |
1145 Okay, got a view, now we need an initial batch | |
1146 */ | |
1147 EntryChit[] myInitialBatch = getNext(myReg.getUID(), anInitialChunk); | |
1148 | |
1149 return new ViewResult( | |
1150 ProxyFactory.newLeaseImpl(theStub, theLookupStore.getUuid(), | |
1151 myReg.getUID(), | |
1152 myReg.getExpiry()), | |
1153 myInitialBatch); | |
1154 } catch (IOException anIOE) { | |
1155 throw new RemoteException("Failed to create view", anIOE); | |
1156 } | |
1157 } | |
1158 | |
1159 public EntryChit[] getNext(EntryViewUID aUid, int aChunkSize) | |
1160 throws RemoteException { | |
1161 | |
1162 stopBarrier(); | |
1163 | |
1164 ArrayList myNext = new ArrayList(); | |
1165 | |
1166 EntryView myView = EntryViewFactory.get().getView(aUid); | |
1167 | |
1168 /* | |
1169 View could have expired or been otherwise lost | |
1170 */ | |
1171 if (myView == null) | |
1172 throw new NoSuchObjectException("View has been lost"); | |
1173 | |
1174 try { | |
1175 for (int i = 0; i < aChunkSize; i++) { | |
1176 EntryChit myChit = myView.next(); | |
1177 | |
1178 if (myChit == null) | |
1179 break; | |
1180 else | |
1181 myNext.add(myChit); | |
1182 } | |
1183 } catch (TransactionException aTE) { | |
1184 throw new RemoteException("View was prematurely destroyed - was a transaction ended?", aTE); | |
1185 } catch (IOException anIOE) { | |
1186 throw new RemoteException("Couldn't recover an Entry", anIOE); | |
1187 } | |
1188 | |
1189 if (myNext.size() == 0) | |
1190 return null; | |
1191 | |
1192 EntryChit[] myChits = new EntryChit[myNext.size()]; | |
1193 myChits = (EntryChit[]) myNext.toArray(myChits); | |
1194 | |
1195 return myChits; | |
1196 } | |
1197 | |
1198 /** | |
1199 Deletes a specific entity returned from an | |
1200 <code>EntryView</code> via an <code>EntryChit</code> | |
1201 */ | |
1202 public void delete(Object aCookie) throws RemoteException { | |
1203 stopBarrier(); | |
1204 | |
1205 try { | |
1206 theSpace.getLeaseControl().cancel((SpaceUID) aCookie); | |
1207 } catch (IOException anIOE) { | |
1208 theLogger.log(Level.SEVERE, "Space has disk problems", anIOE); | |
1209 throw new RemoteException("Space has disk problems", anIOE); | |
1210 } catch (UnknownLeaseException aULE) { | |
1211 // It's gone already, fail silently | |
1212 } | |
1213 } | |
1214 | |
1215 public void close(EntryViewUID aUid) throws RemoteException { | |
1216 stopBarrier(); | |
1217 | |
1218 EntryViewFactory.get().delete(aUid); | |
1219 } | |
1220 | |
1221 /* ********************************************************************* | |
1222 * JavaSpace05 | |
1223 ******************************************************************** */ | |
1224 | |
1225 public List write(List aMangledEntries, Transaction aTxn, List aLeaseTimes) | |
1226 throws RemoteException, TransactionException { | |
1227 | |
1228 stopBarrier(); | |
1229 | |
1230 try { | |
1231 List myTickets = theSpace.write(aMangledEntries, aTxn, aLeaseTimes); | |
1232 | |
1233 for (int i = 0; i < myTickets.size(); i++) { | |
1234 WriteTicket myTicket = (WriteTicket) myTickets.get(i); | |
1235 | |
1236 Lease myLease = | |
1237 ProxyFactory.newEntryLeaseImpl(theStub, theLookupStore.getUuid(), | |
1238 myTicket.getUID(), | |
1239 myTicket.getExpirationTime()); | |
1240 | |
1241 myTickets.set(i, myLease); | |
1242 } | |
1243 | |
1244 return myTickets; | |
1245 } catch (IOException anIOE) { | |
1246 theLogger.log(Level.SEVERE, "SpaceImpl has disk problems", anIOE); | |
1247 throw new RemoteException("Space has disk problems", anIOE); | |
1248 } | |
1249 } | |
1250 | |
1251 public List take(MangledEntry[] aTemplates, Transaction aTxn, | |
1252 long aWaitTime, long aLimit) | |
1253 throws RemoteException, TransactionException { | |
1254 | |
1255 stopBarrier(); | |
1256 | |
1257 try { | |
1258 return theSpace.take(aTemplates, aTxn, aWaitTime, aLimit); | |
1259 } catch (IOException anIOE) { | |
1260 theLogger.log(Level.SEVERE, "SpaceImpl has disk problems", anIOE); | |
1261 throw new RemoteException("Space has disk problems", anIOE); | |
1262 } | |
1263 } | |
1264 | |
1265 public EventRegistration | |
1266 registerForVisibility(MangledEntry[] aTemplates, Transaction aTxn, | |
1267 RemoteEventListener aListener, long aLeaseTime, | |
1268 MarshalledObject aHandback, | |
1269 boolean visibilityOnly) | |
1270 throws RemoteException, TransactionException { | |
1271 | |
1272 stopBarrier(); | |
1273 | |
1274 try { | |
1275 RegTicket myTicket = | |
1276 theSpace.visibility(aTemplates, aTxn, aListener, aLeaseTime, | |
1277 aHandback, visibilityOnly); | |
1278 | |
1279 LeaseImpl myLease = | |
1280 ProxyFactory.newLeaseImpl(theStub, theLookupStore.getUuid(), | |
1281 myTicket.getUID(), | |
1282 myTicket.getExpirationTime()); | |
1283 | |
1284 return new EventRegistration(myTicket.getSourceId(), theSpaceProxy, | |
1285 myLease, myTicket.getSeqNum()); | |
1286 } catch (IOException anIOE) { | |
1287 theLogger.log(Level.SEVERE, "SpaceImpl has disk problems", anIOE); | |
1288 throw new RemoteException("Space has disk problems", anIOE); | |
1289 } | |
1290 } | |
1291 | |
1292 /* ********************************************************************* | |
1293 * BlitzAdmin | |
1294 ******************************************************************** */ | |
1295 public void requestSnapshot() throws RemoteException, | |
1296 TransactionException, IOException { | |
1297 stopBarrier(); | |
1298 theSpace.getTxnControl().requestSnapshot(); | |
1299 } | |
1300 | |
1301 public void shutdown() throws RemoteException { | |
1302 // stopBarrier is donw in destroyImpl | |
1303 destroyImpl(false); | |
1304 } | |
1305 | |
1306 public void backup(String aDir) throws RemoteException, IOException { | |
1307 stopBarrier(); | |
1308 theSpace.getTxnControl().backup(aDir); | |
1309 } | |
1310 | |
1311 public void clean() throws RemoteException, IOException { | |
1312 stopBarrier(); | |
1313 | |
1314 blockCalls(); | |
1315 | |
1316 try { | |
1317 theSpace.empty(); | |
1318 } finally { | |
1319 unblockCalls(); | |
1320 } | |
1321 } | |
1322 | |
1323 public void reap() throws RemoteException { | |
1324 theSpace.reap(); | |
1325 } | |
1326 } |