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.hdfs.protocolPB;
019
020import java.util.ArrayList;
021import java.util.Arrays;
022import java.util.List;
023
024import com.google.protobuf.ByteString;
025
026import org.apache.hadoop.fs.StorageType;
027import org.apache.hadoop.ha.HAServiceProtocol.HAServiceState;
028import org.apache.hadoop.ha.proto.HAServiceProtocolProtos;
029import org.apache.hadoop.hdfs.DFSUtilClient;
030import org.apache.hadoop.hdfs.protocol.Block;
031import org.apache.hadoop.hdfs.protocol.DatanodeID;
032import org.apache.hadoop.hdfs.protocol.DatanodeInfo;
033import org.apache.hadoop.hdfs.protocol.ExtendedBlock;
034import org.apache.hadoop.hdfs.protocol.LocatedBlock;
035import org.apache.hadoop.hdfs.protocol.proto.DatanodeProtocolProtos.BalancerBandwidthCommandProto;
036import org.apache.hadoop.hdfs.protocol.proto.DatanodeProtocolProtos.BlockCommandProto;
037import org.apache.hadoop.hdfs.protocol.proto.DatanodeProtocolProtos.BlockIdCommandProto;
038import org.apache.hadoop.hdfs.protocol.proto.DatanodeProtocolProtos.BlockRecoveryCommandProto;
039import org.apache.hadoop.hdfs.protocol.proto.DatanodeProtocolProtos.DatanodeCommandProto;
040import org.apache.hadoop.hdfs.protocol.proto.DatanodeProtocolProtos.DatanodeRegistrationProto;
041import org.apache.hadoop.hdfs.protocol.proto.DatanodeProtocolProtos.FinalizeCommandProto;
042import org.apache.hadoop.hdfs.protocol.proto.DatanodeProtocolProtos.KeyUpdateCommandProto;
043import org.apache.hadoop.hdfs.protocol.proto.DatanodeProtocolProtos.ReceivedDeletedBlockInfoProto;
044import org.apache.hadoop.hdfs.protocol.proto.DatanodeProtocolProtos.RegisterCommandProto;
045import org.apache.hadoop.hdfs.protocol.proto.DatanodeProtocolProtos.VolumeFailureSummaryProto;
046import org.apache.hadoop.hdfs.protocol.proto.DatanodeProtocolProtos.BlockReportContextProto;
047import org.apache.hadoop.hdfs.protocol.proto.HdfsProtos.BlockProto;
048import org.apache.hadoop.hdfs.protocol.proto.HdfsProtos.DatanodeInfosProto;
049import org.apache.hadoop.hdfs.protocol.proto.HdfsProtos.LocatedBlockProto;
050import org.apache.hadoop.hdfs.protocol.proto.HdfsProtos.StorageTypeProto;
051import org.apache.hadoop.hdfs.protocol.proto.HdfsProtos.StorageTypesProto;
052import org.apache.hadoop.hdfs.protocol.proto.HdfsServerProtos.BlockKeyProto;
053import org.apache.hadoop.hdfs.protocol.proto.HdfsServerProtos.BlockWithLocationsProto;
054import org.apache.hadoop.hdfs.protocol.proto.HdfsServerProtos.BlocksWithLocationsProto;
055import org.apache.hadoop.hdfs.protocol.proto.HdfsServerProtos.CheckpointCommandProto;
056import org.apache.hadoop.hdfs.protocol.proto.HdfsServerProtos.CheckpointSignatureProto;
057import org.apache.hadoop.hdfs.protocol.proto.HdfsServerProtos.ExportedBlockKeysProto;
058import org.apache.hadoop.hdfs.protocol.proto.HdfsServerProtos.NamenodeCommandProto;
059import org.apache.hadoop.hdfs.protocol.proto.HdfsServerProtos.NamenodeRegistrationProto;
060import org.apache.hadoop.hdfs.protocol.proto.HdfsServerProtos.NamenodeRegistrationProto.NamenodeRoleProto;
061import org.apache.hadoop.hdfs.protocol.proto.HdfsServerProtos.NamespaceInfoProto;
062import org.apache.hadoop.hdfs.protocol.proto.HdfsServerProtos.NNHAStatusHeartbeatProto;
063import org.apache.hadoop.hdfs.protocol.proto.HdfsServerProtos.RecoveringBlockProto;
064import org.apache.hadoop.hdfs.protocol.proto.HdfsServerProtos.RemoteEditLogManifestProto;
065import org.apache.hadoop.hdfs.protocol.proto.HdfsServerProtos.RemoteEditLogProto;
066import org.apache.hadoop.hdfs.protocol.proto.HdfsServerProtos.ReplicaStateProto;
067import org.apache.hadoop.hdfs.protocol.proto.HdfsServerProtos.StorageInfoProto;
068import org.apache.hadoop.hdfs.protocol.proto.HdfsServerProtos.StorageUuidsProto;
069import org.apache.hadoop.hdfs.protocol.proto.JournalProtocolProtos.JournalInfoProto;
070import org.apache.hadoop.hdfs.security.token.block.BlockKey;
071import org.apache.hadoop.hdfs.security.token.block.ExportedBlockKeys;
072import org.apache.hadoop.hdfs.server.common.HdfsServerConstants.NamenodeRole;
073import org.apache.hadoop.hdfs.server.common.HdfsServerConstants.NodeType;
074import org.apache.hadoop.hdfs.server.common.HdfsServerConstants.ReplicaState;
075import org.apache.hadoop.hdfs.server.common.Storage;
076import org.apache.hadoop.hdfs.server.common.StorageInfo;
077import org.apache.hadoop.hdfs.server.namenode.CheckpointSignature;
078import org.apache.hadoop.hdfs.server.protocol.BalancerBandwidthCommand;
079import org.apache.hadoop.hdfs.server.protocol.BlockCommand;
080import org.apache.hadoop.hdfs.server.protocol.BlockIdCommand;
081import org.apache.hadoop.hdfs.server.protocol.BlockRecoveryCommand;
082import org.apache.hadoop.hdfs.server.protocol.BlockRecoveryCommand.RecoveringBlock;
083import org.apache.hadoop.hdfs.server.protocol.BlockReportContext;
084import org.apache.hadoop.hdfs.server.protocol.BlocksWithLocations;
085import org.apache.hadoop.hdfs.server.protocol.BlocksWithLocations.BlockWithLocations;
086import org.apache.hadoop.hdfs.server.protocol.CheckpointCommand;
087import org.apache.hadoop.hdfs.server.protocol.DatanodeCommand;
088import org.apache.hadoop.hdfs.server.protocol.DatanodeProtocol;
089import org.apache.hadoop.hdfs.server.protocol.DatanodeRegistration;
090import org.apache.hadoop.hdfs.server.protocol.FinalizeCommand;
091import org.apache.hadoop.hdfs.server.protocol.JournalInfo;
092import org.apache.hadoop.hdfs.server.protocol.KeyUpdateCommand;
093import org.apache.hadoop.hdfs.server.protocol.NNHAStatusHeartbeat;
094import org.apache.hadoop.hdfs.server.protocol.NamenodeCommand;
095import org.apache.hadoop.hdfs.server.protocol.NamenodeRegistration;
096import org.apache.hadoop.hdfs.server.protocol.NamespaceInfo;
097import org.apache.hadoop.hdfs.server.protocol.ReceivedDeletedBlockInfo;
098import org.apache.hadoop.hdfs.server.protocol.ReceivedDeletedBlockInfo.BlockStatus;
099import org.apache.hadoop.hdfs.server.protocol.RegisterCommand;
100import org.apache.hadoop.hdfs.server.protocol.RemoteEditLog;
101import org.apache.hadoop.hdfs.server.protocol.RemoteEditLogManifest;
102import org.apache.hadoop.hdfs.server.protocol.VolumeFailureSummary;
103
104/**
105 * Utilities for converting protobuf classes to and from implementation classes
106 * and other helper utilities to help in dealing with protobuf.
107 * 
108 * Note that when converting from an internal type to protobuf type, the
109 * converter never return null for protobuf type. The check for internal type
110 * being null must be done before calling the convert() method.
111 *
112 * For those helper methods that convert HDFS client-side data structures from
113 * and to protobuf, see {@link PBHelperClient}.
114 */
115public class PBHelper {
116  private static final RegisterCommandProto REG_CMD_PROTO = 
117      RegisterCommandProto.newBuilder().build();
118  private static final RegisterCommand REG_CMD = new RegisterCommand();
119
120  private PBHelper() {
121    /** Hidden constructor */
122  }
123
124  public static NamenodeRole convert(NamenodeRoleProto role) {
125    switch (role) {
126    case NAMENODE:
127      return NamenodeRole.NAMENODE;
128    case BACKUP:
129      return NamenodeRole.BACKUP;
130    case CHECKPOINT:
131      return NamenodeRole.CHECKPOINT;
132    }
133    return null;
134  }
135
136  public static NamenodeRoleProto convert(NamenodeRole role) {
137    switch (role) {
138    case NAMENODE:
139      return NamenodeRoleProto.NAMENODE;
140    case BACKUP:
141      return NamenodeRoleProto.BACKUP;
142    case CHECKPOINT:
143      return NamenodeRoleProto.CHECKPOINT;
144    }
145    return null;
146  }
147
148  public static StorageInfoProto convert(StorageInfo info) {
149    return StorageInfoProto.newBuilder().setClusterID(info.getClusterID())
150        .setCTime(info.getCTime()).setLayoutVersion(info.getLayoutVersion())
151        .setNamespceID(info.getNamespaceID()).build();
152  }
153
154  public static StorageInfo convert(StorageInfoProto info, NodeType type) {
155    return new StorageInfo(info.getLayoutVersion(), info.getNamespceID(),
156        info.getClusterID(), info.getCTime(), type);
157  }
158
159  public static NamenodeRegistrationProto convert(NamenodeRegistration reg) {
160    return NamenodeRegistrationProto.newBuilder()
161        .setHttpAddress(reg.getHttpAddress()).setRole(convert(reg.getRole()))
162        .setRpcAddress(reg.getAddress())
163        .setStorageInfo(convert((StorageInfo) reg)).build();
164  }
165
166  public static NamenodeRegistration convert(NamenodeRegistrationProto reg) {
167    StorageInfo si = convert(reg.getStorageInfo(), NodeType.NAME_NODE);
168    return new NamenodeRegistration(reg.getRpcAddress(), reg.getHttpAddress(),
169        si, convert(reg.getRole()));
170  }
171
172  public static BlockWithLocationsProto convert(BlockWithLocations blk) {
173    return BlockWithLocationsProto.newBuilder()
174        .setBlock(PBHelperClient.convert(blk.getBlock()))
175        .addAllDatanodeUuids(Arrays.asList(blk.getDatanodeUuids()))
176        .addAllStorageUuids(Arrays.asList(blk.getStorageIDs()))
177        .addAllStorageTypes(PBHelperClient.convertStorageTypes(blk.getStorageTypes()))
178        .build();
179  }
180
181  public static BlockWithLocations convert(BlockWithLocationsProto b) {
182    final List<String> datanodeUuids = b.getDatanodeUuidsList();
183    final List<String> storageUuids = b.getStorageUuidsList();
184    final List<StorageTypeProto> storageTypes = b.getStorageTypesList();
185    return new BlockWithLocations(PBHelperClient.convert(b.getBlock()),
186        datanodeUuids.toArray(new String[datanodeUuids.size()]),
187        storageUuids.toArray(new String[storageUuids.size()]),
188        PBHelperClient.convertStorageTypes(storageTypes, storageUuids.size()));
189  }
190
191  public static BlocksWithLocationsProto convert(BlocksWithLocations blks) {
192    BlocksWithLocationsProto.Builder builder = BlocksWithLocationsProto
193        .newBuilder();
194    for (BlockWithLocations b : blks.getBlocks()) {
195      builder.addBlocks(convert(b));
196    }
197    return builder.build();
198  }
199
200  public static BlocksWithLocations convert(BlocksWithLocationsProto blocks) {
201    List<BlockWithLocationsProto> b = blocks.getBlocksList();
202    BlockWithLocations[] ret = new BlockWithLocations[b.size()];
203    int i = 0;
204    for (BlockWithLocationsProto entry : b) {
205      ret[i++] = convert(entry);
206    }
207    return new BlocksWithLocations(ret);
208  }
209
210  public static BlockKeyProto convert(BlockKey key) {
211    byte[] encodedKey = key.getEncodedKey();
212    ByteString keyBytes = PBHelperClient.getByteString(encodedKey == null ?
213        DFSUtilClient.EMPTY_BYTES : encodedKey);
214    return BlockKeyProto.newBuilder().setKeyId(key.getKeyId())
215        .setKeyBytes(keyBytes).setExpiryDate(key.getExpiryDate()).build();
216  }
217
218  public static BlockKey convert(BlockKeyProto k) {
219    return new BlockKey(k.getKeyId(), k.getExpiryDate(), k.getKeyBytes()
220        .toByteArray());
221  }
222
223  public static ExportedBlockKeysProto convert(ExportedBlockKeys keys) {
224    ExportedBlockKeysProto.Builder builder = ExportedBlockKeysProto
225        .newBuilder();
226    builder.setIsBlockTokenEnabled(keys.isBlockTokenEnabled())
227        .setKeyUpdateInterval(keys.getKeyUpdateInterval())
228        .setTokenLifeTime(keys.getTokenLifetime())
229        .setCurrentKey(convert(keys.getCurrentKey()));
230    for (BlockKey k : keys.getAllKeys()) {
231      builder.addAllKeys(convert(k));
232    }
233    return builder.build();
234  }
235
236  public static ExportedBlockKeys convert(ExportedBlockKeysProto keys) {
237    return new ExportedBlockKeys(keys.getIsBlockTokenEnabled(),
238        keys.getKeyUpdateInterval(), keys.getTokenLifeTime(),
239        convert(keys.getCurrentKey()), convertBlockKeys(keys.getAllKeysList()));
240  }
241
242  public static CheckpointSignatureProto convert(CheckpointSignature s) {
243    return CheckpointSignatureProto.newBuilder()
244        .setBlockPoolId(s.getBlockpoolID())
245        .setCurSegmentTxId(s.getCurSegmentTxId())
246        .setMostRecentCheckpointTxId(s.getMostRecentCheckpointTxId())
247        .setStorageInfo(PBHelper.convert((StorageInfo) s)).build();
248  }
249
250  public static CheckpointSignature convert(CheckpointSignatureProto s) {
251    StorageInfo si = PBHelper.convert(s.getStorageInfo(), NodeType.NAME_NODE);
252    return new CheckpointSignature(si, s.getBlockPoolId(),
253        s.getMostRecentCheckpointTxId(), s.getCurSegmentTxId());
254  }
255
256  public static RemoteEditLogProto convert(RemoteEditLog log) {
257    return RemoteEditLogProto.newBuilder()
258        .setStartTxId(log.getStartTxId())
259        .setEndTxId(log.getEndTxId())
260        .setIsInProgress(log.isInProgress()).build();
261  }
262
263  public static RemoteEditLog convert(RemoteEditLogProto l) {
264    return new RemoteEditLog(l.getStartTxId(), l.getEndTxId(),
265        l.getIsInProgress());
266  }
267
268  public static RemoteEditLogManifestProto convert(
269      RemoteEditLogManifest manifest) {
270    RemoteEditLogManifestProto.Builder builder = RemoteEditLogManifestProto
271        .newBuilder();
272    for (RemoteEditLog log : manifest.getLogs()) {
273      builder.addLogs(convert(log));
274    }
275    return builder.build();
276  }
277
278  public static RemoteEditLogManifest convert(
279      RemoteEditLogManifestProto manifest) {
280    List<RemoteEditLog> logs = new ArrayList<RemoteEditLog>(manifest
281        .getLogsList().size());
282    for (RemoteEditLogProto l : manifest.getLogsList()) {
283      logs.add(convert(l));
284    }
285    return new RemoteEditLogManifest(logs);
286  }
287
288  public static CheckpointCommandProto convert(CheckpointCommand cmd) {
289    return CheckpointCommandProto.newBuilder()
290        .setSignature(convert(cmd.getSignature()))
291        .setNeedToReturnImage(cmd.needToReturnImage()).build();
292  }
293
294  public static NamenodeCommandProto convert(NamenodeCommand cmd) {
295    if (cmd instanceof CheckpointCommand) {
296      return NamenodeCommandProto.newBuilder().setAction(cmd.getAction())
297          .setType(NamenodeCommandProto.Type.CheckPointCommand)
298          .setCheckpointCmd(convert((CheckpointCommand) cmd)).build();
299    }
300    return NamenodeCommandProto.newBuilder()
301        .setType(NamenodeCommandProto.Type.NamenodeCommand)
302        .setAction(cmd.getAction()).build();
303  }
304
305  public static BlockKey[] convertBlockKeys(List<BlockKeyProto> list) {
306    BlockKey[] ret = new BlockKey[list.size()];
307    int i = 0;
308    for (BlockKeyProto k : list) {
309      ret[i++] = convert(k);
310    }
311    return ret;
312  }
313
314  public static NamespaceInfo convert(NamespaceInfoProto info) {
315    StorageInfoProto storage = info.getStorageInfo();
316    return new NamespaceInfo(storage.getNamespceID(), storage.getClusterID(),
317        info.getBlockPoolID(), storage.getCTime(), info.getBuildVersion(),
318        info.getSoftwareVersion(), info.getCapabilities(),
319        convert(info.getState()));
320  }
321
322  public static NamenodeCommand convert(NamenodeCommandProto cmd) {
323    if (cmd == null) return null;
324    switch (cmd.getType()) {
325    case CheckPointCommand:
326      CheckpointCommandProto chkPt = cmd.getCheckpointCmd();
327      return new CheckpointCommand(PBHelper.convert(chkPt.getSignature()),
328          chkPt.getNeedToReturnImage());
329    default:
330      return new NamenodeCommand(cmd.getAction());
331    }
332  }
333
334  public static RecoveringBlockProto convert(RecoveringBlock b) {
335    if (b == null) {
336      return null;
337    }
338    LocatedBlockProto lb = PBHelperClient.convert((LocatedBlock) b);
339    RecoveringBlockProto.Builder builder = RecoveringBlockProto.newBuilder();
340    builder.setBlock(lb).setNewGenStamp(b.getNewGenerationStamp());
341    if(b.getNewBlock() != null)
342      builder.setTruncateBlock(PBHelperClient.convert(b.getNewBlock()));
343    return builder.build();
344  }
345
346  public static RecoveringBlock convert(RecoveringBlockProto b) {
347    LocatedBlock lb = PBHelperClient.convert(b.getBlock());
348    RecoveringBlock rBlock;
349    if (b.hasTruncateBlock()) {
350      rBlock = new RecoveringBlock(lb.getBlock(), lb.getLocations(),
351          PBHelperClient.convert(b.getTruncateBlock()));
352    } else {
353      rBlock = new RecoveringBlock(lb.getBlock(), lb.getLocations(),
354          b.getNewGenStamp());
355    }
356    return rBlock;
357  }
358
359  public static ReplicaState convert(ReplicaStateProto state) {
360    switch (state) {
361    case RBW:
362      return ReplicaState.RBW;
363    case RUR:
364      return ReplicaState.RUR;
365    case RWR:
366      return ReplicaState.RWR;
367    case TEMPORARY:
368      return ReplicaState.TEMPORARY;
369    case FINALIZED:
370    default:
371      return ReplicaState.FINALIZED;
372    }
373  }
374
375  public static ReplicaStateProto convert(ReplicaState state) {
376    switch (state) {
377    case RBW:
378      return ReplicaStateProto.RBW;
379    case RUR:
380      return ReplicaStateProto.RUR;
381    case RWR:
382      return ReplicaStateProto.RWR;
383    case TEMPORARY:
384      return ReplicaStateProto.TEMPORARY;
385    case FINALIZED:
386    default:
387      return ReplicaStateProto.FINALIZED;
388    }
389  }
390  
391  public static DatanodeRegistrationProto convert(
392      DatanodeRegistration registration) {
393    DatanodeRegistrationProto.Builder builder = DatanodeRegistrationProto
394        .newBuilder();
395    return builder.setDatanodeID(PBHelperClient.convert((DatanodeID) registration))
396        .setStorageInfo(convert(registration.getStorageInfo()))
397        .setKeys(convert(registration.getExportedKeys()))
398        .setSoftwareVersion(registration.getSoftwareVersion()).build();
399  }
400
401  public static DatanodeRegistration convert(DatanodeRegistrationProto proto) {
402    StorageInfo si = convert(proto.getStorageInfo(), NodeType.DATA_NODE);
403    return new DatanodeRegistration(PBHelperClient.convert(proto.getDatanodeID()),
404        si, convert(proto.getKeys()), proto.getSoftwareVersion());
405  }
406
407  public static DatanodeCommand convert(DatanodeCommandProto proto) {
408    switch (proto.getCmdType()) {
409    case BalancerBandwidthCommand:
410      return PBHelper.convert(proto.getBalancerCmd());
411    case BlockCommand:
412      return PBHelper.convert(proto.getBlkCmd());
413    case BlockRecoveryCommand:
414      return PBHelper.convert(proto.getRecoveryCmd());
415    case FinalizeCommand:
416      return PBHelper.convert(proto.getFinalizeCmd());
417    case KeyUpdateCommand:
418      return PBHelper.convert(proto.getKeyUpdateCmd());
419    case RegisterCommand:
420      return REG_CMD;
421    case BlockIdCommand:
422      return PBHelper.convert(proto.getBlkIdCmd());
423    default:
424      return null;
425    }
426  }
427  
428  public static BalancerBandwidthCommandProto convert(
429      BalancerBandwidthCommand bbCmd) {
430    return BalancerBandwidthCommandProto.newBuilder()
431        .setBandwidth(bbCmd.getBalancerBandwidthValue()).build();
432  }
433
434  public static KeyUpdateCommandProto convert(KeyUpdateCommand cmd) {
435    return KeyUpdateCommandProto.newBuilder()
436        .setKeys(convert(cmd.getExportedKeys())).build();
437  }
438
439  public static BlockRecoveryCommandProto convert(BlockRecoveryCommand cmd) {
440    BlockRecoveryCommandProto.Builder builder = BlockRecoveryCommandProto
441        .newBuilder();
442    for (RecoveringBlock b : cmd.getRecoveringBlocks()) {
443      builder.addBlocks(PBHelper.convert(b));
444    }
445    return builder.build();
446  }
447
448  public static FinalizeCommandProto convert(FinalizeCommand cmd) {
449    return FinalizeCommandProto.newBuilder()
450        .setBlockPoolId(cmd.getBlockPoolId()).build();
451  }
452
453  public static BlockCommandProto convert(BlockCommand cmd) {
454    BlockCommandProto.Builder builder = BlockCommandProto.newBuilder()
455        .setBlockPoolId(cmd.getBlockPoolId());
456    switch (cmd.getAction()) {
457    case DatanodeProtocol.DNA_TRANSFER:
458      builder.setAction(BlockCommandProto.Action.TRANSFER);
459      break;
460    case DatanodeProtocol.DNA_INVALIDATE:
461      builder.setAction(BlockCommandProto.Action.INVALIDATE);
462      break;
463    case DatanodeProtocol.DNA_SHUTDOWN:
464      builder.setAction(BlockCommandProto.Action.SHUTDOWN);
465      break;
466    default:
467      throw new AssertionError("Invalid action");
468    }
469    Block[] blocks = cmd.getBlocks();
470    for (int i = 0; i < blocks.length; i++) {
471      builder.addBlocks(PBHelperClient.convert(blocks[i]));
472    }
473    builder.addAllTargets(PBHelperClient.convert(cmd.getTargets()))
474           .addAllTargetStorageUuids(convert(cmd.getTargetStorageIDs()));
475    StorageType[][] types = cmd.getTargetStorageTypes();
476    if (types != null) {
477      builder.addAllTargetStorageTypes(PBHelperClient.convert(types));
478    }
479    return builder.build();
480  }
481
482  public static BlockIdCommandProto convert(BlockIdCommand cmd) {
483    BlockIdCommandProto.Builder builder = BlockIdCommandProto.newBuilder()
484        .setBlockPoolId(cmd.getBlockPoolId());
485    switch (cmd.getAction()) {
486    case DatanodeProtocol.DNA_CACHE:
487      builder.setAction(BlockIdCommandProto.Action.CACHE);
488      break;
489    case DatanodeProtocol.DNA_UNCACHE:
490      builder.setAction(BlockIdCommandProto.Action.UNCACHE);
491      break;
492    default:
493      throw new AssertionError("Invalid action");
494    }
495    long[] blockIds = cmd.getBlockIds();
496    for (int i = 0; i < blockIds.length; i++) {
497      builder.addBlockIds(blockIds[i]);
498    }
499    return builder.build();
500  }
501
502  private static List<StorageUuidsProto> convert(String[][] targetStorageUuids) {
503    StorageUuidsProto[] ret = new StorageUuidsProto[targetStorageUuids.length];
504    for (int i = 0; i < targetStorageUuids.length; i++) {
505      ret[i] = StorageUuidsProto.newBuilder()
506          .addAllStorageUuids(Arrays.asList(targetStorageUuids[i])).build();
507    }
508    return Arrays.asList(ret);
509  }
510
511  public static DatanodeCommandProto convert(DatanodeCommand datanodeCommand) {
512    DatanodeCommandProto.Builder builder = DatanodeCommandProto.newBuilder();
513    if (datanodeCommand == null) {
514      return builder.setCmdType(DatanodeCommandProto.Type.NullDatanodeCommand)
515          .build();
516    }
517    switch (datanodeCommand.getAction()) {
518    case DatanodeProtocol.DNA_BALANCERBANDWIDTHUPDATE:
519      builder.setCmdType(DatanodeCommandProto.Type.BalancerBandwidthCommand)
520          .setBalancerCmd(
521              PBHelper.convert((BalancerBandwidthCommand) datanodeCommand));
522      break;
523    case DatanodeProtocol.DNA_ACCESSKEYUPDATE:
524      builder
525          .setCmdType(DatanodeCommandProto.Type.KeyUpdateCommand)
526          .setKeyUpdateCmd(PBHelper.convert((KeyUpdateCommand) datanodeCommand));
527      break;
528    case DatanodeProtocol.DNA_RECOVERBLOCK:
529      builder.setCmdType(DatanodeCommandProto.Type.BlockRecoveryCommand)
530          .setRecoveryCmd(
531              PBHelper.convert((BlockRecoveryCommand) datanodeCommand));
532      break;
533    case DatanodeProtocol.DNA_FINALIZE:
534      builder.setCmdType(DatanodeCommandProto.Type.FinalizeCommand)
535          .setFinalizeCmd(PBHelper.convert((FinalizeCommand) datanodeCommand));
536      break;
537    case DatanodeProtocol.DNA_REGISTER:
538      builder.setCmdType(DatanodeCommandProto.Type.RegisterCommand)
539          .setRegisterCmd(REG_CMD_PROTO);
540      break;
541    case DatanodeProtocol.DNA_TRANSFER:
542    case DatanodeProtocol.DNA_INVALIDATE:
543    case DatanodeProtocol.DNA_SHUTDOWN:
544      builder.setCmdType(DatanodeCommandProto.Type.BlockCommand).
545        setBlkCmd(PBHelper.convert((BlockCommand) datanodeCommand));
546      break;
547    case DatanodeProtocol.DNA_CACHE:
548    case DatanodeProtocol.DNA_UNCACHE:
549      builder.setCmdType(DatanodeCommandProto.Type.BlockIdCommand).
550        setBlkIdCmd(PBHelper.convert((BlockIdCommand) datanodeCommand));
551      break;
552    case DatanodeProtocol.DNA_UNKNOWN: //Not expected
553    default:
554      builder.setCmdType(DatanodeCommandProto.Type.NullDatanodeCommand);
555    }
556    return builder.build();
557  }
558
559  public static KeyUpdateCommand convert(KeyUpdateCommandProto keyUpdateCmd) {
560    return new KeyUpdateCommand(convert(keyUpdateCmd.getKeys()));
561  }
562
563  public static FinalizeCommand convert(FinalizeCommandProto finalizeCmd) {
564    return new FinalizeCommand(finalizeCmd.getBlockPoolId());
565  }
566
567  public static BlockRecoveryCommand convert(
568      BlockRecoveryCommandProto recoveryCmd) {
569    List<RecoveringBlockProto> list = recoveryCmd.getBlocksList();
570    List<RecoveringBlock> recoveringBlocks = new ArrayList<RecoveringBlock>(
571        list.size());
572    
573    for (RecoveringBlockProto rbp : list) {
574      recoveringBlocks.add(PBHelper.convert(rbp));
575    }
576    return new BlockRecoveryCommand(recoveringBlocks);
577  }
578
579  public static BlockCommand convert(BlockCommandProto blkCmd) {
580    List<BlockProto> blockProtoList = blkCmd.getBlocksList();
581    Block[] blocks = new Block[blockProtoList.size()];
582    for (int i = 0; i < blockProtoList.size(); i++) {
583      blocks[i] = PBHelperClient.convert(blockProtoList.get(i));
584    }
585    List<DatanodeInfosProto> targetList = blkCmd.getTargetsList();
586    DatanodeInfo[][] targets = new DatanodeInfo[targetList.size()][];
587    for (int i = 0; i < targetList.size(); i++) {
588      targets[i] = PBHelperClient.convert(targetList.get(i));
589    }
590
591    StorageType[][] targetStorageTypes = new StorageType[targetList.size()][];
592    List<StorageTypesProto> targetStorageTypesList = blkCmd.getTargetStorageTypesList();
593    if (targetStorageTypesList.isEmpty()) { // missing storage types
594      for(int i = 0; i < targetStorageTypes.length; i++) {
595        targetStorageTypes[i] = new StorageType[targets[i].length];
596        Arrays.fill(targetStorageTypes[i], StorageType.DEFAULT);
597      }
598    } else {
599      for(int i = 0; i < targetStorageTypes.length; i++) {
600        List<StorageTypeProto> p = targetStorageTypesList.get(i).getStorageTypesList();
601        targetStorageTypes[i] = PBHelperClient.convertStorageTypes(p, targets[i].length);
602      }
603    }
604
605    List<StorageUuidsProto> targetStorageUuidsList = blkCmd.getTargetStorageUuidsList();
606    String[][] targetStorageIDs = new String[targetStorageUuidsList.size()][];
607    for(int i = 0; i < targetStorageIDs.length; i++) {
608      List<String> storageIDs = targetStorageUuidsList.get(i).getStorageUuidsList();
609      targetStorageIDs[i] = storageIDs.toArray(new String[storageIDs.size()]);
610    }
611
612    int action = DatanodeProtocol.DNA_UNKNOWN;
613    switch (blkCmd.getAction()) {
614    case TRANSFER:
615      action = DatanodeProtocol.DNA_TRANSFER;
616      break;
617    case INVALIDATE:
618      action = DatanodeProtocol.DNA_INVALIDATE;
619      break;
620    case SHUTDOWN:
621      action = DatanodeProtocol.DNA_SHUTDOWN;
622      break;
623    default:
624      throw new AssertionError("Unknown action type: " + blkCmd.getAction());
625    }
626    return new BlockCommand(action, blkCmd.getBlockPoolId(), blocks, targets,
627        targetStorageTypes, targetStorageIDs);
628  }
629
630  public static BlockIdCommand convert(BlockIdCommandProto blkIdCmd) {
631    int numBlockIds = blkIdCmd.getBlockIdsCount();
632    long blockIds[] = new long[numBlockIds];
633    for (int i = 0; i < numBlockIds; i++) {
634      blockIds[i] = blkIdCmd.getBlockIds(i);
635    }
636    int action = DatanodeProtocol.DNA_UNKNOWN;
637    switch (blkIdCmd.getAction()) {
638    case CACHE:
639      action = DatanodeProtocol.DNA_CACHE;
640      break;
641    case UNCACHE:
642      action = DatanodeProtocol.DNA_UNCACHE;
643      break;
644    default:
645      throw new AssertionError("Unknown action type: " + blkIdCmd.getAction());
646    }
647    return new BlockIdCommand(action, blkIdCmd.getBlockPoolId(), blockIds);
648  }
649
650  public static BalancerBandwidthCommand convert(
651      BalancerBandwidthCommandProto balancerCmd) {
652    return new BalancerBandwidthCommand(balancerCmd.getBandwidth());
653  }
654
655  public static ReceivedDeletedBlockInfoProto convert(
656      ReceivedDeletedBlockInfo receivedDeletedBlockInfo) {
657    ReceivedDeletedBlockInfoProto.Builder builder = 
658        ReceivedDeletedBlockInfoProto.newBuilder();
659    
660    ReceivedDeletedBlockInfoProto.BlockStatus status;
661    switch (receivedDeletedBlockInfo.getStatus()) {
662    case RECEIVING_BLOCK:
663      status = ReceivedDeletedBlockInfoProto.BlockStatus.RECEIVING;
664      break;
665    case RECEIVED_BLOCK:
666      status = ReceivedDeletedBlockInfoProto.BlockStatus.RECEIVED;
667      break;
668    case DELETED_BLOCK:
669      status = ReceivedDeletedBlockInfoProto.BlockStatus.DELETED;
670      break;
671    default:
672      throw new IllegalArgumentException("Bad status: " +
673          receivedDeletedBlockInfo.getStatus());
674    }
675    builder.setStatus(status);
676    
677    if (receivedDeletedBlockInfo.getDelHints() != null) {
678      builder.setDeleteHint(receivedDeletedBlockInfo.getDelHints());
679    }
680    return builder.setBlock(
681        PBHelperClient.convert(receivedDeletedBlockInfo.getBlock())).build();
682  }
683
684  public static ReceivedDeletedBlockInfo convert(
685      ReceivedDeletedBlockInfoProto proto) {
686    ReceivedDeletedBlockInfo.BlockStatus status = null;
687    switch (proto.getStatus()) {
688    case RECEIVING:
689      status = BlockStatus.RECEIVING_BLOCK;
690      break;
691    case RECEIVED:
692      status = BlockStatus.RECEIVED_BLOCK;
693      break;
694    case DELETED:
695      status = BlockStatus.DELETED_BLOCK;
696      break;
697    }
698    return new ReceivedDeletedBlockInfo(
699        PBHelperClient.convert(proto.getBlock()),
700        status,
701        proto.hasDeleteHint() ? proto.getDeleteHint() : null);
702  }
703  
704  public static NamespaceInfoProto convert(NamespaceInfo info) {
705    NamespaceInfoProto.Builder builder = NamespaceInfoProto.newBuilder();
706    builder.setBlockPoolID(info.getBlockPoolID())
707        .setBuildVersion(info.getBuildVersion())
708        .setUnused(0)
709        .setStorageInfo(PBHelper.convert((StorageInfo)info))
710        .setSoftwareVersion(info.getSoftwareVersion())
711        .setCapabilities(info.getCapabilities());
712    HAServiceState state = info.getState();
713    if(state != null) {
714      builder.setState(convert(info.getState()));
715    }
716    return builder.build();
717  }
718
719  public static HAServiceState convert(NNHAStatusHeartbeatProto.State s) {
720    if (s == null) {
721      return null;
722    }
723    switch (s) {
724    case ACTIVE:
725      return HAServiceState.ACTIVE;
726    case STANDBY:
727      return HAServiceState.STANDBY;
728    default:
729      throw new IllegalArgumentException("Unexpected HAServiceStateProto:"
730          + s);
731    }
732  }
733
734  public static NNHAStatusHeartbeatProto.State convert(HAServiceState s) {
735    if (s == null) {
736      return null;
737    }
738    switch (s) {
739    case ACTIVE:
740      return NNHAStatusHeartbeatProto.State.ACTIVE;
741    case STANDBY:
742      return NNHAStatusHeartbeatProto.State.STANDBY;
743    default:
744      throw new IllegalArgumentException("Unexpected HAServiceState:"
745          + s);
746    }
747  }
748
749  public static NNHAStatusHeartbeat convert(NNHAStatusHeartbeatProto s) {
750    if (s == null) {
751      return null;
752    }
753    return new NNHAStatusHeartbeat(convert(s.getState()), s.getTxid());
754  }
755
756  public static NNHAStatusHeartbeatProto convert(NNHAStatusHeartbeat hb) {
757    if (hb == null) {
758      return null;
759    }
760    NNHAStatusHeartbeatProto.Builder builder =
761        NNHAStatusHeartbeatProto.newBuilder();
762    builder.setState(convert(hb.getState()));
763    builder.setTxid(hb.getTxId());
764    return builder.build();
765  }
766
767  public static VolumeFailureSummary convertVolumeFailureSummary(
768      VolumeFailureSummaryProto proto) {
769    List<String> failedStorageLocations = proto.getFailedStorageLocationsList();
770    return new VolumeFailureSummary(
771        failedStorageLocations.toArray(new String[failedStorageLocations.size()]),
772        proto.getLastVolumeFailureDate(), proto.getEstimatedCapacityLostTotal());
773  }
774
775  public static VolumeFailureSummaryProto convertVolumeFailureSummary(
776      VolumeFailureSummary volumeFailureSummary) {
777    VolumeFailureSummaryProto.Builder builder =
778        VolumeFailureSummaryProto.newBuilder();
779    for (String failedStorageLocation:
780        volumeFailureSummary.getFailedStorageLocations()) {
781      builder.addFailedStorageLocations(failedStorageLocation);
782    }
783    builder.setLastVolumeFailureDate(
784        volumeFailureSummary.getLastVolumeFailureDate());
785    builder.setEstimatedCapacityLostTotal(
786        volumeFailureSummary.getEstimatedCapacityLostTotal());
787    return builder.build();
788  }
789
790  public static JournalInfo convert(JournalInfoProto info) {
791    int lv = info.hasLayoutVersion() ? info.getLayoutVersion() : 0;
792    int nsID = info.hasNamespaceID() ? info.getNamespaceID() : 0;
793    return new JournalInfo(lv, info.getClusterID(), nsID);
794  }
795
796  /**
797   * Method used for converting {@link JournalInfoProto} sent from Namenode
798   * to Journal receivers to {@link NamenodeRegistration}.
799   */
800  public static JournalInfoProto convert(JournalInfo j) {
801    return JournalInfoProto.newBuilder().setClusterID(j.getClusterId())
802        .setLayoutVersion(j.getLayoutVersion())
803        .setNamespaceID(j.getNamespaceId()).build();
804  }
805
806
807  public static BlockReportContext convert(BlockReportContextProto proto) {
808    return new BlockReportContext(proto.getTotalRpcs(),
809        proto.getCurRpc(), proto.getId(), proto.getLeaseId());
810  }
811
812  public static BlockReportContextProto convert(BlockReportContext context) {
813    return BlockReportContextProto.newBuilder().
814        setTotalRpcs(context.getTotalRpcs()).
815        setCurRpc(context.getCurRpc()).
816        setId(context.getReportId()).
817        setLeaseId(context.getLeaseId()).
818        build();
819  }
820}