protected void await(boolean throwInterrupt) throws InterruptedException { if (!signaled.get()) { lock.acquired = false; sendAwaitConditionRequest(lock.name, lock.owner); boolean interrupted = false; while (!signaled.get()) { parker.set(Thread.currentThread()); LockSupport.park(this); if (Thread.interrupted()) { // If we were interrupted and haven't received a response yet then we try to // clean up the lock request and throw the exception if (!signaled.get()) { sendDeleteAwaitConditionRequest(lock.name, lock.owner); throw new InterruptedException(); } // In the case that we were signaled and interrupted // we want to return the signal but still interrupt // our thread interrupted = true; } } if (interrupted) Thread.currentThread().interrupt(); } // We set as if this signal was no released. This way if the // condition is reused again, but the client condition isn't lost // we won't think we were signaled immediately signaled.set(false); }
public void receive(Message msg) { if (!msg.isFlagSet(Message.OOB)) { try { System.out.println(Thread.currentThread() + ": waiting on latch"); latch.await(25000, TimeUnit.MILLISECONDS); System.out.println(Thread.currentThread() + ": DONE waiting on latch"); } catch (InterruptedException e) { e.printStackTrace(); } } msgs.add((Integer) msg.getObject()); }
private void send(Address dest) throws Exception { final CountDownLatch latch = new CountDownLatch(1); final BlockingReceiver receiver = new BlockingReceiver(latch); final int NUM = 10; b.setReceiver(receiver); a.send(dest, 1); // the only regular message for (int i = 2; i <= NUM; i++) a.send(new Message(dest, i).setFlag(Message.Flag.OOB)); sendStableMessages(a, b); List<Integer> list = receiver.getMsgs(); for (int i = 0; i < 20; i++) { if (list.size() == NUM - 1) break; sendStableMessages(a, b); Util.sleep(500); // give the asynchronous msgs some time to be received } System.out.println("list = " + list); assert list.size() == NUM - 1 : "list is " + list; assert list.contains(2) && list.contains(10); System.out.println("[" + Thread.currentThread().getName() + "]: releasing latch"); latch.countDown(); for (int i = 0; i < 20; i++) { if (list.size() == NUM) break; sendStableMessages(a, b); Util.sleep(1000); // give the asynchronous msgs some time to be received } System.out.println("list = " + list); assert list.size() == NUM : "list is " + list; for (int i = 1; i <= NUM; i++) assert list.contains(i); }
protected synchronized void acquire(boolean throwInterrupt) throws InterruptedException { if (!acquired) { owner = getOwner(); sendGrantLockRequest(name, owner, 0, false); boolean interrupted = false; while (!acquired) { try { this.wait(); } catch (InterruptedException e) { // If we haven't acquired the lock yet and were interrupted, then we have to clean up // the lock // request and throw the exception if (throwInterrupt && !acquired) { _unlock(true); throw e; } // If we did get the lock then we will return with the lock and interrupt status. // If we don't throw exceptions then we just set the interrupt flag and let it loop // around interrupted = true; } } if (interrupted) Thread.currentThread().interrupt(); } }
protected long await(long nanoSeconds) throws InterruptedException { long target_nano = System.nanoTime() + nanoSeconds; if (!signaled.get()) { // We release the lock at the same time as waiting on the // condition lock.acquired = false; sendAwaitConditionRequest(lock.name, lock.owner); boolean interrupted = false; while (!signaled.get()) { long wait_nano = target_nano - System.nanoTime(); // If we waited max time break out if (wait_nano > 0) { parker.set(Thread.currentThread()); LockSupport.parkNanos(this, wait_nano); if (Thread.interrupted()) { // If we were interrupted and haven't received a response yet then we try to // clean up the lock request and throw the exception if (!signaled.get()) { sendDeleteAwaitConditionRequest(lock.name, lock.owner); throw new InterruptedException(); } // In the case that we were signaled and interrupted // we want to return the signal but still interrupt // our thread interrupted = true; } } else { break; } } if (interrupted) Thread.currentThread().interrupt(); } // We set as if this signal was no released. This way if the // condition is reused again, but the client condition isn't lost // we won't think we were signaled immediately // If we weren't signaled then delete our request if (!signaled.getAndSet(false)) { sendDeleteAwaitConditionRequest(lock.name, lock.owner); } return target_nano - System.nanoTime(); }
private void send(Address dest) throws ChannelNotConnectedException, ChannelClosedException { final ReentrantLock lock = new ReentrantLock(); final BlockingReceiver receiver = new BlockingReceiver(lock); final int NUM = 10; c2.setReceiver(receiver); System.out.println("[" + Thread.currentThread().getName() + "]: locking lock"); lock.lock(); c1.send(new Message(dest, null, 1)); for (int i = 2; i <= NUM; i++) { Message msg = new Message(dest, null, i); msg.setFlag(Message.OOB); c1.send(msg); } sendStableMessages(c1, c2); Util.sleep(500); List<Integer> list = receiver.getMsgs(); for (int i = 0; i < 20; i++) { if (list.size() == NUM - 1) break; System.out.println("list = " + list); Util.sleep(1000); // give the asynchronous msgs some time to be received } System.out.println("list = " + list); assert list.size() == NUM - 1 : "list is " + list; assert list.contains(2) && list.contains(10); System.out.println("[" + Thread.currentThread().getName() + "]: unlocking lock"); lock.unlock(); for (int i = 0; i < 20; i++) { if (list.size() == NUM) break; System.out.println("list = " + list); Util.sleep(1000); // give the asynchronous msgs some time to be received } System.out.println("list = " + list); assert list.size() == NUM : "list is " + list; for (int i = 1; i <= NUM; i++) assert list.contains(i); }
synchronized void waitUntilCompleted(long timeout, boolean resume) { if (thread != null) { try { thread.join(timeout); } catch (InterruptedException e) { Thread.currentThread().interrupt(); // set interrupt flag again } thread = null; // Added after Brian noticed that ViewHandler leaks class loaders } if (resume) resumeForce(); }
protected void handleTaskSubmittedRequest( Runnable runnable, Address source, long requestId, long threadId) { // We store in our map so that when that task is // finished so that we can send back to the owner // with the results _running.put(runnable, new Owner(source, requestId)); // We give the task to the thread that is now waiting for it to be returned // If we can't offer then we have to respond back to // caller that we can't handle it. They must have // gotten our address when we had a consumer, but // they went away between then and now. boolean received; try { _tasks.put(threadId, runnable); CyclicBarrier barrier = _taskBarriers.remove(threadId); if (received = (barrier != null)) { // Only wait 10 milliseconds, in case if the consumer was // stopped between when we were told it was available and now barrier.await(10, TimeUnit.MILLISECONDS); } } catch (InterruptedException e) { if (log.isDebugEnabled()) log.debug("Interrupted while handing off task"); Thread.currentThread().interrupt(); received = false; } catch (BrokenBarrierException e) { if (log.isDebugEnabled()) log.debug( "Consumer " + threadId + " has been interrupted, " + "must retry to submit elsewhere"); received = false; } catch (TimeoutException e) { if (log.isDebugEnabled()) log.debug("Timeout waiting to hand off to barrier, consumer " + threadId + " must be slow"); // This should only happen if the consumer put the latch then got // interrupted but hadn't yet removed the latch, should almost never // happen received = false; } if (!received) { // Clean up the tasks request _tasks.remove(threadId); if (log.isDebugEnabled()) log.debug("Run rejected not able to pass off to consumer"); // If we couldn't hand off the task we have to tell the client // and also reupdate the coordinator that our consumer is ready sendRequest(source, Type.RUN_REJECTED, requestId, null); _running.remove(runnable); } }
protected synchronized boolean acquireTryLock(long timeout, boolean use_timeout) throws InterruptedException { if (denied) return false; if (!acquired) { is_trylock = true; this.timeout = timeout; if (owner == null) owner = getOwner(); sendGrantLockRequest(name, owner, timeout, true); long target_time = use_timeout ? System.currentTimeMillis() + timeout : 0; boolean interrupted = false; while (!acquired && !denied) { if (use_timeout) { long wait_time = target_time - System.currentTimeMillis(); if (wait_time <= 0) break; else { this.timeout = wait_time; try { this.wait(wait_time); } catch (InterruptedException e) { // If we were interrupted and haven't received a response yet then we try to // clean up the lock request and throw the exception if (!acquired && !denied) { _unlock(true); throw e; } // In the case that we were told if we acquired or denied the lock then return that, // but // make sure we set the interrupt status interrupted = true; } } } else { try { this.wait(); } catch (InterruptedException e) { interrupted = true; } } } if (interrupted) Thread.currentThread().interrupt(); } if (!acquired || denied) _unlock(true); return acquired && !denied; }
/** * Initialisation if a supplied key is defined in the properties. This supplied key must be in a * keystore which can be generated using the keystoreGenerator file in demos. The keystore must be * on the classpath to find it. * * @throws KeyStoreException * @throws Exception * @throws IOException * @throws NoSuchAlgorithmException * @throws CertificateException * @throws UnrecoverableKeyException */ private void initConfiguredKey() throws Exception { InputStream inputStream = null; // must not use default keystore type - as does not support secret keys KeyStore store = KeyStore.getInstance("JCEKS"); SecretKey tempKey = null; try { // load in keystore using this thread's classloader inputStream = Thread.currentThread().getContextClassLoader().getResourceAsStream(keyStoreName); if (inputStream == null) inputStream = new FileInputStream(keyStoreName); // we can't find a keystore here - if (inputStream == null) { throw new Exception( "Unable to load keystore " + keyStoreName + " ensure file is on classpath"); } // we have located a file lets load the keystore try { store.load(inputStream, storePassword.toCharArray()); // loaded keystore - get the key tempKey = (SecretKey) store.getKey(alias, keyPassword.toCharArray()); } catch (IOException e) { throw new Exception("Unable to load keystore " + keyStoreName + ": " + e); } catch (NoSuchAlgorithmException e) { throw new Exception("No Such algorithm " + keyStoreName + ": " + e); } catch (CertificateException e) { throw new Exception("Certificate exception " + keyStoreName + ": " + e); } if (tempKey == null) throw new Exception("Unable to retrieve key '" + alias + "' from keystore " + keyStoreName); // set the key here setSecretKey(tempKey); if (symAlgorithm.equals(DEFAULT_SYM_ALGO)) symAlgorithm = tempKey.getAlgorithm(); // set the fact we are using a supplied key suppliedKey = true; queue_down = queue_up = false; } finally { Util.close(inputStream); } }
public void run() { long end_time, wait_time; List<Request> requests = new LinkedList<Request>(); while (Thread.currentThread().equals(thread) && !suspended) { try { boolean keepGoing = false; end_time = System.currentTimeMillis() + max_bundling_time; do { Request firstRequest = (Request) queue.remove(INTERVAL); // throws a TimeoutException if it runs into timeout requests.add(firstRequest); if (!view_bundling) break; if (queue.size() > 0) { Request nextReq = (Request) queue.peek(); keepGoing = view_bundling && firstRequest.canBeProcessedTogether(nextReq); } else { wait_time = end_time - System.currentTimeMillis(); if (wait_time > 0) queue.waitUntilClosed( wait_time); // misnomer: waits until element has been added or q closed keepGoing = queue.size() > 0 && firstRequest.canBeProcessedTogether((Request) queue.peek()); } } while (keepGoing && System.currentTimeMillis() < end_time); try { process(requests); } finally { requests.clear(); } } catch (QueueClosedException e) { break; } catch (TimeoutException e) { break; } catch (Throwable catchall) { Util.sleep(50); } } }
public Object down(Event evt) { switch (evt.getType()) { case ExecutorEvent.TASK_SUBMIT: Runnable runnable = evt.getArg(); // We are limited to a number of concurrent request id's // equal to 2^63-1. This is quite large and if it // overflows it will still be positive long requestId = Math.abs(counter.getAndIncrement()); if (requestId == Long.MIN_VALUE) { // TODO: need to fix this it isn't safe for concurrent modifications counter.set(0); requestId = Math.abs(counter.getAndIncrement()); } // Need to make sure to put the requestId in our map before // adding the runnable to awaiting consumer in case if // coordinator sent a consumer found and their original task // is no longer around // see https://issues.jboss.org/browse/JGRP-1744 _requestId.put(runnable, requestId); _awaitingConsumer.add(runnable); sendToCoordinator(RUN_REQUEST, requestId, local_addr); break; case ExecutorEvent.CONSUMER_READY: Thread currentThread = Thread.currentThread(); long threadId = currentThread.getId(); _consumerId.put(threadId, PRESENT); try { for (; ; ) { CyclicBarrier barrier = new CyclicBarrier(2); _taskBarriers.put(threadId, barrier); // We only send to the coordinator that we are ready after // making the barrier, wait for request to come and let // us free sendToCoordinator(Type.CONSUMER_READY, threadId, local_addr); try { barrier.await(); break; } catch (BrokenBarrierException e) { if (log.isDebugEnabled()) log.debug( "Producer timed out before we picked up" + " the task, have to tell coordinator" + " we are still good."); } } // This should always be non nullable since the latch // was freed runnable = _tasks.remove(threadId); _runnableThreads.put(runnable, currentThread); return runnable; } catch (InterruptedException e) { if (log.isDebugEnabled()) log.debug("Consumer " + threadId + " stopped via interrupt"); sendToCoordinator(Type.CONSUMER_UNREADY, threadId, local_addr); Thread.currentThread().interrupt(); } finally { // Make sure the barriers are cleaned up as well _taskBarriers.remove(threadId); _consumerId.remove(threadId); } break; case ExecutorEvent.TASK_COMPLETE: Object arg = evt.getArg(); Throwable throwable = null; if (arg instanceof Object[]) { Object[] array = (Object[]) arg; runnable = (Runnable) array[0]; throwable = (Throwable) array[1]; } else { runnable = (Runnable) arg; } Owner owner = _running.remove(runnable); // This won't remove anything if owner doesn't come back _runnableThreads.remove(runnable); Object value = null; boolean exception = false; if (throwable != null) { // InterruptedException is special telling us that // we interrupted the thread while waiting but still got // a task therefore we have to reject it. if (throwable instanceof InterruptedException) { if (log.isDebugEnabled()) log.debug("Run rejected due to interrupted exception returned"); sendRequest(owner.address, Type.RUN_REJECTED, owner.requestId, null); break; } value = throwable; exception = true; } else if (runnable instanceof RunnableFuture<?>) { RunnableFuture<?> future = (RunnableFuture<?>) runnable; boolean interrupted = false; boolean gotValue = false; // We have the value, before we interrupt at least get it! while (!gotValue) { try { value = future.get(); gotValue = true; } catch (InterruptedException e) { interrupted = true; } catch (ExecutionException e) { value = e.getCause(); exception = true; gotValue = true; } } if (interrupted) { Thread.currentThread().interrupt(); } } if (owner != null) { final Type type; final Object valueToSend; if (value == null) { type = Type.RESULT_SUCCESS; valueToSend = value; } // Both serializable values and exceptions would go in here else if (value instanceof Serializable || value instanceof Externalizable || value instanceof Streamable) { type = exception ? Type.RESULT_EXCEPTION : Type.RESULT_SUCCESS; valueToSend = value; } // This would happen if the value wasn't serializable, // so we have to send back to the client that the class // wasn't serializable else { type = Type.RESULT_EXCEPTION; valueToSend = new NotSerializableException(value.getClass().getName()); } if (local_addr.equals(owner.getAddress())) { if (log.isTraceEnabled()) log.trace( "[redirect] <--> [" + local_addr + "] " + type.name() + " [" + value + (owner.requestId != -1 ? " request id: " + owner.requestId : "") + "]"); if (type == Type.RESULT_SUCCESS) { handleValueResponse(local_addr, owner.requestId, valueToSend); } else if (type == Type.RESULT_EXCEPTION) { handleExceptionResponse(local_addr, owner.requestId, (Throwable) valueToSend); } } else { sendRequest(owner.getAddress(), type, owner.requestId, valueToSend); } } else { if (log.isTraceEnabled()) { log.trace("Could not return result - most likely because it was interrupted"); } } break; case ExecutorEvent.TASK_CANCEL: Object[] array = evt.getArg(); runnable = (Runnable) array[0]; if (_awaitingConsumer.remove(runnable)) { _requestId.remove(runnable); ExecutorNotification notification = notifiers.remove(runnable); if (notification != null) { notification.interrupted(runnable); } if (log.isTraceEnabled()) log.trace("Cancelled task " + runnable + " before it was picked up"); return Boolean.TRUE; } // This is guaranteed to not be null so don't take cost of auto unboxing else if (array[1] == Boolean.TRUE) { owner = removeKeyForValue(_awaitingReturn, runnable); if (owner != null) { Long requestIdValue = _requestId.remove(runnable); // We only cancel if the requestId is still available // this means the result hasn't been returned yet and // we still have a chance to interrupt if (requestIdValue != null) { if (requestIdValue != owner.getRequestId()) { log.warn("Cancelling requestId didn't match waiting"); } sendRequest(owner.getAddress(), Type.INTERRUPT_RUN, owner.getRequestId(), null); } } else { if (log.isTraceEnabled()) log.warn("Couldn't interrupt server task: " + runnable); } ExecutorNotification notification = notifiers.remove(runnable); if (notification != null) { notification.interrupted(runnable); } return Boolean.TRUE; } else { return Boolean.FALSE; } case ExecutorEvent.ALL_TASK_CANCEL: array = evt.getArg(); // This is a RunnableFuture<?> so this cast is okay @SuppressWarnings("unchecked") Set<Runnable> runnables = (Set<Runnable>) array[0]; Boolean booleanValue = (Boolean) array[1]; List<Runnable> notRan = new ArrayList<>(); for (Runnable cancelRunnable : runnables) { // Removed from the consumer if (!_awaitingConsumer.remove(cancelRunnable) && booleanValue == Boolean.TRUE) { synchronized (_awaitingReturn) { owner = removeKeyForValue(_awaitingReturn, cancelRunnable); if (owner != null) { Long requestIdValue = _requestId.remove(cancelRunnable); if (requestIdValue != owner.getRequestId()) { log.warn("Cancelling requestId didn't match waiting"); } sendRequest(owner.getAddress(), Type.INTERRUPT_RUN, owner.getRequestId(), null); } ExecutorNotification notification = notifiers.remove(cancelRunnable); if (notification != null) { log.trace("Notifying listener"); notification.interrupted(cancelRunnable); } } } else { _requestId.remove(cancelRunnable); notRan.add(cancelRunnable); } } return notRan; case Event.SET_LOCAL_ADDRESS: local_addr = evt.getArg(); break; case Event.VIEW_CHANGE: handleView(evt.getArg()); break; } return down_prot.down(evt); }
/** * An event was received from the layer below. Usually the current layer will want to examine the * event type and - depending on its type - perform some computation (e.g. removing headers from a * MSG event type, or updating the internal membership list when receiving a VIEW_CHANGE event). * Finally the event is either a) discarded, or b) an event is sent down the stack using <code> * PassDown</code> or c) the event (or another event) is sent up the stack using <code>PassUp * </code>. * * <p>For the PING protocol, the Up operation does the following things. 1. If the event is a * Event.MSG then PING will inspect the message header. If the header is null, PING simply passes * up the event If the header is PingHeader.GET_MBRS_REQ then the PING protocol will PassDown a * PingRequest message If the header is PingHeader.GET_MBRS_RSP we will add the message to the * initial members vector and wake up any waiting threads. 2. If the event is Event.SET_LOCAL_ADDR * we will simple set the local address of this protocol 3. For all other messages we simple pass * it up to the protocol above * * @param evt - the event that has been sent from the layer below */ @SuppressWarnings("unchecked") public Object up(Event evt) { switch (evt.getType()) { case Event.MSG: Message msg = (Message) evt.getArg(); PingHeader hdr = (PingHeader) msg.getHeader(this.id); if (hdr == null) return up_prot.up(evt); PingData data = hdr.data; Address logical_addr = data != null ? data.getAddress() : null; if (is_leaving) return null; // prevents merging back a leaving member // (https://issues.jboss.org/browse/JGRP-1336) switch (hdr.type) { case PingHeader.GET_MBRS_REQ: // return Rsp(local_addr, coord) if (group_addr == null || hdr.cluster_name == null) { if (log.isWarnEnabled()) log.warn( "group_addr (" + group_addr + ") or cluster_name of header (" + hdr.cluster_name + ") is null; passing up discovery request from " + msg.getSrc() + ", but this should not" + " be the case"); } else { if (!group_addr.equals(hdr.cluster_name)) { if (log.isWarnEnabled()) log.warn( "discarding discovery request for cluster '" + hdr.cluster_name + "' from " + msg.getSrc() + "; our cluster name is '" + group_addr + "'. " + "Please separate your clusters cleanly."); return null; } } // add physical address and logical name of the discovery sender (if available) to the // cache if (data != null) { if (logical_addr == null) logical_addr = msg.getSrc(); Collection<PhysicalAddress> physical_addrs = data.getPhysicalAddrs(); PhysicalAddress physical_addr = physical_addrs != null && !physical_addrs.isEmpty() ? physical_addrs.iterator().next() : null; if (logical_addr != null && physical_addr != null) down( new Event( Event.SET_PHYSICAL_ADDRESS, new Tuple<Address, PhysicalAddress>(logical_addr, physical_addr))); if (logical_addr != null && data.getLogicalName() != null) UUID.add(logical_addr, data.getLogicalName()); discoveryRequestReceived(msg.getSrc(), data.getLogicalName(), physical_addrs); synchronized (ping_responses) { for (Responses response : ping_responses) { response.addResponse(data, false); } } } if (hdr.view_id != null) { // If the discovery request is merge-triggered, and the ViewId shipped with it // is the same as ours, we don't respond (JGRP-1315). ViewId my_view_id = view != null ? view.getViewId() : null; if (my_view_id != null && my_view_id.equals(hdr.view_id)) return null; boolean send_discovery_rsp = force_sending_discovery_rsps || is_coord || current_coord == null || current_coord.equals(msg.getSrc()); if (!send_discovery_rsp) { if (log.isTraceEnabled()) log.trace( local_addr + ": suppressing merge response as I'm not a coordinator and the " + "discovery request was not sent by a coordinator"); return null; } } if (isMergeRunning()) { if (log.isTraceEnabled()) log.trace( local_addr + ": suppressing merge response as a merge is already in progress"); return null; } List<PhysicalAddress> physical_addrs = hdr.view_id != null ? null : Arrays.asList( (PhysicalAddress) down(new Event(Event.GET_PHYSICAL_ADDRESS, local_addr))); sendDiscoveryResponse( local_addr, physical_addrs, is_server, hdr.view_id != null, UUID.get(local_addr), msg.getSrc()); return null; case PingHeader.GET_MBRS_RSP: // add response to vector and notify waiting thread // add physical address (if available) to transport's cache if (data != null) { Address response_sender = msg.getSrc(); if (logical_addr == null) logical_addr = msg.getSrc(); Collection<PhysicalAddress> addrs = data.getPhysicalAddrs(); PhysicalAddress physical_addr = addrs != null && !addrs.isEmpty() ? addrs.iterator().next() : null; if (logical_addr != null && physical_addr != null) down( new Event( Event.SET_PHYSICAL_ADDRESS, new Tuple<Address, PhysicalAddress>(logical_addr, physical_addr))); if (logical_addr != null && data.getLogicalName() != null) UUID.add(logical_addr, data.getLogicalName()); if (log.isTraceEnabled()) log.trace( local_addr + ": received GET_MBRS_RSP from " + response_sender + ": " + data); boolean overwrite = logical_addr != null && logical_addr.equals(response_sender); synchronized (ping_responses) { for (Responses response : ping_responses) { response.addResponse(data, overwrite); } } } return null; default: if (log.isWarnEnabled()) log.warn("got PING header with unknown type (" + hdr.type + ')'); return null; } case Event.GET_PHYSICAL_ADDRESS: try { sendDiscoveryRequest(group_addr, null, null); } catch (InterruptedIOException ie) { if (log.isWarnEnabled()) { log.warn("Discovery request for cluster " + group_addr + " interrupted"); } Thread.currentThread().interrupt(); } catch (Exception ex) { if (log.isErrorEnabled()) log.error("failed sending discovery request", ex); } return null; case Event.FIND_INITIAL_MBRS: // sent by transport return findInitialMembers(null); } return up_prot.up(evt); }
protected Owner getOwner() { return new Owner(local_addr, Thread.currentThread().getId()); }
public Object down(Event evt) { switch (evt.getType()) { case Event.LOCK: LockInfo info = (LockInfo) evt.getArg(); ClientLock lock = getLock(info.getName()); if (!info.isTrylock()) { if (info.isLockInterruptibly()) { try { lock.lockInterruptibly(); } catch (InterruptedException e) { Thread.currentThread() .interrupt(); // has to be checked by caller who has to rethrow ... } } else lock.lock(); } else { if (info.isUseTimeout()) { try { return lock.tryLock(info.getTimeout(), info.getTimeUnit()); } catch (InterruptedException e) { Thread.currentThread().interrupt(); } } else { return lock.tryLock(); } } return null; case Event.UNLOCK: info = (LockInfo) evt.getArg(); lock = getLock(info.getName(), false); if (lock != null) lock.unlock(); return null; case Event.UNLOCK_ALL: unlockAll(); return null; case Event.LOCK_AWAIT: info = (LockInfo) evt.getArg(); lock = getLock(info.getName(), false); if (lock == null || !lock.acquired) { throw new IllegalMonitorStateException(); } Condition condition = lock.newCondition(); if (info.isUseTimeout()) { try { return condition.awaitNanos(info.getTimeUnit().toNanos(info.getTimeout())); } catch (InterruptedException e) { Thread.currentThread().interrupt(); } } else if (info.isLockInterruptibly()) { try { condition.await(); } catch (InterruptedException e) { Thread.currentThread().interrupt(); } } else { condition.awaitUninterruptibly(); } break; case Event.LOCK_SIGNAL: AwaitInfo awaitInfo = (AwaitInfo) evt.getArg(); lock = getLock(awaitInfo.getName(), false); if (lock == null || !lock.acquired) { throw new IllegalMonitorStateException(); } sendSignalConditionRequest(awaitInfo.getName(), awaitInfo.isAll()); break; case Event.SET_LOCAL_ADDRESS: local_addr = (Address) evt.getArg(); break; case Event.VIEW_CHANGE: handleView((View) evt.getArg()); break; } return down_prot.down(evt); }