View Javadoc

1   /**
2    *
3    * Licensed to the Apache Software Foundation (ASF) under one
4    * or more contributor license agreements.  See the NOTICE file
5    * distributed with this work for additional information
6    * regarding copyright ownership.  The ASF licenses this file
7    * to you under the Apache License, Version 2.0 (the
8    * "License"); you may not use this file except in compliance
9    * with the License.  You may obtain a copy of the License at
10   *
11   *     http://www.apache.org/licenses/LICENSE-2.0
12   *
13   * Unless required by applicable law or agreed to in writing, software
14   * distributed under the License is distributed on an "AS IS" BASIS,
15   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16   * See the License for the specific language governing permissions and
17   * limitations under the License.
18   */
19  
20  package org.apache.hadoop.hbase.protobuf;
21  
22  
23  import java.io.IOException;
24  import java.util.ArrayList;
25  import java.util.Iterator;
26  import java.util.List;
27  import java.util.Map;
28  import java.util.NavigableMap;
29  import java.util.UUID;
30  
31  import com.google.protobuf.HBaseZeroCopyByteString;
32  import org.apache.hadoop.classification.InterfaceAudience;
33  import org.apache.hadoop.hbase.Cell;
34  import org.apache.hadoop.hbase.CellScanner;
35  import org.apache.hadoop.hbase.KeyValue;
36  import org.apache.hadoop.hbase.io.SizedCellScanner;
37  import org.apache.hadoop.hbase.ipc.PayloadCarryingRpcController;
38  import org.apache.hadoop.hbase.protobuf.generated.AdminProtos;
39  import org.apache.hadoop.hbase.protobuf.generated.AdminProtos.AdminService;
40  import org.apache.hadoop.hbase.protobuf.generated.HBaseProtos;
41  import org.apache.hadoop.hbase.protobuf.generated.WALProtos;
42  import org.apache.hadoop.hbase.regionserver.wal.HLog;
43  import org.apache.hadoop.hbase.regionserver.wal.HLogKey;
44  import org.apache.hadoop.hbase.regionserver.wal.WALEdit;
45  import org.apache.hadoop.hbase.util.Pair;
46  
47  import com.google.protobuf.ServiceException;
48  
49  @InterfaceAudience.Private
50  public class ReplicationProtbufUtil {
51    /**
52     * A helper to replicate a list of HLog entries using admin protocol.
53     *
54     * @param admin
55     * @param entries
56     * @throws java.io.IOException
57     */
58    public static void replicateWALEntry(final AdminService.BlockingInterface admin,
59        final HLog.Entry[] entries) throws IOException {
60      Pair<AdminProtos.ReplicateWALEntryRequest, CellScanner> p =
61        buildReplicateWALEntryRequest(entries);
62      try {
63        PayloadCarryingRpcController controller = new PayloadCarryingRpcController(p.getSecond());
64        admin.replicateWALEntry(controller, p.getFirst());
65      } catch (ServiceException se) {
66        throw ProtobufUtil.getRemoteException(se);
67      }
68    }
69  
70    /**
71     * Create a new ReplicateWALEntryRequest from a list of HLog entries
72     *
73     * @param entries the HLog entries to be replicated
74     * @return a pair of ReplicateWALEntryRequest and a CellScanner over all the WALEdit values
75     * found.
76     */
77    public static Pair<AdminProtos.ReplicateWALEntryRequest, CellScanner>
78        buildReplicateWALEntryRequest(final HLog.Entry[] entries) {
79      // Accumulate all the KVs seen in here.
80      List<List<? extends Cell>> allkvs = new ArrayList<List<? extends Cell>>(entries.length);
81      int size = 0;
82      WALProtos.FamilyScope.Builder scopeBuilder = WALProtos.FamilyScope.newBuilder();
83      AdminProtos.WALEntry.Builder entryBuilder = AdminProtos.WALEntry.newBuilder();
84      AdminProtos.ReplicateWALEntryRequest.Builder builder =
85        AdminProtos.ReplicateWALEntryRequest.newBuilder();
86      HBaseProtos.UUID.Builder uuidBuilder = HBaseProtos.UUID.newBuilder();
87      for (HLog.Entry entry: entries) {
88        entryBuilder.clear();
89        WALProtos.WALKey.Builder keyBuilder = entryBuilder.getKeyBuilder();
90        HLogKey key = entry.getKey();
91        keyBuilder.setEncodedRegionName(
92          HBaseZeroCopyByteString.wrap(key.getEncodedRegionName()));
93        keyBuilder.setTableName(HBaseZeroCopyByteString.wrap(key.getTablename().getName()));
94        keyBuilder.setLogSequenceNumber(key.getLogSeqNum());
95        keyBuilder.setWriteTime(key.getWriteTime());
96        for(UUID clusterId : key.getClusterIds()) {
97          uuidBuilder.setLeastSigBits(clusterId.getLeastSignificantBits());
98          uuidBuilder.setMostSigBits(clusterId.getMostSignificantBits());
99          keyBuilder.addClusterIds(uuidBuilder.build());
100       }
101       WALEdit edit = entry.getEdit();
102       NavigableMap<byte[], Integer> scopes = key.getScopes();
103       if (scopes != null && !scopes.isEmpty()) {
104         for (Map.Entry<byte[], Integer> scope: scopes.entrySet()) {
105           scopeBuilder.setFamily(HBaseZeroCopyByteString.wrap(scope.getKey()));
106           WALProtos.ScopeType scopeType =
107               WALProtos.ScopeType.valueOf(scope.getValue().intValue());
108           scopeBuilder.setScopeType(scopeType);
109           keyBuilder.addScopes(scopeBuilder.build());
110         }
111       }
112       List<KeyValue> kvs = edit.getKeyValues();
113       // Add up the size.  It is used later serializing out the kvs.
114       for (KeyValue kv: kvs) {
115         size += kv.getLength();
116       }
117       // Collect up the kvs
118       allkvs.add(kvs);
119       // Write out how many kvs associated with this entry.
120       entryBuilder.setAssociatedCellCount(kvs.size());
121       builder.addEntry(entryBuilder.build());
122     }
123     return new Pair<AdminProtos.ReplicateWALEntryRequest, CellScanner>(builder.build(),
124       getCellScanner(allkvs, size));
125   }
126 
127   /**
128    * @param cells
129    * @return <code>cells</code> packaged as a CellScanner
130    */
131   static CellScanner getCellScanner(final List<List<? extends Cell>> cells, final int size) {
132     return new SizedCellScanner() {
133       private final Iterator<List<? extends Cell>> entries = cells.iterator();
134       private Iterator<? extends Cell> currentIterator = null;
135       private Cell currentCell;
136 
137       @Override
138       public Cell current() {
139         return this.currentCell;
140       }
141 
142       @Override
143       public boolean advance() {
144         if (this.currentIterator == null) {
145           if (!this.entries.hasNext()) return false;
146           this.currentIterator = this.entries.next().iterator();
147         }
148         if (this.currentIterator.hasNext()) {
149           this.currentCell = this.currentIterator.next();
150           return true;
151         }
152         this.currentCell = null;
153         this.currentIterator = null;
154         return advance();
155       }
156 
157       @Override
158       public long heapSize() {
159         return size;
160       }
161     };
162   }
163 }