public Void call() throws Exception { final GangliaSender tmp = gangliaSender; if (gangliaSender != null) { if (msg.isMetricMetadata()) { messageEncoder.writeMetadata(tmp.xdr, (IGangliaMetadataMessage) msg); } else if (msg.isMetricRequest()) { messageEncoder.writeRequest(tmp.xdr, (IGangliaRequestMessage) msg); } else if (msg.isMetricValue()) { messageEncoder.writeMetric( tmp.xdr, ((RichMetricMessage) msg).getMetadata(), (IGangliaMetricMessage) msg); } else { throw new AssertionError(); } tmp.sendMessage(tmp.xdr); } return (Void) null; }
@Override public void accept(final IGangliaMessage msg) { if (msg == null) return; /* * true iff the message is from this host. * * Note: A message from this host could be from either an embedded * ganglia service (such as ourselves) or from gmond or even gmetad * (if we are running on the same host as gmetad). * * It is Ok to accept metric value updates from ourselves, and this * makes it possible to listen to a gmond instance on the same host. * However, the receipt of a metric value MUST NOT cause us to send * out a new metric value record. */ if (msg.isMetricRequest()) { /* * Metadata request. */ if (isQuietPeriod()) { /* * Ignore requests during the quiet period. * * TODO Review the quite period behavior. Is this correct? */ return; } /* * Lookup the metric value for *this* host. */ final TimestampMetricValue tmv = gangliaState.getMetric(hostName, msg.getMetricName()); if (tmv != null && tmv.getTimestamp() != 0L) { /* * If the requested metric is known on this host then we * reset it now. The next time we sample that metric it will * have a timestamp of ZERO (0) and will be sent out to all * listeners. Since the timestamp is ZERO (0) (rather than a * valid timestamp at which the metric was last sent), the * metadata record will also be sent out. */ tmv.resetTimestamp(); if (log.isInfoEnabled()) log.info("Reset metric timestamp: " + msg.toString()); } } else if (msg.isMetricMetadata()) { /* * Handle metadata message. * * TODO Allow a pattern for metrics that we will accept. Do not * store the declaration unless it satisfies that pattern. */ if (gangliaState.putIfAbsent((IGangliaMetadataMessage) msg) == null) { if (log.isInfoEnabled()) log.info("declared by host: " + msg.toString()); } } else if (msg.isMetricValue()) { /* * TODO Allow a pattern for metrics that we will accept. Do not * store the declaration unless it satisfies that pattern. */ if (gangliaState.getMetadata(msg.getMetricName()) == null) { /* * Request the metadata for the metric. * * Note: We will not accept the metric record into our * internal state until we have received a metadata record * for that metric. */ if (log.isDebugEnabled()) log.debug("No metadata for metric: " + msg.getMetricName()); sendMessage(new GangliaRequestMessage(hostName, msg.getMetricName(), false /* spoof */)); return; } /* * Update the counters for the appropriate host. * * Note: At this point we have verified that we have a metadata * declaration on hand for this metric so we can go ahead and * store the metric value in our internal state. */ final IGangliaMetricMessage m2 = (IGangliaMetricMessage) msg; final TimestampMetricValue tmv = gangliaState.getMetric(msg.getHostName(), msg.getMetricName()); // Guaranteed non-null since metadata decl exists for metric. assert tmv != null; /* * Update the value. * * Note: The return value is ignored. Since the metric was * received over the wire we ignore the age of the metric rather * than using the metric age to trigger a send of the metric * value. (I.e., avoid re-sending received metrics.) */ tmv.setValue(m2.getValue()); if (log.isDebugEnabled()) log.debug("Updated value: " + msg); } else { log.error("Unknown message type: " + msg); } }