/** * {@inheritDoc} * * @see org.helios.apmrouter.jmx.mbeanserver.MBeanServerConnectionAdmin#onSynchronousResponse(int, * java.lang.Object) */ @Override public void onSynchronousResponse(int requestId, Object value) { SimpleLogger.debug("Response for req [", requestId, "]:[", value, "]"); synchResultMap.putIfAbsent(requestId, value); CountDownLatch latch = synchTimeoutMap.remove(requestId); if (latch != null) { latch.countDown(); SimpleLogger.debug("Counted Down Latch for req [", requestId, "]:[", value, "]"); } }
/** * {@inheritDoc} * * @see * org.helios.apmrouter.jmx.mbeanserver.MBeanServerConnectionAdmin#waitForSynchronousResponse(int, * long) */ @Override public void waitForSynchronousResponse(int requestId, long timeout) { CountDownLatch latch = new CountDownLatch(1); synchTimeoutMap.put(requestId, latch); try { SimpleLogger.debug("Waiting for response to [", requestId, "]...."); boolean timedout = latch.await(timeout, TimeUnit.MILLISECONDS); SimpleLogger.debug("Result of Waiting for response to [", requestId, "]:", timedout); } catch (InterruptedException iex) { synchResultMap.putIfAbsent( requestId, new IOException( "Thread was interrupted while waiting on Operation completion", new Throwable())); } }
/** * {@inheritDoc} * * @see java.lang.reflect.InvocationHandler#invoke(java.lang.Object, java.lang.reflect.Method, * java.lang.Object[]) */ @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { if (MBeanServerConnection.class != method.getDeclaringClass()) { return method.invoke(Modifier.isStatic(method.getModifiers()) ? null : this, args); } if (channel.getPipeline().get(getClass().getSimpleName()) == null) { throw new IOException("This MBeanServerConnection has been closed", new Throwable()); } // SimpleLogger.debug("MBeanServerConnection [", method.getName(), "] Payload Size [", // sargs.length+6+4, "]"); final int reqId = requestId.incrementAndGet(); if ("addNotificationListener".equals(method.getName()) && !method.getParameterTypes()[1].equals(ObjectName.class)) { NotificationListener listener = (NotificationListener) args[1]; args[1] = reqId; addRegisteredListener(reqId, listener); } else if ("removeNotificationListener".equals(method.getName()) && !method.getParameterTypes()[1].equals(ObjectName.class)) { removeRegisteredListener((NotificationListener) args[1]); args = new Object[0]; } byte[] sargs = getOutput(args); ChannelBuffer cb = ChannelBuffers.directBuffer(1 + domainInfoData.length + 4 + 1 + 4 + sargs.length); cb.writeByte(OpCode.JMX_REQUEST.op()); // 1 cb.writeBytes(domainInfoData); // domain data cb.writeInt(reqId); // 4 cb.writeByte(methodToKey.get(method)); // 1 cb.writeInt(sargs.length); // 4 cb.writeBytes(sargs); // sargs.length if (listener == null) { synchTimeoutMap.addListener( new TimeoutListener<Integer, CountDownLatch>() { @Override public void onTimeout(Integer key, CountDownLatch value) { if (reqId == key) { synchTimeoutMap.remove(key); synchTimeoutMap.removeListener(this); onSynchronousResponse( reqId, new IOException( "Operation timed out after [" + timeout + "] ms.", new Throwable())); } } }); } else { asynchTimeoutMap.put(reqId, listener, timeout); asynchTimeoutMap.addListener( new TimeoutListener<Integer, AsynchJMXResponseListener>() { @Override public void onTimeout(Integer key, AsynchJMXResponseListener value) { if (reqId == key) { asynchTimeoutMap.remove(key); listener.onTimeout(reqId, timeout); asynchTimeoutMap.removeListener(this); } } }); } channel .write(cb, remoteAddress) .addListener( new ChannelFutureListener() { @Override public void operationComplete(ChannelFuture future) throws Exception { if (future.isSuccess()) { SimpleLogger.debug("Sent JMX Request to [", remoteAddress, "]"); } else { SimpleLogger.error( "Failed to send JMX Request to [", remoteAddress, "]", future.getCause()); } } }); if (listener == null) { waitForSynchronousResponse(reqId, timeout); Object result = synchResultMap.get(reqId); if (result != null && result instanceof Throwable) { throw (Throwable) result; } return result; } return null; }