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  @InterfaceAudience.Private
056  public void init(String contextName, ContextFactory factory) {
057    super.init(contextName, factory);
058    int nKids;
059    try {
060      String sKids = getAttribute(ARITY_LABEL);
061      nKids = Integer.parseInt(sKids);
062    } catch (Exception e) {
063      LOG.error("Unable to initialize composite metric " + contextName +
064                ": could not init arity", e);
065      return;
066    }
067    for (int i = 0; i < nKids; ++i) {
068      MetricsContext ctxt = MetricsUtil.getContext(
069          String.format(SUB_FMT, contextName, i), contextName);
070      if (null != ctxt) {
071        subctxt.add(ctxt);
072      }
073    }
074  }
075
076  @InterfaceAudience.Private
077  @Override
078  public MetricsRecord newRecord(String recordName) {
079    return (MetricsRecord) Proxy.newProxyInstance(
080        MetricsRecord.class.getClassLoader(),
081        new Class[] { MetricsRecord.class },
082        new MetricsRecordDelegator(recordName, subctxt));
083  }
084
085  @InterfaceAudience.Private
086  @Override
087  protected void emitRecord(String contextName, String recordName,
088      OutputRecord outRec) throws IOException {
089    for (MetricsContext ctxt : subctxt) {
090      try {
091        ((AbstractMetricsContext)ctxt).emitRecord(
092          contextName, recordName, outRec);
093        if (contextName == null || recordName == null || outRec == null) {
094          throw new IOException(contextName + ":" + recordName + ":" + outRec);
095        }
096      } catch (IOException e) {
097        LOG.warn("emitRecord failed: " + ctxt.getContextName(), e);
098      }
099    }
100  }
101
102  @InterfaceAudience.Private
103  @Override
104  protected void flush() throws IOException {
105    for (MetricsContext ctxt : subctxt) {
106      try {
107        ((AbstractMetricsContext)ctxt).flush();
108      } catch (IOException e) {
109        LOG.warn("flush failed: " + ctxt.getContextName(), e);
110      }
111    }
112  }
113
114  @InterfaceAudience.Private
115  @Override
116  public void startMonitoring() throws IOException {
117    for (MetricsContext ctxt : subctxt) {
118      try {
119        ctxt.startMonitoring();
120      } catch (IOException e) {
121        LOG.warn("startMonitoring failed: " + ctxt.getContextName(), e);
122      }
123    }
124  }
125
126  @InterfaceAudience.Private
127  @Override
128  public void stopMonitoring() {
129    for (MetricsContext ctxt : subctxt) {
130      ctxt.stopMonitoring();
131    }
132  }
133
134  /**
135   * Return true if all subcontexts are monitoring.
136   */
137  @InterfaceAudience.Private
138  @Override
139  public boolean isMonitoring() {
140    boolean ret = true;
141    for (MetricsContext ctxt : subctxt) {
142      ret &= ctxt.isMonitoring();
143    }
144    return ret;
145  }
146
147  @InterfaceAudience.Private
148  @Override
149  public void close() {
150    for (MetricsContext ctxt : subctxt) {
151      ctxt.close();
152    }
153  }
154
155  @InterfaceAudience.Private
156  @Override
157  public void registerUpdater(Updater updater) {
158    for (MetricsContext ctxt : subctxt) {
159      ctxt.registerUpdater(updater);
160    }
161  }
162
163  @InterfaceAudience.Private
164  @Override
165  public void unregisterUpdater(Updater updater) {
166    for (MetricsContext ctxt : subctxt) {
167      ctxt.unregisterUpdater(updater);
168    }
169  }
170
171  private static class MetricsRecordDelegator implements InvocationHandler {
172    private static final Method m_getRecordName = initMethod();
173    private static Method initMethod() {
174      try {
175        return MetricsRecord.class.getMethod("getRecordName", new Class[0]);
176      } catch (Exception e) {
177        throw new RuntimeException("Internal error", e);
178      }
179    }
180
181    private final String recordName;
182    private final ArrayList<MetricsRecord> subrecs;
183
184    MetricsRecordDelegator(String recordName, ArrayList<MetricsContext> ctxts) {
185      this.recordName = recordName;
186      this.subrecs = new ArrayList<MetricsRecord>(ctxts.size());
187      for (MetricsContext ctxt : ctxts) {
188        subrecs.add(ctxt.createRecord(recordName));
189      }
190    }
191
192    public Object invoke(Object p, Method m, Object[] args) throws Throwable {
193      if (m_getRecordName.equals(m)) {
194        return recordName;
195      }
196      assert Void.TYPE.equals(m.getReturnType());
197      for (MetricsRecord rec : subrecs) {
198        m.invoke(rec, args);
199      }
200      return null;
201    }
202  }
203
204}