View Javadoc

1   /**
2    * Copyright 2011 The Apache Software Foundation
3    *
4    * Licensed to the Apache Software Foundation (ASF) under one
5    * or more contributor license agreements.  See the NOTICE file
6    * distributed with this work for additional information
7    * regarding copyright ownership.  The ASF licenses this file
8    * to you under the Apache License, Version 2.0 (the
9    * "License"); you may not use this file except in compliance
10   * with the License.  You may obtain a copy of the License at
11   *
12   *     http://www.apache.org/licenses/LICENSE-2.0
13   *
14   * Unless required by applicable law or agreed to in writing, software
15   * distributed under the License is distributed on an "AS IS" BASIS,
16   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17   * See the License for the specific language governing permissions and
18   * limitations under the License.
19   */
20  package org.apache.hadoop.hbase.util;
21  
22  import java.lang.reflect.Array;
23  import java.util.ArrayList;
24  import java.util.Collections;
25  import java.util.Comparator;
26  import java.util.HashMap;
27  import java.util.List;
28  
29  import org.apache.hadoop.hbase.KeyValue;
30  import org.apache.hadoop.hbase.client.Action;
31  import org.apache.hadoop.hbase.client.Delete;
32  import org.apache.hadoop.hbase.client.Get;
33  import org.apache.hadoop.hbase.client.Increment;
34  import org.apache.hadoop.hbase.client.MultiAction;
35  import org.apache.hadoop.hbase.client.Put;
36  
37  /**
38   * Utility methods for interacting with object instances.
39   */
40  public class Objects {
41    private static class QuantityMap extends HashMap<String,Quantity> {
42      public void increment(String type, int count) {
43        Quantity q = get(type);
44        if (q == null) {
45          q = new Quantity();
46          q.what = type;
47          put(type, q);
48        }
49        q.increment(count);
50      }
51  
52      public void stat(String type, int value) {
53        Quantity q = get(type);
54        if (q == null) {
55          q = new Stat();
56          q.what = type;
57          put(type, q);
58        }
59        q.increment(value);
60      }
61    }
62  
63    private static class Quantity {
64      int count;
65      String what;
66  
67      public void increment(int amount) {
68        count += amount;
69      }
70  
71      public void appendToString(StringBuilder out) {
72        if (out.length() > 0) out.append(", ");
73  
74        out.append(count).append(" ").append(what);
75        if (count != 1 && !what.endsWith("s")) {
76          out.append("s");
77        }
78      }
79    }
80  
81    private static class Stat extends Quantity {
82      int min;
83      int max;
84      long total;
85  
86      public void increment(int amount) {
87        if (count == 0) {
88          min = max = amount;
89        } else {
90          min = Math.min(min, amount);
91          max = Math.max(max, amount);
92        }
93        total += amount;
94        count++;
95      }
96  
97      public void appendToString(StringBuilder out) {
98        super.appendToString(out);
99  
100       out.append(" [ ");
101       if (count > 0) {
102         out.append("min=").append(min)
103             .append(" max=").append(max)
104             .append(" avg=").append((int)(total/count));
105       } else {
106         out.append("none");
107       }
108       out.append(" ]");
109     }
110   }
111 
112   private static class QuantityComparator implements Comparator<Quantity> {
113     @Override
114     public int compare(Quantity q1, Quantity q2) {
115       if (q1.count < q2.count) {
116         return -1;
117       } else if (q1.count > q2.count) {
118         return 1;
119       }
120       return 0;
121     }
122   }
123 
124   /**
125    * Attempts to construct a text description of the given object, by
126    * introspecting known classes and building a description of size.
127    * @param obj
128    * @return Description
129    */
130   public static String describeQuantity(Object obj) {
131     StringBuilder str = new StringBuilder();
132     QuantityMap quantities = new QuantityMap();
133     quantify(obj, quantities);
134     List<Quantity> totals = new ArrayList<Quantity>(quantities.values());
135     Collections.sort(totals, new QuantityComparator());
136     for (Quantity q : totals) {
137       q.appendToString(str);
138     }
139     return str.toString();
140   }
141 
142   public static void quantify(Object obj, QuantityMap quantities) {
143     if (obj == null) {
144       return;
145     }
146 
147     if (obj.getClass().isArray()) {
148       Class type = obj.getClass().getComponentType();
149       int length = Array.getLength(obj);
150       if (type.isPrimitive()) {
151         quantities.increment(type.getSimpleName(), length);
152       } else {
153         for (int i=0; i<length; i++) {
154           quantify(Array.get(obj, i), quantities);
155         }
156       }
157     } else if (obj instanceof Iterable) {
158       for (Object child : ((Iterable)obj)) {
159         quantify(child, quantities);
160       }
161     } else if (obj instanceof MultiAction) {
162       MultiAction multi = (MultiAction)obj;
163       quantify(multi.allActions(), quantities);
164     } else if (obj instanceof Action) {
165       quantify(((Action)obj).getAction(), quantities);
166     } else if (obj instanceof Put) {
167       quantities.increment("Put", 1);
168       quantities.increment("KeyValue", ((Put)obj).size());
169       for (List<KeyValue> keyValues : ((Put)obj).getFamilyMap().values()) {
170         for (KeyValue kv : keyValues) {
171           quantities.stat("values", kv.getValueLength());
172         }
173       }
174     } else if (obj instanceof Delete) {
175       quantities.increment("Delete", 1);
176       for (List<KeyValue> kvs : ((Delete)obj).getFamilyMap().values()) {
177         quantities.increment("KeyValue", kvs.size());
178       }
179     } else if (obj instanceof Increment) {
180       quantities.increment("Increment", 1);
181       quantities.increment("KeyValue", ((Increment)obj).numColumns());
182     } else if (obj instanceof Get) {
183       quantities.increment("Get", 1);
184     } else {
185       String type = obj.getClass().getSimpleName();
186       quantities.increment(type, 1);
187     }
188   }
189 }