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  
21  package org.apache.hadoop.hbase.client;
22  
23  import java.util.ArrayList;
24  import java.util.HashMap;
25  import java.util.List;
26  import java.util.Map;
27  import java.util.TreeMap;
28  import java.util.UUID;
29  
30  import org.apache.hadoop.hbase.HConstants;
31  import org.apache.hadoop.hbase.KeyValue;
32  import org.apache.hadoop.hbase.util.Bytes;
33  
34  public abstract class Mutation extends OperationWithAttributes {
35    // Attribute used in Mutations to indicate the originating cluster.
36    private static final String CLUSTER_ID_ATTR = "_c.id_";
37  
38    protected byte [] row = null;
39    protected long ts = HConstants.LATEST_TIMESTAMP;
40    protected long lockId = -1L;
41    protected boolean writeToWAL = true;
42    protected Map<byte [], List<KeyValue>> familyMap =
43        new TreeMap<byte [], List<KeyValue>>(Bytes.BYTES_COMPARATOR);
44  
45    /**
46     * Compile the column family (i.e. schema) information
47     * into a Map. Useful for parsing and aggregation by debugging,
48     * logging, and administration tools.
49     * @return Map
50     */
51    @Override
52    public Map<String, Object> getFingerprint() {
53      Map<String, Object> map = new HashMap<String, Object>();
54      List<String> families = new ArrayList<String>();
55      // ideally, we would also include table information, but that information
56      // is not stored in each Operation instance.
57      map.put("families", families);
58      for (Map.Entry<byte [], List<KeyValue>> entry : this.familyMap.entrySet()) {
59        families.add(Bytes.toStringBinary(entry.getKey()));
60      } 
61      return map;
62    }
63  
64    /**
65     * Compile the details beyond the scope of getFingerprint (row, columns,
66     * timestamps, etc.) into a Map along with the fingerprinted information.
67     * Useful for debugging, logging, and administration tools.
68     * @param maxCols a limit on the number of columns output prior to truncation
69     * @return Map
70     */
71    @Override
72    public Map<String, Object> toMap(int maxCols) {
73      // we start with the fingerprint map and build on top of it.
74      Map<String, Object> map = getFingerprint();
75      // replace the fingerprint's simple list of families with a 
76      // map from column families to lists of qualifiers and kv details
77      Map<String, List<Map<String, Object>>> columns =
78        new HashMap<String, List<Map<String, Object>>>();
79      map.put("families", columns);
80      map.put("row", Bytes.toStringBinary(this.row));
81      int colCount = 0;
82      // iterate through all column families affected
83      for (Map.Entry<byte [], List<KeyValue>> entry : this.familyMap.entrySet()) {
84        // map from this family to details for each kv affected within the family
85        List<Map<String, Object>> qualifierDetails =
86          new ArrayList<Map<String, Object>>();
87        columns.put(Bytes.toStringBinary(entry.getKey()), qualifierDetails);
88        colCount += entry.getValue().size();
89        if (maxCols <= 0) {
90          continue;
91        }
92        // add details for each kv
93        for (KeyValue kv : entry.getValue()) {
94          if (--maxCols <= 0 ) {
95            continue;
96          }
97          Map<String, Object> kvMap = kv.toStringMap();
98          // row and family information are already available in the bigger map
99          kvMap.remove("row");
100         kvMap.remove("family");
101         qualifierDetails.add(kvMap);
102       }
103     }
104     map.put("totalColumns", colCount);
105     return map;
106   }
107 
108   /**
109    * @return true if edits should be applied to WAL, false if not
110    */
111   public boolean getWriteToWAL() {
112     return this.writeToWAL;
113   }
114 
115   /**
116    * Set whether this Delete should be written to the WAL or not.
117    * Not writing the WAL means you may lose edits on server crash.
118    * @param write true if edits should be written to WAL, false if not
119    */
120   public void setWriteToWAL(boolean write) {
121     this.writeToWAL = write;
122   }
123 
124   /**
125    * Method for retrieving the put's familyMap
126    * @return familyMap
127    */
128   public Map<byte [], List<KeyValue>> getFamilyMap() {
129     return this.familyMap;
130   }
131 
132   /**
133    * Method for setting the put's familyMap
134    */
135   public void setFamilyMap(Map<byte [], List<KeyValue>> map) {
136     this.familyMap = map;
137   }
138 
139   /**
140    * Method to check if the familyMap is empty
141    * @return true if empty, false otherwise
142    */
143   public boolean isEmpty() {
144     return familyMap.isEmpty();
145   }
146 
147   /**
148    * Method for retrieving the delete's row
149    * @return row
150    */
151   public byte [] getRow() {
152     return this.row;
153   }
154 
155   public int compareTo(final Row d) {
156     return Bytes.compareTo(this.getRow(), d.getRow());
157   }
158 
159   /**
160    * Method for retrieving the delete's RowLock
161    * @return RowLock
162    */
163   public RowLock getRowLock() {
164     return new RowLock(this.row, this.lockId);
165   }
166 
167   /**
168    * Method for retrieving the delete's lock ID.
169    *
170    * @return The lock ID.
171    */
172   public long getLockId() {
173   return this.lockId;
174   }
175 
176   /**
177    * Method for retrieving the timestamp
178    * @return timestamp
179    */
180   public long getTimeStamp() {
181     return this.ts;
182   }
183 
184   /**
185    * Set the replication custer id.
186    * @param clusterId
187    */
188   public void setClusterId(UUID clusterId) {
189     byte[] val = new byte[2*Bytes.SIZEOF_LONG];
190     Bytes.putLong(val, 0, clusterId.getMostSignificantBits());
191     Bytes.putLong(val, Bytes.SIZEOF_LONG, clusterId.getLeastSignificantBits());
192     setAttribute(CLUSTER_ID_ATTR, val);
193   }
194 
195   /**
196    * @return The replication cluster id.
197    */
198   public UUID getClusterId() {
199     byte[] attr = getAttribute(CLUSTER_ID_ATTR);
200     if (attr == null) {
201       return HConstants.DEFAULT_CLUSTER_ID;
202     }
203     return new UUID(Bytes.toLong(attr,0), Bytes.toLong(attr, Bytes.SIZEOF_LONG));
204   }
205 }