001/**
002 * Licensed to the Apache Software Foundation (ASF) under one
003 * or more contributor license agreements.  See the NOTICE file
004 * distributed with this work for additional information
005 * regarding copyright ownership.  The ASF licenses this file
006 * to you under the Apache License, Version 2.0 (the
007 * "License"); you may not use this file except in compliance
008 * with the License.  You may obtain a copy of the License at
009 *
010 *     http://www.apache.org/licenses/LICENSE-2.0
011 *
012 * Unless required by applicable law or agreed to in writing, software
013 * distributed under the License is distributed on an "AS IS" BASIS,
014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
015 * See the License for the specific language governing permissions and
016 * limitations under the License.
017 */
018package org.apache.hadoop.metrics.spi;
019
020import java.io.IOException;
021import java.lang.reflect.InvocationHandler;
022import java.lang.reflect.Method;
023import java.lang.reflect.Proxy;
024import java.util.ArrayList;
025
026import org.apache.commons.logging.Log;
027import org.apache.commons.logging.LogFactory;
028
029import org.apache.hadoop.classification.InterfaceAudience;
030import org.apache.hadoop.classification.InterfaceStability;
031import org.apache.hadoop.metrics.ContextFactory;
032import org.apache.hadoop.metrics.MetricsContext;
033import org.apache.hadoop.metrics.MetricsRecord;
034import org.apache.hadoop.metrics.MetricsUtil;
035import org.apache.hadoop.metrics.Updater;
036
037/**
038 * @deprecated Use org.apache.hadoop.metrics2 package instead.
039 */
040@Deprecated
041@InterfaceAudience.Public
042@InterfaceStability.Evolving
043public class CompositeContext extends AbstractMetricsContext {
044
045  private static final Log LOG = LogFactory.getLog(CompositeContext.class);
046  private static final String ARITY_LABEL = "arity";
047  private static final String SUB_FMT = "%s.sub%d";
048  private final ArrayList<MetricsContext> subctxt =
049    new ArrayList<MetricsContext>();
050
051  @InterfaceAudience.Private
052  public CompositeContext() {
053  }
054
055  @Override
056  @InterfaceAudience.Private
057  public void init(String contextName, ContextFactory factory) {
058    super.init(contextName, factory);
059    int nKids;
060    try {
061      String sKids = getAttribute(ARITY_LABEL);
062      nKids = Integer.parseInt(sKids);
063    } catch (Exception e) {
064      LOG.error("Unable to initialize composite metric " + contextName +
065                ": could not init arity", e);
066      return;
067    }
068    for (int i = 0; i < nKids; ++i) {
069      MetricsContext ctxt = MetricsUtil.getContext(
070          String.format(SUB_FMT, contextName, i), contextName);
071      if (null != ctxt) {
072        subctxt.add(ctxt);
073      }
074    }
075  }
076
077  @InterfaceAudience.Private
078  @Override
079  public MetricsRecord newRecord(String recordName) {
080    return (MetricsRecord) Proxy.newProxyInstance(
081        MetricsRecord.class.getClassLoader(),
082        new Class[] { MetricsRecord.class },
083        new MetricsRecordDelegator(recordName, subctxt));
084  }
085
086  @InterfaceAudience.Private
087  @Override
088  protected void emitRecord(String contextName, String recordName,
089      OutputRecord outRec) throws IOException {
090    for (MetricsContext ctxt : subctxt) {
091      try {
092        ((AbstractMetricsContext)ctxt).emitRecord(
093          contextName, recordName, outRec);
094        if (contextName == null || recordName == null || outRec == null) {
095          throw new IOException(contextName + ":" + recordName + ":" + outRec);
096        }
097      } catch (IOException e) {
098        LOG.warn("emitRecord failed: " + ctxt.getContextName(), e);
099      }
100    }
101  }
102
103  @InterfaceAudience.Private
104  @Override
105  protected void flush() throws IOException {
106    for (MetricsContext ctxt : subctxt) {
107      try {
108        ((AbstractMetricsContext)ctxt).flush();
109      } catch (IOException e) {
110        LOG.warn("flush failed: " + ctxt.getContextName(), e);
111      }
112    }
113  }
114
115  @InterfaceAudience.Private
116  @Override
117  public void startMonitoring() throws IOException {
118    for (MetricsContext ctxt : subctxt) {
119      try {
120        ctxt.startMonitoring();
121      } catch (IOException e) {
122        LOG.warn("startMonitoring failed: " + ctxt.getContextName(), e);
123      }
124    }
125  }
126
127  @InterfaceAudience.Private
128  @Override
129  public void stopMonitoring() {
130    for (MetricsContext ctxt : subctxt) {
131      ctxt.stopMonitoring();
132    }
133  }
134
135  /**
136   * Return true if all subcontexts are monitoring.
137   */
138  @InterfaceAudience.Private
139  @Override
140  public boolean isMonitoring() {
141    boolean ret = true;
142    for (MetricsContext ctxt : subctxt) {
143      ret &= ctxt.isMonitoring();
144    }
145    return ret;
146  }
147
148  @InterfaceAudience.Private
149  @Override
150  public void close() {
151    for (MetricsContext ctxt : subctxt) {
152      ctxt.close();
153    }
154  }
155
156  @InterfaceAudience.Private
157  @Override
158  public void registerUpdater(Updater updater) {
159    for (MetricsContext ctxt : subctxt) {
160      ctxt.registerUpdater(updater);
161    }
162  }
163
164  @InterfaceAudience.Private
165  @Override
166  public void unregisterUpdater(Updater updater) {
167    for (MetricsContext ctxt : subctxt) {
168      ctxt.unregisterUpdater(updater);
169    }
170  }
171
172  private static class MetricsRecordDelegator implements InvocationHandler {
173    private static final Method m_getRecordName = initMethod();
174    private static Method initMethod() {
175      try {
176        return MetricsRecord.class.getMethod("getRecordName", new Class[0]);
177      } catch (Exception e) {
178        throw new RuntimeException("Internal error", e);
179      }
180    }
181
182    private final String recordName;
183    private final ArrayList<MetricsRecord> subrecs;
184
185    MetricsRecordDelegator(String recordName, ArrayList<MetricsContext> ctxts) {
186      this.recordName = recordName;
187      this.subrecs = new ArrayList<MetricsRecord>(ctxts.size());
188      for (MetricsContext ctxt : ctxts) {
189        subrecs.add(ctxt.createRecord(recordName));
190      }
191    }
192
193    @Override
194    public Object invoke(Object p, Method m, Object[] args) throws Throwable {
195      if (m_getRecordName.equals(m)) {
196        return recordName;
197      }
198      assert Void.TYPE.equals(m.getReturnType());
199      for (MetricsRecord rec : subrecs) {
200        m.invoke(rec, args);
201      }
202      return null;
203    }
204  }
205
206}