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 static com.google.common.base.Preconditions.checkNotNull;
021
022import java.io.EOFException;
023import java.io.IOException;
024import java.io.InputStream;
025import java.util.ArrayList;
026import java.util.Arrays;
027import java.util.EnumSet;
028import java.util.List;
029
030import com.google.common.base.Preconditions;
031import org.apache.hadoop.fs.CacheFlag;
032import org.apache.hadoop.fs.ContentSummary;
033import org.apache.hadoop.fs.CreateFlag;
034import org.apache.hadoop.fs.FsServerDefaults;
035import org.apache.hadoop.fs.Path;
036import org.apache.hadoop.fs.permission.FsPermission;
037import org.apache.hadoop.ha.HAServiceProtocol.HAServiceState;
038import org.apache.hadoop.hdfs.DFSUtil;
039import org.apache.hadoop.hdfs.StorageType;
040import org.apache.hadoop.hdfs.protocol.Block;
041import org.apache.hadoop.hdfs.protocol.CacheDirectiveEntry;
042import org.apache.hadoop.hdfs.protocol.CacheDirectiveStats;
043import org.apache.hadoop.hdfs.protocol.CachePoolEntry;
044import org.apache.hadoop.hdfs.protocol.CachePoolInfo;
045import org.apache.hadoop.hdfs.protocol.CachePoolStats;
046import org.apache.hadoop.hdfs.protocol.ClientProtocol;
047import org.apache.hadoop.hdfs.protocol.CorruptFileBlocks;
048import org.apache.hadoop.hdfs.protocol.DatanodeID;
049import org.apache.hadoop.hdfs.protocol.DatanodeInfo;
050import org.apache.hadoop.hdfs.protocol.CacheDirectiveInfo;
051import org.apache.hadoop.hdfs.protocol.SnapshotDiffReport;
052import org.apache.hadoop.hdfs.protocol.DatanodeInfo.AdminStates;
053import org.apache.hadoop.hdfs.protocol.DirectoryListing;
054import org.apache.hadoop.hdfs.protocol.ExtendedBlock;
055import org.apache.hadoop.hdfs.protocol.HdfsConstants.DatanodeReportType;
056import org.apache.hadoop.hdfs.protocol.HdfsConstants.SafeModeAction;
057import org.apache.hadoop.hdfs.protocol.HdfsFileStatus;
058import org.apache.hadoop.hdfs.protocol.HdfsLocatedFileStatus;
059import org.apache.hadoop.hdfs.protocol.LocatedBlock;
060import org.apache.hadoop.hdfs.protocol.LocatedBlocks;
061import org.apache.hadoop.hdfs.protocol.SnapshotDiffReport.DiffReportEntry;
062import org.apache.hadoop.hdfs.protocol.SnapshotDiffReport.DiffType;
063import org.apache.hadoop.hdfs.protocol.SnapshottableDirectoryStatus;
064import org.apache.hadoop.hdfs.protocol.proto.ClientNamenodeProtocolProtos;
065import org.apache.hadoop.hdfs.protocol.proto.ClientNamenodeProtocolProtos.CacheDirectiveEntryProto;
066import org.apache.hadoop.hdfs.protocol.proto.ClientNamenodeProtocolProtos.CacheDirectiveInfoExpirationProto;
067import org.apache.hadoop.hdfs.protocol.proto.ClientNamenodeProtocolProtos.CacheDirectiveStatsProto;
068import org.apache.hadoop.hdfs.protocol.proto.ClientNamenodeProtocolProtos.CacheFlagProto;
069import org.apache.hadoop.hdfs.protocol.proto.ClientNamenodeProtocolProtos.CachePoolEntryProto;
070import org.apache.hadoop.hdfs.protocol.proto.ClientNamenodeProtocolProtos.CachePoolInfoProto;
071import org.apache.hadoop.hdfs.protocol.proto.ClientNamenodeProtocolProtos.CachePoolStatsProto;
072import org.apache.hadoop.hdfs.protocol.proto.ClientNamenodeProtocolProtos.CreateFlagProto;
073import org.apache.hadoop.hdfs.protocol.proto.ClientNamenodeProtocolProtos.DatanodeReportTypeProto;
074import org.apache.hadoop.hdfs.protocol.proto.ClientNamenodeProtocolProtos.GetFsStatsResponseProto;
075import org.apache.hadoop.hdfs.protocol.proto.ClientNamenodeProtocolProtos.SafeModeActionProto;
076import org.apache.hadoop.hdfs.protocol.proto.ClientNamenodeProtocolProtos.CacheDirectiveInfoProto;
077import org.apache.hadoop.hdfs.protocol.proto.DatanodeProtocolProtos.BalancerBandwidthCommandProto;
078import org.apache.hadoop.hdfs.protocol.proto.DatanodeProtocolProtos.BlockCommandProto;
079import org.apache.hadoop.hdfs.protocol.proto.DatanodeProtocolProtos.BlockIdCommandProto;
080import org.apache.hadoop.hdfs.protocol.proto.DatanodeProtocolProtos.BlockRecoveryCommandProto;
081import org.apache.hadoop.hdfs.protocol.proto.DatanodeProtocolProtos.DatanodeCommandProto;
082import org.apache.hadoop.hdfs.protocol.proto.DatanodeProtocolProtos.DatanodeRegistrationProto;
083import org.apache.hadoop.hdfs.protocol.proto.DatanodeProtocolProtos.DatanodeStorageProto;
084import org.apache.hadoop.hdfs.protocol.proto.DatanodeProtocolProtos.DatanodeStorageProto.StorageState;
085import org.apache.hadoop.hdfs.protocol.proto.DatanodeProtocolProtos.FinalizeCommandProto;
086import org.apache.hadoop.hdfs.protocol.proto.DatanodeProtocolProtos.KeyUpdateCommandProto;
087import org.apache.hadoop.hdfs.protocol.proto.DatanodeProtocolProtos.NNHAStatusHeartbeatProto;
088import org.apache.hadoop.hdfs.protocol.proto.DatanodeProtocolProtos.ReceivedDeletedBlockInfoProto;
089import org.apache.hadoop.hdfs.protocol.proto.DatanodeProtocolProtos.RegisterCommandProto;
090import org.apache.hadoop.hdfs.protocol.proto.DatanodeProtocolProtos.StorageReportProto;
091import org.apache.hadoop.hdfs.protocol.proto.HdfsProtos;
092import org.apache.hadoop.hdfs.protocol.proto.HdfsProtos.BlockKeyProto;
093import org.apache.hadoop.hdfs.protocol.proto.HdfsProtos.BlockProto;
094import org.apache.hadoop.hdfs.protocol.proto.HdfsProtos.BlockWithLocationsProto;
095import org.apache.hadoop.hdfs.protocol.proto.HdfsProtos.BlocksWithLocationsProto;
096import org.apache.hadoop.hdfs.protocol.proto.HdfsProtos.CheckpointCommandProto;
097import org.apache.hadoop.hdfs.protocol.proto.HdfsProtos.CheckpointSignatureProto;
098import org.apache.hadoop.hdfs.protocol.proto.HdfsProtos.ContentSummaryProto;
099import org.apache.hadoop.hdfs.protocol.proto.HdfsProtos.CorruptFileBlocksProto;
100import org.apache.hadoop.hdfs.protocol.proto.HdfsProtos.DataEncryptionKeyProto;
101import org.apache.hadoop.hdfs.protocol.proto.HdfsProtos.DatanodeIDProto;
102import org.apache.hadoop.hdfs.protocol.proto.HdfsProtos.DatanodeInfoProto;
103import org.apache.hadoop.hdfs.protocol.proto.HdfsProtos.DatanodeInfoProto.AdminState;
104import org.apache.hadoop.hdfs.protocol.proto.HdfsProtos.DatanodeInfosProto;
105import org.apache.hadoop.hdfs.protocol.proto.HdfsProtos.DirectoryListingProto;
106import org.apache.hadoop.hdfs.protocol.proto.HdfsProtos.ExportedBlockKeysProto;
107import org.apache.hadoop.hdfs.protocol.proto.HdfsProtos.ExtendedBlockProto;
108import org.apache.hadoop.hdfs.protocol.proto.HdfsProtos.FsPermissionProto;
109import org.apache.hadoop.hdfs.protocol.proto.HdfsProtos.FsServerDefaultsProto;
110import org.apache.hadoop.hdfs.protocol.proto.HdfsProtos.HdfsFileStatusProto;
111import org.apache.hadoop.hdfs.protocol.proto.HdfsProtos.HdfsFileStatusProto.FileType;
112import org.apache.hadoop.hdfs.protocol.proto.HdfsProtos.LocatedBlockProto;
113import org.apache.hadoop.hdfs.protocol.proto.HdfsProtos.LocatedBlockProto.Builder;
114import org.apache.hadoop.hdfs.protocol.proto.HdfsProtos.LocatedBlocksProto;
115import org.apache.hadoop.hdfs.protocol.proto.HdfsProtos.NamenodeCommandProto;
116import org.apache.hadoop.hdfs.protocol.proto.HdfsProtos.NamenodeRegistrationProto;
117import org.apache.hadoop.hdfs.protocol.proto.HdfsProtos.NamenodeRegistrationProto.NamenodeRoleProto;
118import org.apache.hadoop.hdfs.protocol.proto.HdfsProtos.NamespaceInfoProto;
119import org.apache.hadoop.hdfs.protocol.proto.HdfsProtos.RecoveringBlockProto;
120import org.apache.hadoop.hdfs.protocol.proto.HdfsProtos.RemoteEditLogManifestProto;
121import org.apache.hadoop.hdfs.protocol.proto.HdfsProtos.RemoteEditLogProto;
122import org.apache.hadoop.hdfs.protocol.proto.HdfsProtos.ReplicaStateProto;
123import org.apache.hadoop.hdfs.protocol.proto.HdfsProtos.SnapshotDiffReportEntryProto;
124import org.apache.hadoop.hdfs.protocol.proto.HdfsProtos.SnapshotDiffReportProto;
125import org.apache.hadoop.hdfs.protocol.proto.HdfsProtos.SnapshottableDirectoryListingProto;
126import org.apache.hadoop.hdfs.protocol.proto.HdfsProtos.SnapshottableDirectoryStatusProto;
127import org.apache.hadoop.hdfs.protocol.proto.HdfsProtos.StorageInfoProto;
128import org.apache.hadoop.hdfs.protocol.proto.HdfsProtos.StorageTypeProto;
129import org.apache.hadoop.hdfs.protocol.proto.HdfsProtos.StorageUuidsProto;
130import org.apache.hadoop.hdfs.protocol.proto.JournalProtocolProtos.JournalInfoProto;
131import org.apache.hadoop.hdfs.security.token.block.BlockKey;
132import org.apache.hadoop.hdfs.security.token.block.BlockTokenIdentifier;
133import org.apache.hadoop.hdfs.security.token.block.DataEncryptionKey;
134import org.apache.hadoop.hdfs.security.token.block.ExportedBlockKeys;
135import org.apache.hadoop.hdfs.security.token.delegation.DelegationTokenIdentifier;
136import org.apache.hadoop.hdfs.server.common.HdfsServerConstants.NamenodeRole;
137import org.apache.hadoop.hdfs.server.common.HdfsServerConstants.ReplicaState;
138import org.apache.hadoop.hdfs.server.common.StorageInfo;
139import org.apache.hadoop.hdfs.server.namenode.CheckpointSignature;
140import org.apache.hadoop.hdfs.server.namenode.INodeId;
141import org.apache.hadoop.hdfs.server.protocol.BalancerBandwidthCommand;
142import org.apache.hadoop.hdfs.server.protocol.BlockCommand;
143import org.apache.hadoop.hdfs.server.protocol.BlockIdCommand;
144import org.apache.hadoop.hdfs.server.protocol.BlockRecoveryCommand;
145import org.apache.hadoop.hdfs.server.protocol.BlockRecoveryCommand.RecoveringBlock;
146import org.apache.hadoop.hdfs.server.protocol.BlocksWithLocations;
147import org.apache.hadoop.hdfs.server.protocol.BlocksWithLocations.BlockWithLocations;
148import org.apache.hadoop.hdfs.server.protocol.CheckpointCommand;
149import org.apache.hadoop.hdfs.server.protocol.DatanodeCommand;
150import org.apache.hadoop.hdfs.server.protocol.DatanodeProtocol;
151import org.apache.hadoop.hdfs.server.protocol.DatanodeRegistration;
152import org.apache.hadoop.hdfs.server.protocol.DatanodeStorage;
153import org.apache.hadoop.hdfs.server.protocol.DatanodeStorage.State;
154import org.apache.hadoop.hdfs.server.protocol.FinalizeCommand;
155import org.apache.hadoop.hdfs.server.protocol.JournalInfo;
156import org.apache.hadoop.hdfs.server.protocol.KeyUpdateCommand;
157import org.apache.hadoop.hdfs.server.protocol.NNHAStatusHeartbeat;
158import org.apache.hadoop.hdfs.server.protocol.NamenodeCommand;
159import org.apache.hadoop.hdfs.server.protocol.NamenodeRegistration;
160import org.apache.hadoop.hdfs.server.protocol.NamespaceInfo;
161import org.apache.hadoop.hdfs.server.protocol.ReceivedDeletedBlockInfo;
162import org.apache.hadoop.hdfs.server.protocol.ReceivedDeletedBlockInfo.BlockStatus;
163import org.apache.hadoop.hdfs.server.protocol.RegisterCommand;
164import org.apache.hadoop.hdfs.server.protocol.RemoteEditLog;
165import org.apache.hadoop.hdfs.server.protocol.RemoteEditLogManifest;
166import org.apache.hadoop.hdfs.server.protocol.StorageReport;
167import org.apache.hadoop.hdfs.util.ExactSizeInputStream;
168import org.apache.hadoop.io.EnumSetWritable;
169import org.apache.hadoop.io.Text;
170import org.apache.hadoop.security.proto.SecurityProtos.TokenProto;
171import org.apache.hadoop.security.token.Token;
172import org.apache.hadoop.util.DataChecksum;
173
174import com.google.common.base.Preconditions;
175import com.google.common.collect.Lists;
176import com.google.common.primitives.Shorts;
177import com.google.protobuf.ByteString;
178import com.google.protobuf.CodedInputStream;
179
180/**
181 * Utilities for converting protobuf classes to and from implementation classes
182 * and other helper utilities to help in dealing with protobuf.
183 * 
184 * Note that when converting from an internal type to protobuf type, the
185 * converter never return null for protobuf type. The check for internal type
186 * being null must be done before calling the convert() method.
187 */
188public class PBHelper {
189  private static final RegisterCommandProto REG_CMD_PROTO = 
190      RegisterCommandProto.newBuilder().build();
191  private static final RegisterCommand REG_CMD = new RegisterCommand();
192
193  private PBHelper() {
194    /** Hidden constructor */
195  }
196
197  public static ByteString getByteString(byte[] bytes) {
198    return ByteString.copyFrom(bytes);
199  }
200
201  public static NamenodeRole convert(NamenodeRoleProto role) {
202    switch (role) {
203    case NAMENODE:
204      return NamenodeRole.NAMENODE;
205    case BACKUP:
206      return NamenodeRole.BACKUP;
207    case CHECKPOINT:
208      return NamenodeRole.CHECKPOINT;
209    }
210    return null;
211  }
212
213  public static NamenodeRoleProto convert(NamenodeRole role) {
214    switch (role) {
215    case NAMENODE:
216      return NamenodeRoleProto.NAMENODE;
217    case BACKUP:
218      return NamenodeRoleProto.BACKUP;
219    case CHECKPOINT:
220      return NamenodeRoleProto.CHECKPOINT;
221    }
222    return null;
223  }
224
225  public static StorageInfoProto convert(StorageInfo info) {
226    return StorageInfoProto.newBuilder().setClusterID(info.getClusterID())
227        .setCTime(info.getCTime()).setLayoutVersion(info.getLayoutVersion())
228        .setNamespceID(info.getNamespaceID()).build();
229  }
230
231  public static StorageInfo convert(StorageInfoProto info) {
232    return new StorageInfo(info.getLayoutVersion(), info.getNamespceID(),
233        info.getClusterID(), info.getCTime());
234  }
235
236  public static NamenodeRegistrationProto convert(NamenodeRegistration reg) {
237    return NamenodeRegistrationProto.newBuilder()
238        .setHttpAddress(reg.getHttpAddress()).setRole(convert(reg.getRole()))
239        .setRpcAddress(reg.getAddress())
240        .setStorageInfo(convert((StorageInfo) reg)).build();
241  }
242
243  public static NamenodeRegistration convert(NamenodeRegistrationProto reg) {
244    return new NamenodeRegistration(reg.getRpcAddress(), reg.getHttpAddress(),
245        convert(reg.getStorageInfo()), convert(reg.getRole()));
246  }
247
248  // DatanodeId
249  public static DatanodeID convert(DatanodeIDProto dn) {
250    return new DatanodeID(dn.getIpAddr(), dn.getHostName(), dn.getDatanodeUuid(),
251        dn.getXferPort(), dn.getInfoPort(), dn.hasInfoSecurePort() ? dn
252        .getInfoSecurePort() : 0, dn.getIpcPort());
253  }
254
255  public static DatanodeIDProto convert(DatanodeID dn) {
256    // For wire compatibility with older versions we transmit the StorageID
257    // which is the same as the DatanodeUuid. Since StorageID is a required
258    // field we pass the empty string if the DatanodeUuid is not yet known.
259    return DatanodeIDProto.newBuilder()
260        .setIpAddr(dn.getIpAddr())
261        .setHostName(dn.getHostName())
262        .setXferPort(dn.getXferPort())
263        .setDatanodeUuid(dn.getDatanodeUuid() != null ? dn.getDatanodeUuid() : "")
264        .setInfoPort(dn.getInfoPort())
265        .setInfoSecurePort(dn.getInfoSecurePort())
266        .setIpcPort(dn.getIpcPort()).build();
267  }
268
269  // Arrays of DatanodeId
270  public static DatanodeIDProto[] convert(DatanodeID[] did) {
271    if (did == null)
272      return null;
273    final int len = did.length;
274    DatanodeIDProto[] result = new DatanodeIDProto[len];
275    for (int i = 0; i < len; ++i) {
276      result[i] = convert(did[i]);
277    }
278    return result;
279  }
280  
281  public static DatanodeID[] convert(DatanodeIDProto[] did) {
282    if (did == null) return null;
283    final int len = did.length;
284    DatanodeID[] result = new DatanodeID[len];
285    for (int i = 0; i < len; ++i) {
286      result[i] = convert(did[i]);
287    }
288    return result;
289  }
290  
291  // Block
292  public static BlockProto convert(Block b) {
293    return BlockProto.newBuilder().setBlockId(b.getBlockId())
294        .setGenStamp(b.getGenerationStamp()).setNumBytes(b.getNumBytes())
295        .build();
296  }
297
298  public static Block convert(BlockProto b) {
299    return new Block(b.getBlockId(), b.getNumBytes(), b.getGenStamp());
300  }
301
302  public static BlockWithLocationsProto convert(BlockWithLocations blk) {
303    return BlockWithLocationsProto.newBuilder()
304        .setBlock(convert(blk.getBlock()))
305        .addAllDatanodeUuids(Arrays.asList(blk.getDatanodeUuids()))
306        .addAllStorageUuids(Arrays.asList(blk.getStorageIDs())).build();
307  }
308
309  public static BlockWithLocations convert(BlockWithLocationsProto b) {
310    final List<String> datanodeUuids = b.getDatanodeUuidsList();
311    final List<String> storageUuids = b.getStorageUuidsList();
312    return new BlockWithLocations(convert(b.getBlock()),
313        datanodeUuids.toArray(new String[datanodeUuids.size()]),
314        storageUuids.toArray(new String[storageUuids.size()]));
315  }
316
317  public static BlocksWithLocationsProto convert(BlocksWithLocations blks) {
318    BlocksWithLocationsProto.Builder builder = BlocksWithLocationsProto
319        .newBuilder();
320    for (BlockWithLocations b : blks.getBlocks()) {
321      builder.addBlocks(convert(b));
322    }
323    return builder.build();
324  }
325
326  public static BlocksWithLocations convert(BlocksWithLocationsProto blocks) {
327    List<BlockWithLocationsProto> b = blocks.getBlocksList();
328    BlockWithLocations[] ret = new BlockWithLocations[b.size()];
329    int i = 0;
330    for (BlockWithLocationsProto entry : b) {
331      ret[i++] = convert(entry);
332    }
333    return new BlocksWithLocations(ret);
334  }
335
336  public static BlockKeyProto convert(BlockKey key) {
337    byte[] encodedKey = key.getEncodedKey();
338    ByteString keyBytes = ByteString.copyFrom(encodedKey == null ? 
339        DFSUtil.EMPTY_BYTES : encodedKey);
340    return BlockKeyProto.newBuilder().setKeyId(key.getKeyId())
341        .setKeyBytes(keyBytes).setExpiryDate(key.getExpiryDate()).build();
342  }
343
344  public static BlockKey convert(BlockKeyProto k) {
345    return new BlockKey(k.getKeyId(), k.getExpiryDate(), k.getKeyBytes()
346        .toByteArray());
347  }
348
349  public static ExportedBlockKeysProto convert(ExportedBlockKeys keys) {
350    ExportedBlockKeysProto.Builder builder = ExportedBlockKeysProto
351        .newBuilder();
352    builder.setIsBlockTokenEnabled(keys.isBlockTokenEnabled())
353        .setKeyUpdateInterval(keys.getKeyUpdateInterval())
354        .setTokenLifeTime(keys.getTokenLifetime())
355        .setCurrentKey(convert(keys.getCurrentKey()));
356    for (BlockKey k : keys.getAllKeys()) {
357      builder.addAllKeys(convert(k));
358    }
359    return builder.build();
360  }
361
362  public static ExportedBlockKeys convert(ExportedBlockKeysProto keys) {
363    return new ExportedBlockKeys(keys.getIsBlockTokenEnabled(),
364        keys.getKeyUpdateInterval(), keys.getTokenLifeTime(),
365        convert(keys.getCurrentKey()), convertBlockKeys(keys.getAllKeysList()));
366  }
367
368  public static CheckpointSignatureProto convert(CheckpointSignature s) {
369    return CheckpointSignatureProto.newBuilder()
370        .setBlockPoolId(s.getBlockpoolID())
371        .setCurSegmentTxId(s.getCurSegmentTxId())
372        .setMostRecentCheckpointTxId(s.getMostRecentCheckpointTxId())
373        .setStorageInfo(PBHelper.convert((StorageInfo) s)).build();
374  }
375
376  public static CheckpointSignature convert(CheckpointSignatureProto s) {
377    return new CheckpointSignature(PBHelper.convert(s.getStorageInfo()),
378        s.getBlockPoolId(), s.getMostRecentCheckpointTxId(),
379        s.getCurSegmentTxId());
380  }
381
382  public static RemoteEditLogProto convert(RemoteEditLog log) {
383    return RemoteEditLogProto.newBuilder()
384        .setStartTxId(log.getStartTxId())
385        .setEndTxId(log.getEndTxId())
386        .setIsInProgress(log.isInProgress()).build();
387  }
388
389  public static RemoteEditLog convert(RemoteEditLogProto l) {
390    return new RemoteEditLog(l.getStartTxId(), l.getEndTxId(),
391        l.getIsInProgress());
392  }
393
394  public static RemoteEditLogManifestProto convert(
395      RemoteEditLogManifest manifest) {
396    RemoteEditLogManifestProto.Builder builder = RemoteEditLogManifestProto
397        .newBuilder();
398    for (RemoteEditLog log : manifest.getLogs()) {
399      builder.addLogs(convert(log));
400    }
401    return builder.build();
402  }
403
404  public static RemoteEditLogManifest convert(
405      RemoteEditLogManifestProto manifest) {
406    List<RemoteEditLog> logs = new ArrayList<RemoteEditLog>(manifest
407        .getLogsList().size());
408    for (RemoteEditLogProto l : manifest.getLogsList()) {
409      logs.add(convert(l));
410    }
411    return new RemoteEditLogManifest(logs);
412  }
413
414  public static CheckpointCommandProto convert(CheckpointCommand cmd) {
415    return CheckpointCommandProto.newBuilder()
416        .setSignature(convert(cmd.getSignature()))
417        .setNeedToReturnImage(cmd.needToReturnImage()).build();
418  }
419
420  public static NamenodeCommandProto convert(NamenodeCommand cmd) {
421    if (cmd instanceof CheckpointCommand) {
422      return NamenodeCommandProto.newBuilder().setAction(cmd.getAction())
423          .setType(NamenodeCommandProto.Type.CheckPointCommand)
424          .setCheckpointCmd(convert((CheckpointCommand) cmd)).build();
425    }
426    return NamenodeCommandProto.newBuilder()
427        .setType(NamenodeCommandProto.Type.NamenodeCommand)
428        .setAction(cmd.getAction()).build();
429  }
430
431  public static BlockKey[] convertBlockKeys(List<BlockKeyProto> list) {
432    BlockKey[] ret = new BlockKey[list.size()];
433    int i = 0;
434    for (BlockKeyProto k : list) {
435      ret[i++] = convert(k);
436    }
437    return ret;
438  }
439
440  public static NamespaceInfo convert(NamespaceInfoProto info) {
441    StorageInfoProto storage = info.getStorageInfo();
442    return new NamespaceInfo(storage.getNamespceID(), storage.getClusterID(),
443        info.getBlockPoolID(), storage.getCTime(), info.getBuildVersion(),
444        info.getSoftwareVersion());
445  }
446
447  public static NamenodeCommand convert(NamenodeCommandProto cmd) {
448    if (cmd == null) return null;
449    switch (cmd.getType()) {
450    case CheckPointCommand:
451      CheckpointCommandProto chkPt = cmd.getCheckpointCmd();
452      return new CheckpointCommand(PBHelper.convert(chkPt.getSignature()),
453          chkPt.getNeedToReturnImage());
454    default:
455      return new NamenodeCommand(cmd.getAction());
456    }
457  }
458  
459  public static ExtendedBlock convert(ExtendedBlockProto eb) {
460    if (eb == null) return null;
461    return new ExtendedBlock( eb.getPoolId(),  eb.getBlockId(),   eb.getNumBytes(),
462       eb.getGenerationStamp());
463  }
464  
465  public static ExtendedBlockProto convert(final ExtendedBlock b) {
466    if (b == null) return null;
467   return ExtendedBlockProto.newBuilder().
468      setPoolId(b.getBlockPoolId()).
469      setBlockId(b.getBlockId()).
470      setNumBytes(b.getNumBytes()).
471      setGenerationStamp(b.getGenerationStamp()).
472      build();
473  }
474  
475  public static RecoveringBlockProto convert(RecoveringBlock b) {
476    if (b == null) {
477      return null;
478    }
479    LocatedBlockProto lb = PBHelper.convert((LocatedBlock)b);
480    return RecoveringBlockProto.newBuilder().setBlock(lb)
481        .setNewGenStamp(b.getNewGenerationStamp()).build();
482  }
483
484  public static RecoveringBlock convert(RecoveringBlockProto b) {
485    ExtendedBlock block = convert(b.getBlock().getB());
486    DatanodeInfo[] locs = convert(b.getBlock().getLocsList());
487    return new RecoveringBlock(block, locs, b.getNewGenStamp());
488  }
489  
490  public static DatanodeInfoProto.AdminState convert(
491      final DatanodeInfo.AdminStates inAs) {
492    switch (inAs) {
493    case NORMAL: return  DatanodeInfoProto.AdminState.NORMAL;
494    case DECOMMISSION_INPROGRESS: 
495        return DatanodeInfoProto.AdminState.DECOMMISSION_INPROGRESS;
496    case DECOMMISSIONED: return DatanodeInfoProto.AdminState.DECOMMISSIONED;
497    default: return DatanodeInfoProto.AdminState.NORMAL;
498    }
499  }
500  
501  static public DatanodeInfo convert(DatanodeInfoProto di) {
502    if (di == null) return null;
503    return new DatanodeInfo(
504        PBHelper.convert(di.getId()),
505        di.hasLocation() ? di.getLocation() : null , 
506        di.getCapacity(),  di.getDfsUsed(),  di.getRemaining(),
507        di.getBlockPoolUsed(), di.getCacheCapacity(), di.getCacheUsed(),
508        di.getLastUpdate(), di.getXceiverCount(),
509        PBHelper.convert(di.getAdminState())); 
510  }
511  
512  static public DatanodeInfoProto convertDatanodeInfo(DatanodeInfo di) {
513    if (di == null) return null;
514    return convert(di);
515  }
516  
517  
518  static public DatanodeInfo[] convert(DatanodeInfoProto di[]) {
519    if (di == null) return null;
520    DatanodeInfo[] result = new DatanodeInfo[di.length];
521    for (int i = 0; i < di.length; i++) {
522      result[i] = convert(di[i]);
523    }    
524    return result;
525  }
526
527  public static List<? extends HdfsProtos.DatanodeInfoProto> convert(
528      DatanodeInfo[] dnInfos) {
529    return convert(dnInfos, 0);
530  }
531  
532  /**
533   * Copy from {@code dnInfos} to a target of list of same size starting at
534   * {@code startIdx}.
535   */
536  public static List<? extends HdfsProtos.DatanodeInfoProto> convert(
537      DatanodeInfo[] dnInfos, int startIdx) {
538    if (dnInfos == null)
539      return null;
540    ArrayList<HdfsProtos.DatanodeInfoProto> protos = Lists
541        .newArrayListWithCapacity(dnInfos.length);
542    for (int i = startIdx; i < dnInfos.length; i++) {
543      protos.add(convert(dnInfos[i]));
544    }
545    return protos;
546  }
547
548  public static DatanodeInfo[] convert(List<DatanodeInfoProto> list) {
549    DatanodeInfo[] info = new DatanodeInfo[list.size()];
550    for (int i = 0; i < info.length; i++) {
551      info[i] = convert(list.get(i));
552    }
553    return info;
554  }
555  
556  public static DatanodeInfoProto convert(DatanodeInfo info) {
557    DatanodeInfoProto.Builder builder = DatanodeInfoProto.newBuilder();
558    if (info.getNetworkLocation() != null) {
559      builder.setLocation(info.getNetworkLocation());
560    }
561    builder
562        .setId(PBHelper.convert((DatanodeID)info))
563        .setCapacity(info.getCapacity())
564        .setDfsUsed(info.getDfsUsed())
565        .setRemaining(info.getRemaining())
566        .setBlockPoolUsed(info.getBlockPoolUsed())
567        .setCacheCapacity(info.getCacheCapacity())
568        .setCacheUsed(info.getCacheUsed())
569        .setLastUpdate(info.getLastUpdate())
570        .setXceiverCount(info.getXceiverCount())
571        .setAdminState(PBHelper.convert(info.getAdminState()))
572        .build();
573    return builder.build();
574  }
575
576  public static AdminStates convert(AdminState adminState) {
577    switch(adminState) {
578    case DECOMMISSION_INPROGRESS:
579      return AdminStates.DECOMMISSION_INPROGRESS;
580    case DECOMMISSIONED:
581      return AdminStates.DECOMMISSIONED;
582    case NORMAL:
583    default:
584      return AdminStates.NORMAL;
585    }
586  }
587  
588  public static LocatedBlockProto convert(LocatedBlock b) {
589    if (b == null) return null;
590    Builder builder = LocatedBlockProto.newBuilder();
591    DatanodeInfo[] locs = b.getLocations();
592    List<DatanodeInfo> cachedLocs =
593        Lists.newLinkedList(Arrays.asList(b.getCachedLocations()));
594    for (int i = 0; i < locs.length; i++) {
595      DatanodeInfo loc = locs[i];
596      builder.addLocs(i, PBHelper.convert(loc));
597      boolean locIsCached = cachedLocs.contains(loc);
598      builder.addIsCached(locIsCached);
599      if (locIsCached) {
600        cachedLocs.remove(loc);
601      }
602    }
603    Preconditions.checkArgument(cachedLocs.size() == 0,
604        "Found additional cached replica locations that are not in the set of"
605        + " storage-backed locations!");
606
607    StorageType[] storageTypes = b.getStorageTypes();
608    if (storageTypes != null) {
609      for (int i = 0; i < storageTypes.length; ++i) {
610        builder.addStorageTypes(PBHelper.convertStorageType(storageTypes[i]));
611      }
612    }
613    final String[] storageIDs = b.getStorageIDs();
614    if (storageIDs != null) {
615      builder.addAllStorageIDs(Arrays.asList(storageIDs));
616    }
617
618    return builder.setB(PBHelper.convert(b.getBlock()))
619        .setBlockToken(PBHelper.convert(b.getBlockToken()))
620        .setCorrupt(b.isCorrupt()).setOffset(b.getStartOffset()).build();
621  }
622  
623  public static LocatedBlock convert(LocatedBlockProto proto) {
624    if (proto == null) return null;
625    List<DatanodeInfoProto> locs = proto.getLocsList();
626    DatanodeInfo[] targets = new DatanodeInfo[locs.size()];
627    for (int i = 0; i < locs.size(); i++) {
628      targets[i] = PBHelper.convert(locs.get(i));
629    }
630
631    final int storageTypesCount = proto.getStorageTypesCount();
632    final StorageType[] storageTypes;
633    if (storageTypesCount == 0) {
634      storageTypes = null;
635    } else {
636      Preconditions.checkState(storageTypesCount == locs.size());
637      storageTypes = convertStorageTypeProtos(proto.getStorageTypesList());
638    }
639
640    final int storageIDsCount = proto.getStorageIDsCount();
641    final String[] storageIDs;
642    if (storageIDsCount == 0) {
643      storageIDs = null;
644    } else {
645      Preconditions.checkState(storageIDsCount == locs.size());
646      storageIDs = proto.getStorageIDsList().toArray(new String[storageIDsCount]);
647    }
648
649    // Set values from the isCached list, re-using references from loc
650    List<DatanodeInfo> cachedLocs = new ArrayList<DatanodeInfo>(locs.size());
651    List<Boolean> isCachedList = proto.getIsCachedList();
652    for (int i=0; i<isCachedList.size(); i++) {
653      if (isCachedList.get(i)) {
654        cachedLocs.add(targets[i]);
655      }
656    }
657
658    LocatedBlock lb = new LocatedBlock(PBHelper.convert(proto.getB()), targets,
659        storageIDs, storageTypes, proto.getOffset(), proto.getCorrupt(),
660        cachedLocs.toArray(new DatanodeInfo[0]));
661    lb.setBlockToken(PBHelper.convert(proto.getBlockToken()));
662
663    return lb;
664  }
665
666  public static TokenProto convert(Token<?> tok) {
667    return TokenProto.newBuilder().
668              setIdentifier(ByteString.copyFrom(tok.getIdentifier())).
669              setPassword(ByteString.copyFrom(tok.getPassword())).
670              setKind(tok.getKind().toString()).
671              setService(tok.getService().toString()).build(); 
672  }
673  
674  public static Token<BlockTokenIdentifier> convert(
675      TokenProto blockToken) {
676    return new Token<BlockTokenIdentifier>(blockToken.getIdentifier()
677        .toByteArray(), blockToken.getPassword().toByteArray(), new Text(
678        blockToken.getKind()), new Text(blockToken.getService()));
679  }
680
681  
682  public static Token<DelegationTokenIdentifier> convertDelegationToken(
683      TokenProto blockToken) {
684    return new Token<DelegationTokenIdentifier>(blockToken.getIdentifier()
685        .toByteArray(), blockToken.getPassword().toByteArray(), new Text(
686        blockToken.getKind()), new Text(blockToken.getService()));
687  }
688
689  public static ReplicaState convert(ReplicaStateProto state) {
690    switch (state) {
691    case RBW:
692      return ReplicaState.RBW;
693    case RUR:
694      return ReplicaState.RUR;
695    case RWR:
696      return ReplicaState.RWR;
697    case TEMPORARY:
698      return ReplicaState.TEMPORARY;
699    case FINALIZED:
700    default:
701      return ReplicaState.FINALIZED;
702    }
703  }
704
705  public static ReplicaStateProto convert(ReplicaState state) {
706    switch (state) {
707    case RBW:
708      return ReplicaStateProto.RBW;
709    case RUR:
710      return ReplicaStateProto.RUR;
711    case RWR:
712      return ReplicaStateProto.RWR;
713    case TEMPORARY:
714      return ReplicaStateProto.TEMPORARY;
715    case FINALIZED:
716    default:
717      return ReplicaStateProto.FINALIZED;
718    }
719  }
720  
721  public static DatanodeRegistrationProto convert(
722      DatanodeRegistration registration) {
723    DatanodeRegistrationProto.Builder builder = DatanodeRegistrationProto
724        .newBuilder();
725    return builder.setDatanodeID(PBHelper.convert((DatanodeID) registration))
726        .setStorageInfo(PBHelper.convert(registration.getStorageInfo()))
727        .setKeys(PBHelper.convert(registration.getExportedKeys()))
728        .setSoftwareVersion(registration.getSoftwareVersion()).build();
729  }
730
731  public static DatanodeRegistration convert(DatanodeRegistrationProto proto) {
732    return new DatanodeRegistration(PBHelper.convert(proto.getDatanodeID()),
733        PBHelper.convert(proto.getStorageInfo()), PBHelper.convert(proto
734            .getKeys()), proto.getSoftwareVersion());
735  }
736
737  public static DatanodeCommand convert(DatanodeCommandProto proto) {
738    switch (proto.getCmdType()) {
739    case BalancerBandwidthCommand:
740      return PBHelper.convert(proto.getBalancerCmd());
741    case BlockCommand:
742      return PBHelper.convert(proto.getBlkCmd());
743    case BlockRecoveryCommand:
744      return PBHelper.convert(proto.getRecoveryCmd());
745    case FinalizeCommand:
746      return PBHelper.convert(proto.getFinalizeCmd());
747    case KeyUpdateCommand:
748      return PBHelper.convert(proto.getKeyUpdateCmd());
749    case RegisterCommand:
750      return REG_CMD;
751    case BlockIdCommand:
752      return PBHelper.convert(proto.getBlkIdCmd());
753    }
754    return null;
755  }
756  
757  public static BalancerBandwidthCommandProto convert(
758      BalancerBandwidthCommand bbCmd) {
759    return BalancerBandwidthCommandProto.newBuilder()
760        .setBandwidth(bbCmd.getBalancerBandwidthValue()).build();
761  }
762
763  public static KeyUpdateCommandProto convert(KeyUpdateCommand cmd) {
764    return KeyUpdateCommandProto.newBuilder()
765        .setKeys(PBHelper.convert(cmd.getExportedKeys())).build();
766  }
767
768  public static BlockRecoveryCommandProto convert(BlockRecoveryCommand cmd) {
769    BlockRecoveryCommandProto.Builder builder = BlockRecoveryCommandProto
770        .newBuilder();
771    for (RecoveringBlock b : cmd.getRecoveringBlocks()) {
772      builder.addBlocks(PBHelper.convert(b));
773    }
774    return builder.build();
775  }
776
777  public static FinalizeCommandProto convert(FinalizeCommand cmd) {
778    return FinalizeCommandProto.newBuilder()
779        .setBlockPoolId(cmd.getBlockPoolId()).build();
780  }
781
782  public static BlockCommandProto convert(BlockCommand cmd) {
783    BlockCommandProto.Builder builder = BlockCommandProto.newBuilder()
784        .setBlockPoolId(cmd.getBlockPoolId());
785    switch (cmd.getAction()) {
786    case DatanodeProtocol.DNA_TRANSFER:
787      builder.setAction(BlockCommandProto.Action.TRANSFER);
788      break;
789    case DatanodeProtocol.DNA_INVALIDATE:
790      builder.setAction(BlockCommandProto.Action.INVALIDATE);
791      break;
792    case DatanodeProtocol.DNA_SHUTDOWN:
793      builder.setAction(BlockCommandProto.Action.SHUTDOWN);
794      break;
795    default:
796      throw new AssertionError("Invalid action");
797    }
798    Block[] blocks = cmd.getBlocks();
799    for (int i = 0; i < blocks.length; i++) {
800      builder.addBlocks(PBHelper.convert(blocks[i]));
801    }
802    builder.addAllTargets(convert(cmd.getTargets()))
803           .addAllTargetStorageUuids(convert(cmd.getTargetStorageIDs()));
804    return builder.build();
805  }
806  
807  public static BlockIdCommandProto convert(BlockIdCommand cmd) {
808    BlockIdCommandProto.Builder builder = BlockIdCommandProto.newBuilder()
809        .setBlockPoolId(cmd.getBlockPoolId());
810    switch (cmd.getAction()) {
811    case DatanodeProtocol.DNA_CACHE:
812      builder.setAction(BlockIdCommandProto.Action.CACHE);
813      break;
814    case DatanodeProtocol.DNA_UNCACHE:
815      builder.setAction(BlockIdCommandProto.Action.UNCACHE);
816      break;
817    default:
818      throw new AssertionError("Invalid action");
819    }
820    long[] blockIds = cmd.getBlockIds();
821    for (int i = 0; i < blockIds.length; i++) {
822      builder.addBlockIds(blockIds[i]);
823    }
824    return builder.build();
825  }
826
827  private static List<DatanodeInfosProto> convert(DatanodeInfo[][] targets) {
828    DatanodeInfosProto[] ret = new DatanodeInfosProto[targets.length];
829    for (int i = 0; i < targets.length; i++) {
830      ret[i] = DatanodeInfosProto.newBuilder()
831          .addAllDatanodes(PBHelper.convert(targets[i])).build();
832    }
833    return Arrays.asList(ret);
834  }
835
836  private static List<StorageUuidsProto> convert(String[][] targetStorageUuids) {
837    StorageUuidsProto[] ret = new StorageUuidsProto[targetStorageUuids.length];
838    for (int i = 0; i < targetStorageUuids.length; i++) {
839      ret[i] = StorageUuidsProto.newBuilder()
840          .addAllStorageUuids(Arrays.asList(targetStorageUuids[i])).build();
841    }
842    return Arrays.asList(ret);
843  }
844
845  public static DatanodeCommandProto convert(DatanodeCommand datanodeCommand) {
846    DatanodeCommandProto.Builder builder = DatanodeCommandProto.newBuilder();
847    if (datanodeCommand == null) {
848      return builder.setCmdType(DatanodeCommandProto.Type.NullDatanodeCommand)
849          .build();
850    }
851    switch (datanodeCommand.getAction()) {
852    case DatanodeProtocol.DNA_BALANCERBANDWIDTHUPDATE:
853      builder.setCmdType(DatanodeCommandProto.Type.BalancerBandwidthCommand)
854          .setBalancerCmd(
855              PBHelper.convert((BalancerBandwidthCommand) datanodeCommand));
856      break;
857    case DatanodeProtocol.DNA_ACCESSKEYUPDATE:
858      builder
859          .setCmdType(DatanodeCommandProto.Type.KeyUpdateCommand)
860          .setKeyUpdateCmd(PBHelper.convert((KeyUpdateCommand) datanodeCommand));
861      break;
862    case DatanodeProtocol.DNA_RECOVERBLOCK:
863      builder.setCmdType(DatanodeCommandProto.Type.BlockRecoveryCommand)
864          .setRecoveryCmd(
865              PBHelper.convert((BlockRecoveryCommand) datanodeCommand));
866      break;
867    case DatanodeProtocol.DNA_FINALIZE:
868      builder.setCmdType(DatanodeCommandProto.Type.FinalizeCommand)
869          .setFinalizeCmd(PBHelper.convert((FinalizeCommand) datanodeCommand));
870      break;
871    case DatanodeProtocol.DNA_REGISTER:
872      builder.setCmdType(DatanodeCommandProto.Type.RegisterCommand)
873          .setRegisterCmd(REG_CMD_PROTO);
874      break;
875    case DatanodeProtocol.DNA_TRANSFER:
876    case DatanodeProtocol.DNA_INVALIDATE:
877    case DatanodeProtocol.DNA_SHUTDOWN:
878      builder.setCmdType(DatanodeCommandProto.Type.BlockCommand).
879        setBlkCmd(PBHelper.convert((BlockCommand) datanodeCommand));
880      break;
881    case DatanodeProtocol.DNA_CACHE:
882    case DatanodeProtocol.DNA_UNCACHE:
883      builder.setCmdType(DatanodeCommandProto.Type.BlockIdCommand).
884        setBlkIdCmd(PBHelper.convert((BlockIdCommand) datanodeCommand));
885      break;
886    case DatanodeProtocol.DNA_UNKNOWN: //Not expected
887    default:
888      builder.setCmdType(DatanodeCommandProto.Type.NullDatanodeCommand);
889    }
890    return builder.build();
891  }
892
893  public static KeyUpdateCommand convert(KeyUpdateCommandProto keyUpdateCmd) {
894    return new KeyUpdateCommand(PBHelper.convert(keyUpdateCmd.getKeys()));
895  }
896
897  public static FinalizeCommand convert(FinalizeCommandProto finalizeCmd) {
898    return new FinalizeCommand(finalizeCmd.getBlockPoolId());
899  }
900
901  public static BlockRecoveryCommand convert(
902      BlockRecoveryCommandProto recoveryCmd) {
903    List<RecoveringBlockProto> list = recoveryCmd.getBlocksList();
904    List<RecoveringBlock> recoveringBlocks = new ArrayList<RecoveringBlock>(
905        list.size());
906    
907    for (RecoveringBlockProto rbp : list) {
908      recoveringBlocks.add(PBHelper.convert(rbp));
909    }
910    return new BlockRecoveryCommand(recoveringBlocks);
911  }
912
913  public static BlockCommand convert(BlockCommandProto blkCmd) {
914    List<BlockProto> blockProtoList = blkCmd.getBlocksList();
915    Block[] blocks = new Block[blockProtoList.size()];
916    for (int i = 0; i < blockProtoList.size(); i++) {
917      blocks[i] = PBHelper.convert(blockProtoList.get(i));
918    }
919    List<DatanodeInfosProto> targetList = blkCmd.getTargetsList();
920    DatanodeInfo[][] targets = new DatanodeInfo[targetList.size()][];
921    for (int i = 0; i < targetList.size(); i++) {
922      targets[i] = PBHelper.convert(targetList.get(i));
923    }
924
925    List<StorageUuidsProto> targetStorageUuidsList = blkCmd.getTargetStorageUuidsList();
926    String[][] targetStorageIDs = new String[targetStorageUuidsList.size()][];
927    for(int i = 0; i < targetStorageIDs.length; i++) {
928      List<String> storageIDs = targetStorageUuidsList.get(i).getStorageUuidsList();
929      targetStorageIDs[i] = storageIDs.toArray(new String[storageIDs.size()]);
930    }
931
932    int action = DatanodeProtocol.DNA_UNKNOWN;
933    switch (blkCmd.getAction()) {
934    case TRANSFER:
935      action = DatanodeProtocol.DNA_TRANSFER;
936      break;
937    case INVALIDATE:
938      action = DatanodeProtocol.DNA_INVALIDATE;
939      break;
940    case SHUTDOWN:
941      action = DatanodeProtocol.DNA_SHUTDOWN;
942      break;
943    default:
944      throw new AssertionError("Unknown action type: " + blkCmd.getAction());
945    }
946    return new BlockCommand(action, blkCmd.getBlockPoolId(), blocks, targets,
947        targetStorageIDs);
948  }
949
950  public static BlockIdCommand convert(BlockIdCommandProto blkIdCmd) {
951    int numBlockIds = blkIdCmd.getBlockIdsCount();
952    long blockIds[] = new long[numBlockIds];
953    for (int i = 0; i < numBlockIds; i++) {
954      blockIds[i] = blkIdCmd.getBlockIds(i);
955    }
956    int action = DatanodeProtocol.DNA_UNKNOWN;
957    switch (blkIdCmd.getAction()) {
958    case CACHE:
959      action = DatanodeProtocol.DNA_CACHE;
960      break;
961    case UNCACHE:
962      action = DatanodeProtocol.DNA_UNCACHE;
963      break;
964    default:
965      throw new AssertionError("Unknown action type: " + blkIdCmd.getAction());
966    }
967    return new BlockIdCommand(action, blkIdCmd.getBlockPoolId(), blockIds);
968  }
969
970  public static DatanodeInfo[] convert(DatanodeInfosProto datanodeInfosProto) {
971    List<DatanodeInfoProto> proto = datanodeInfosProto.getDatanodesList();
972    DatanodeInfo[] infos = new DatanodeInfo[proto.size()];
973    for (int i = 0; i < infos.length; i++) {
974      infos[i] = PBHelper.convert(proto.get(i));
975    }
976    return infos;
977  }
978
979  public static BalancerBandwidthCommand convert(
980      BalancerBandwidthCommandProto balancerCmd) {
981    return new BalancerBandwidthCommand(balancerCmd.getBandwidth());
982  }
983
984  public static ReceivedDeletedBlockInfoProto convert(
985      ReceivedDeletedBlockInfo receivedDeletedBlockInfo) {
986    ReceivedDeletedBlockInfoProto.Builder builder = 
987        ReceivedDeletedBlockInfoProto.newBuilder();
988    
989    ReceivedDeletedBlockInfoProto.BlockStatus status;
990    switch (receivedDeletedBlockInfo.getStatus()) {
991    case RECEIVING_BLOCK:
992      status = ReceivedDeletedBlockInfoProto.BlockStatus.RECEIVING;
993      break;
994    case RECEIVED_BLOCK:
995      status = ReceivedDeletedBlockInfoProto.BlockStatus.RECEIVED;
996      break;
997    case DELETED_BLOCK:
998      status = ReceivedDeletedBlockInfoProto.BlockStatus.DELETED;
999      break;
1000    default:
1001      throw new IllegalArgumentException("Bad status: " +
1002          receivedDeletedBlockInfo.getStatus());
1003    }
1004    builder.setStatus(status);
1005    
1006    if (receivedDeletedBlockInfo.getDelHints() != null) {
1007      builder.setDeleteHint(receivedDeletedBlockInfo.getDelHints());
1008    }
1009    return builder.setBlock(PBHelper.convert(receivedDeletedBlockInfo.getBlock()))
1010        .build();
1011  }
1012
1013  public static ReceivedDeletedBlockInfo convert(
1014      ReceivedDeletedBlockInfoProto proto) {
1015    ReceivedDeletedBlockInfo.BlockStatus status = null;
1016    switch (proto.getStatus()) {
1017    case RECEIVING:
1018      status = BlockStatus.RECEIVING_BLOCK;
1019      break;
1020    case RECEIVED:
1021      status = BlockStatus.RECEIVED_BLOCK;
1022      break;
1023    case DELETED:
1024      status = BlockStatus.DELETED_BLOCK;
1025      break;
1026    }
1027    return new ReceivedDeletedBlockInfo(
1028        PBHelper.convert(proto.getBlock()),
1029        status,
1030        proto.hasDeleteHint() ? proto.getDeleteHint() : null);
1031  }
1032  
1033  public static NamespaceInfoProto convert(NamespaceInfo info) {
1034    return NamespaceInfoProto.newBuilder()
1035        .setBlockPoolID(info.getBlockPoolID())
1036        .setBuildVersion(info.getBuildVersion())
1037        .setUnused(0)
1038        .setStorageInfo(PBHelper.convert((StorageInfo)info))
1039        .setSoftwareVersion(info.getSoftwareVersion()).build();
1040  }
1041  
1042  // Located Block Arrays and Lists
1043  public static LocatedBlockProto[] convertLocatedBlock(LocatedBlock[] lb) {
1044    if (lb == null) return null;
1045    return convertLocatedBlock2(Arrays.asList(lb)).toArray(
1046        new LocatedBlockProto[lb.length]);
1047  }
1048  
1049  public static LocatedBlock[] convertLocatedBlock(LocatedBlockProto[] lb) {
1050    if (lb == null) return null;
1051    return convertLocatedBlock(Arrays.asList(lb)).toArray(
1052        new LocatedBlock[lb.length]);
1053  }
1054  
1055  public static List<LocatedBlock> convertLocatedBlock(
1056      List<LocatedBlockProto> lb) {
1057    if (lb == null) return null;
1058    final int len = lb.size();
1059    List<LocatedBlock> result = 
1060        new ArrayList<LocatedBlock>(len);
1061    for (int i = 0; i < len; ++i) {
1062      result.add(PBHelper.convert(lb.get(i)));
1063    }
1064    return result;
1065  }
1066  
1067  public static List<LocatedBlockProto> convertLocatedBlock2(List<LocatedBlock> lb) {
1068    if (lb == null) return null;
1069    final int len = lb.size();
1070    List<LocatedBlockProto> result = new ArrayList<LocatedBlockProto>(len);
1071    for (int i = 0; i < len; ++i) {
1072      result.add(PBHelper.convert(lb.get(i)));
1073    }
1074    return result;
1075  }
1076  
1077  
1078  // LocatedBlocks
1079  public static LocatedBlocks convert(LocatedBlocksProto lb) {
1080    return new LocatedBlocks(
1081        lb.getFileLength(), lb.getUnderConstruction(),
1082        PBHelper.convertLocatedBlock(lb.getBlocksList()),
1083        lb.hasLastBlock() ? PBHelper.convert(lb.getLastBlock()) : null,
1084        lb.getIsLastBlockComplete());
1085  }
1086  
1087  public static LocatedBlocksProto convert(LocatedBlocks lb) {
1088    if (lb == null) {
1089      return null;
1090    }
1091    LocatedBlocksProto.Builder builder = 
1092        LocatedBlocksProto.newBuilder();
1093    if (lb.getLastLocatedBlock() != null) {
1094      builder.setLastBlock(PBHelper.convert(lb.getLastLocatedBlock()));
1095    }
1096    return builder.setFileLength(lb.getFileLength())
1097        .setUnderConstruction(lb.isUnderConstruction())
1098        .addAllBlocks(PBHelper.convertLocatedBlock2(lb.getLocatedBlocks()))
1099        .setIsLastBlockComplete(lb.isLastBlockComplete()).build();
1100  }
1101  
1102  // DataEncryptionKey
1103  public static DataEncryptionKey convert(DataEncryptionKeyProto bet) {
1104    String encryptionAlgorithm = bet.getEncryptionAlgorithm();
1105    return new DataEncryptionKey(bet.getKeyId(),
1106        bet.getBlockPoolId(),
1107        bet.getNonce().toByteArray(),
1108        bet.getEncryptionKey().toByteArray(),
1109        bet.getExpiryDate(),
1110        encryptionAlgorithm.isEmpty() ? null : encryptionAlgorithm);
1111  }
1112  
1113  public static DataEncryptionKeyProto convert(DataEncryptionKey bet) {
1114    DataEncryptionKeyProto.Builder b = DataEncryptionKeyProto.newBuilder()
1115        .setKeyId(bet.keyId)
1116        .setBlockPoolId(bet.blockPoolId)
1117        .setNonce(ByteString.copyFrom(bet.nonce))
1118        .setEncryptionKey(ByteString.copyFrom(bet.encryptionKey))
1119        .setExpiryDate(bet.expiryDate);
1120    if (bet.encryptionAlgorithm != null) {
1121      b.setEncryptionAlgorithm(bet.encryptionAlgorithm);
1122    }
1123    return b.build();
1124  }
1125  
1126  public static FsServerDefaults convert(FsServerDefaultsProto fs) {
1127    if (fs == null) return null;
1128    return new FsServerDefaults(
1129        fs.getBlockSize(), fs.getBytesPerChecksum(), 
1130        fs.getWritePacketSize(), (short) fs.getReplication(),
1131        fs.getFileBufferSize(),
1132        fs.getEncryptDataTransfer(),
1133        fs.getTrashInterval(),
1134        PBHelper.convert(fs.getChecksumType()));
1135  }
1136  
1137  public static FsServerDefaultsProto convert(FsServerDefaults fs) {
1138    if (fs == null) return null;
1139    return FsServerDefaultsProto.newBuilder().
1140      setBlockSize(fs.getBlockSize()).
1141      setBytesPerChecksum(fs.getBytesPerChecksum()).
1142      setWritePacketSize(fs.getWritePacketSize())
1143      .setReplication(fs.getReplication())
1144      .setFileBufferSize(fs.getFileBufferSize())
1145      .setEncryptDataTransfer(fs.getEncryptDataTransfer())
1146      .setTrashInterval(fs.getTrashInterval())
1147      .setChecksumType(PBHelper.convert(fs.getChecksumType()))
1148      .build();
1149  }
1150  
1151  public static FsPermissionProto convert(FsPermission p) {
1152    if (p == null) return null;
1153    return FsPermissionProto.newBuilder().setPerm(p.toShort()).build();
1154  }
1155  
1156  public static FsPermission convert(FsPermissionProto p) {
1157    if (p == null) return null;
1158    return new FsPermission((short)p.getPerm());
1159  }
1160  
1161  
1162  // The creatFlag field in PB is a bitmask whose values are the same a the 
1163  // emum values of CreateFlag
1164  public static int convertCreateFlag(EnumSetWritable<CreateFlag> flag) {
1165    int value = 0;
1166    if (flag.contains(CreateFlag.APPEND)) {
1167      value |= CreateFlagProto.APPEND.getNumber();
1168    }
1169    if (flag.contains(CreateFlag.CREATE)) {
1170      value |= CreateFlagProto.CREATE.getNumber();
1171    }
1172    if (flag.contains(CreateFlag.OVERWRITE)) {
1173      value |= CreateFlagProto.OVERWRITE.getNumber();
1174    }
1175    return value;
1176  }
1177  
1178  public static EnumSetWritable<CreateFlag> convertCreateFlag(int flag) {
1179    EnumSet<CreateFlag> result = 
1180       EnumSet.noneOf(CreateFlag.class);   
1181    if ((flag & CreateFlagProto.APPEND_VALUE) == CreateFlagProto.APPEND_VALUE) {
1182      result.add(CreateFlag.APPEND);
1183    }
1184    if ((flag & CreateFlagProto.CREATE_VALUE) == CreateFlagProto.CREATE_VALUE) {
1185      result.add(CreateFlag.CREATE);
1186    }
1187    if ((flag & CreateFlagProto.OVERWRITE_VALUE) 
1188        == CreateFlagProto.OVERWRITE_VALUE) {
1189      result.add(CreateFlag.OVERWRITE);
1190    }
1191    return new EnumSetWritable<CreateFlag>(result);
1192  }
1193
1194  public static int convertCacheFlags(EnumSet<CacheFlag> flags) {
1195    int value = 0;
1196    if (flags.contains(CacheFlag.FORCE)) {
1197      value |= CacheFlagProto.FORCE.getNumber();
1198    }
1199    return value;
1200  }
1201
1202  public static EnumSet<CacheFlag> convertCacheFlags(int flags) {
1203    EnumSet<CacheFlag> result = EnumSet.noneOf(CacheFlag.class);
1204    if ((flags & CacheFlagProto.FORCE_VALUE) == CacheFlagProto.FORCE_VALUE) {
1205      result.add(CacheFlag.FORCE);
1206    }
1207    return result;
1208  }
1209
1210  public static HdfsFileStatus convert(HdfsFileStatusProto fs) {
1211    if (fs == null)
1212      return null;
1213    return new HdfsLocatedFileStatus(
1214        fs.getLength(), fs.getFileType().equals(FileType.IS_DIR), 
1215        fs.getBlockReplication(), fs.getBlocksize(),
1216        fs.getModificationTime(), fs.getAccessTime(),
1217        PBHelper.convert(fs.getPermission()), fs.getOwner(), fs.getGroup(), 
1218        fs.getFileType().equals(FileType.IS_SYMLINK) ? 
1219            fs.getSymlink().toByteArray() : null,
1220        fs.getPath().toByteArray(),
1221        fs.hasFileId()? fs.getFileId(): INodeId.GRANDFATHER_INODE_ID,
1222        fs.hasLocations() ? PBHelper.convert(fs.getLocations()) : null,
1223        fs.hasChildrenNum() ? fs.getChildrenNum() : -1);
1224  }
1225
1226  public static SnapshottableDirectoryStatus convert(
1227      SnapshottableDirectoryStatusProto sdirStatusProto) {
1228    if (sdirStatusProto == null) {
1229      return null;
1230    }
1231    final HdfsFileStatusProto status = sdirStatusProto.getDirStatus();
1232    return new SnapshottableDirectoryStatus(
1233        status.getModificationTime(),
1234        status.getAccessTime(),
1235        PBHelper.convert(status.getPermission()),
1236        status.getOwner(),
1237        status.getGroup(),
1238        status.getPath().toByteArray(),
1239        status.getFileId(),
1240        status.getChildrenNum(),
1241        sdirStatusProto.getSnapshotNumber(),
1242        sdirStatusProto.getSnapshotQuota(),
1243        sdirStatusProto.getParentFullpath().toByteArray());
1244  }
1245  
1246  public static HdfsFileStatusProto convert(HdfsFileStatus fs) {
1247    if (fs == null)
1248      return null;
1249    FileType fType = FileType.IS_FILE;
1250    if (fs.isDir()) {
1251      fType = FileType.IS_DIR;
1252    } else if (fs.isSymlink()) {
1253      fType = FileType.IS_SYMLINK;
1254    }
1255
1256    HdfsFileStatusProto.Builder builder = 
1257     HdfsFileStatusProto.newBuilder().
1258      setLength(fs.getLen()).
1259      setFileType(fType).
1260      setBlockReplication(fs.getReplication()).
1261      setBlocksize(fs.getBlockSize()).
1262      setModificationTime(fs.getModificationTime()).
1263      setAccessTime(fs.getAccessTime()).
1264      setPermission(PBHelper.convert(fs.getPermission())).
1265      setOwner(fs.getOwner()).
1266      setGroup(fs.getGroup()).
1267      setFileId(fs.getFileId()).
1268      setChildrenNum(fs.getChildrenNum()).
1269      setPath(ByteString.copyFrom(fs.getLocalNameInBytes()));
1270    if (fs.isSymlink())  {
1271      builder.setSymlink(ByteString.copyFrom(fs.getSymlinkInBytes()));
1272    }
1273    if (fs instanceof HdfsLocatedFileStatus) {
1274      LocatedBlocks locations = ((HdfsLocatedFileStatus)fs).getBlockLocations();
1275      if (locations != null) {
1276        builder.setLocations(PBHelper.convert(locations));
1277      }
1278    }
1279    return builder.build();
1280  }
1281  
1282  public static SnapshottableDirectoryStatusProto convert(
1283      SnapshottableDirectoryStatus status) {
1284    if (status == null) {
1285      return null;
1286    }
1287    int snapshotNumber = status.getSnapshotNumber();
1288    int snapshotQuota = status.getSnapshotQuota();
1289    byte[] parentFullPath = status.getParentFullPath();
1290    ByteString parentFullPathBytes = ByteString.copyFrom(
1291        parentFullPath == null ? DFSUtil.EMPTY_BYTES : parentFullPath);
1292    HdfsFileStatusProto fs = convert(status.getDirStatus());
1293    SnapshottableDirectoryStatusProto.Builder builder = 
1294        SnapshottableDirectoryStatusProto
1295        .newBuilder().setSnapshotNumber(snapshotNumber)
1296        .setSnapshotQuota(snapshotQuota).setParentFullpath(parentFullPathBytes)
1297        .setDirStatus(fs);
1298    return builder.build();
1299  }
1300  
1301  public static HdfsFileStatusProto[] convert(HdfsFileStatus[] fs) {
1302    if (fs == null) return null;
1303    final int len = fs.length;
1304    HdfsFileStatusProto[] result = new HdfsFileStatusProto[len];
1305    for (int i = 0; i < len; ++i) {
1306      result[i] = PBHelper.convert(fs[i]);
1307    }
1308    return result;
1309  }
1310  
1311  public static HdfsFileStatus[] convert(HdfsFileStatusProto[] fs) {
1312    if (fs == null) return null;
1313    final int len = fs.length;
1314    HdfsFileStatus[] result = new HdfsFileStatus[len];
1315    for (int i = 0; i < len; ++i) {
1316      result[i] = PBHelper.convert(fs[i]);
1317    }
1318    return result;
1319  }
1320  
1321  public static DirectoryListing convert(DirectoryListingProto dl) {
1322    if (dl == null)
1323      return null;
1324    List<HdfsFileStatusProto> partList =  dl.getPartialListingList();
1325    return new DirectoryListing( 
1326        partList.isEmpty() ? new HdfsLocatedFileStatus[0] 
1327          : PBHelper.convert(
1328              partList.toArray(new HdfsFileStatusProto[partList.size()])),
1329        dl.getRemainingEntries());
1330  }
1331
1332  public static DirectoryListingProto convert(DirectoryListing d) {
1333    if (d == null)
1334      return null;
1335    return DirectoryListingProto.newBuilder().
1336        addAllPartialListing(Arrays.asList(
1337            PBHelper.convert(d.getPartialListing()))).
1338        setRemainingEntries(d.getRemainingEntries()).
1339        build();
1340  }
1341
1342  public static long[] convert(GetFsStatsResponseProto res) {
1343    long[] result = new long[6];
1344    result[ClientProtocol.GET_STATS_CAPACITY_IDX] = res.getCapacity();
1345    result[ClientProtocol.GET_STATS_USED_IDX] = res.getUsed();
1346    result[ClientProtocol.GET_STATS_REMAINING_IDX] = res.getRemaining();
1347    result[ClientProtocol.GET_STATS_UNDER_REPLICATED_IDX] = res.getUnderReplicated();
1348    result[ClientProtocol.GET_STATS_CORRUPT_BLOCKS_IDX] = res.getCorruptBlocks();
1349    result[ClientProtocol.GET_STATS_MISSING_BLOCKS_IDX] = res.getMissingBlocks();
1350    return result;
1351  }
1352  
1353  public static GetFsStatsResponseProto convert(long[] fsStats) {
1354    GetFsStatsResponseProto.Builder result = GetFsStatsResponseProto
1355        .newBuilder();
1356    if (fsStats.length >= ClientProtocol.GET_STATS_CAPACITY_IDX + 1)
1357      result.setCapacity(fsStats[ClientProtocol.GET_STATS_CAPACITY_IDX]);
1358    if (fsStats.length >= ClientProtocol.GET_STATS_USED_IDX + 1)
1359      result.setUsed(fsStats[ClientProtocol.GET_STATS_USED_IDX]);
1360    if (fsStats.length >= ClientProtocol.GET_STATS_REMAINING_IDX + 1)
1361      result.setRemaining(fsStats[ClientProtocol.GET_STATS_REMAINING_IDX]);
1362    if (fsStats.length >= ClientProtocol.GET_STATS_UNDER_REPLICATED_IDX + 1)
1363      result.setUnderReplicated(
1364              fsStats[ClientProtocol.GET_STATS_UNDER_REPLICATED_IDX]);
1365    if (fsStats.length >= ClientProtocol.GET_STATS_CORRUPT_BLOCKS_IDX + 1)
1366      result.setCorruptBlocks(
1367          fsStats[ClientProtocol.GET_STATS_CORRUPT_BLOCKS_IDX]);
1368    if (fsStats.length >= ClientProtocol.GET_STATS_MISSING_BLOCKS_IDX + 1)
1369      result.setMissingBlocks(
1370          fsStats[ClientProtocol.GET_STATS_MISSING_BLOCKS_IDX]);
1371    return result.build();
1372  }
1373  
1374  public static DatanodeReportTypeProto
1375    convert(DatanodeReportType t) {
1376    switch (t) {
1377    case ALL: return DatanodeReportTypeProto.ALL;
1378    case LIVE: return DatanodeReportTypeProto.LIVE;
1379    case DEAD: return DatanodeReportTypeProto.DEAD;
1380    default: 
1381      throw new IllegalArgumentException("Unexpected data type report:" + t);
1382    }
1383  }
1384  
1385  public static DatanodeReportType 
1386    convert(DatanodeReportTypeProto t) {
1387    switch (t) {
1388    case ALL: return DatanodeReportType.ALL;
1389    case LIVE: return DatanodeReportType.LIVE;
1390    case DEAD: return DatanodeReportType.DEAD;
1391    default: 
1392      throw new IllegalArgumentException("Unexpected data type report:" + t);
1393    }
1394  }
1395
1396  public static SafeModeActionProto convert(
1397      SafeModeAction a) {
1398    switch (a) {
1399    case SAFEMODE_LEAVE:
1400      return SafeModeActionProto.SAFEMODE_LEAVE;
1401    case SAFEMODE_ENTER:
1402      return SafeModeActionProto.SAFEMODE_ENTER;
1403    case SAFEMODE_GET:
1404      return SafeModeActionProto.SAFEMODE_GET;
1405    default:
1406      throw new IllegalArgumentException("Unexpected SafeModeAction :" + a);
1407    }
1408  }
1409  
1410  public static SafeModeAction convert(
1411      ClientNamenodeProtocolProtos.SafeModeActionProto a) {
1412    switch (a) {
1413    case SAFEMODE_LEAVE:
1414      return SafeModeAction.SAFEMODE_LEAVE;
1415    case SAFEMODE_ENTER:
1416      return SafeModeAction.SAFEMODE_ENTER;
1417    case SAFEMODE_GET:
1418      return SafeModeAction.SAFEMODE_GET;
1419    default:
1420      throw new IllegalArgumentException("Unexpected SafeModeAction :" + a);
1421    }
1422  }
1423  
1424  public static CorruptFileBlocks convert(CorruptFileBlocksProto c) {
1425    if (c == null)
1426      return null;
1427    List<String> fileList = c.getFilesList();
1428    return new CorruptFileBlocks(fileList.toArray(new String[fileList.size()]),
1429        c.getCookie());
1430  }
1431
1432  public static CorruptFileBlocksProto convert(CorruptFileBlocks c) {
1433    if (c == null)
1434      return null;
1435    return CorruptFileBlocksProto.newBuilder().
1436        addAllFiles(Arrays.asList(c.getFiles())).
1437        setCookie(c.getCookie()).
1438        build();
1439  }
1440  
1441  public static ContentSummary convert(ContentSummaryProto cs) {
1442    if (cs == null) return null;
1443    return new ContentSummary(
1444      cs.getLength(), cs.getFileCount(), cs.getDirectoryCount(), cs.getQuota(),
1445      cs.getSpaceConsumed(), cs.getSpaceQuota());
1446  }
1447  
1448  public static ContentSummaryProto convert(ContentSummary cs) {
1449    if (cs == null) return null;
1450    return ContentSummaryProto.newBuilder().
1451        setLength(cs.getLength()).
1452        setFileCount(cs.getFileCount()).
1453        setDirectoryCount(cs.getDirectoryCount()).
1454        setQuota(cs.getQuota()).
1455        setSpaceConsumed(cs.getSpaceConsumed()).
1456        setSpaceQuota(cs.getSpaceQuota()).
1457        build();
1458  }
1459
1460  public static NNHAStatusHeartbeat convert(NNHAStatusHeartbeatProto s) {
1461    if (s == null) return null;
1462    switch (s.getState()) {
1463    case ACTIVE:
1464      return new NNHAStatusHeartbeat(HAServiceState.ACTIVE, s.getTxid());
1465    case STANDBY:
1466      return new NNHAStatusHeartbeat(HAServiceState.STANDBY, s.getTxid());
1467    default:
1468      throw new IllegalArgumentException("Unexpected NNHAStatusHeartbeat.State:" + s.getState());
1469    }
1470  }
1471
1472  public static NNHAStatusHeartbeatProto convert(NNHAStatusHeartbeat hb) {
1473    if (hb == null) return null;
1474    NNHAStatusHeartbeatProto.Builder builder =
1475      NNHAStatusHeartbeatProto.newBuilder();
1476    switch (hb.getState()) {
1477      case ACTIVE:
1478        builder.setState(NNHAStatusHeartbeatProto.State.ACTIVE);
1479        break;
1480      case STANDBY:
1481        builder.setState(NNHAStatusHeartbeatProto.State.STANDBY);
1482        break;
1483      default:
1484        throw new IllegalArgumentException("Unexpected NNHAStatusHeartbeat.State:" +
1485            hb.getState());
1486    }
1487    builder.setTxid(hb.getTxId());
1488    return builder.build();
1489  }
1490
1491  public static DatanodeStorageProto convert(DatanodeStorage s) {
1492    return DatanodeStorageProto.newBuilder()
1493        .setState(PBHelper.convertState(s.getState()))
1494        .setStorageType(PBHelper.convertStorageType(s.getStorageType()))
1495        .setStorageUuid(s.getStorageID()).build();
1496  }
1497
1498  private static StorageState convertState(State state) {
1499    switch(state) {
1500    case READ_ONLY:
1501      return StorageState.READ_ONLY;
1502    case NORMAL:
1503    default:
1504      return StorageState.NORMAL;
1505    }
1506  }
1507
1508  private static StorageTypeProto convertStorageType(
1509      StorageType type) {
1510    switch(type) {
1511    case DISK:
1512      return StorageTypeProto.DISK;
1513    case SSD:
1514      return StorageTypeProto.SSD;
1515    default:
1516      throw new IllegalStateException(
1517          "BUG: StorageType not found, type=" + type);
1518    }
1519  }
1520
1521  public static DatanodeStorage convert(DatanodeStorageProto s) {
1522    return new DatanodeStorage(s.getStorageUuid(),
1523                               PBHelper.convertState(s.getState()),
1524                               PBHelper.convertType(s.getStorageType()));
1525  }
1526
1527  private static State convertState(StorageState state) {
1528    switch(state) {
1529    case READ_ONLY:
1530      return DatanodeStorage.State.READ_ONLY;
1531    case NORMAL:
1532    default:
1533      return DatanodeStorage.State.NORMAL;
1534    }
1535  }
1536
1537  private static StorageType convertType(StorageTypeProto type) {
1538    switch(type) {
1539      case DISK:
1540        return StorageType.DISK;
1541      case SSD:
1542        return StorageType.SSD;
1543      default:
1544        throw new IllegalStateException(
1545            "BUG: StorageTypeProto not found, type=" + type);
1546    }
1547  }
1548
1549  private static StorageType[] convertStorageTypeProtos(
1550      List<StorageTypeProto> storageTypesList) {
1551    final StorageType[] storageTypes = new StorageType[storageTypesList.size()];
1552    for (int i = 0; i < storageTypes.length; ++i) {
1553      storageTypes[i] = PBHelper.convertType(storageTypesList.get(i));
1554    }
1555    return storageTypes;
1556  }
1557
1558  public static StorageReportProto convert(StorageReport r) {
1559    StorageReportProto.Builder builder = StorageReportProto.newBuilder()
1560        .setBlockPoolUsed(r.getBlockPoolUsed()).setCapacity(r.getCapacity())
1561        .setDfsUsed(r.getDfsUsed()).setRemaining(r.getRemaining())
1562        .setStorageUuid(r.getStorage().getStorageID())
1563        .setStorage(convert(r.getStorage()));
1564    return builder.build();
1565  }
1566
1567  public static StorageReport convert(StorageReportProto p) {
1568    return new StorageReport(
1569        p.hasStorage() ?
1570            convert(p.getStorage()) :
1571            new DatanodeStorage(p.getStorageUuid()),
1572        p.getFailed(), p.getCapacity(), p.getDfsUsed(), p.getRemaining(),
1573        p.getBlockPoolUsed());
1574  }
1575
1576  public static StorageReport[] convertStorageReports(
1577      List<StorageReportProto> list) {
1578    final StorageReport[] report = new StorageReport[list.size()];
1579    for (int i = 0; i < report.length; i++) {
1580      report[i] = convert(list.get(i));
1581    }
1582    return report;
1583  }
1584
1585  public static JournalInfo convert(JournalInfoProto info) {
1586    int lv = info.hasLayoutVersion() ? info.getLayoutVersion() : 0;
1587    int nsID = info.hasNamespaceID() ? info.getNamespaceID() : 0;
1588    return new JournalInfo(lv, info.getClusterID(), nsID);
1589  }
1590
1591  /**
1592   * Method used for converting {@link JournalInfoProto} sent from Namenode
1593   * to Journal receivers to {@link NamenodeRegistration}.
1594   */
1595  public static JournalInfoProto convert(JournalInfo j) {
1596    return JournalInfoProto.newBuilder().setClusterID(j.getClusterId())
1597        .setLayoutVersion(j.getLayoutVersion())
1598        .setNamespaceID(j.getNamespaceId()).build();
1599  } 
1600  
1601  public static SnapshottableDirectoryStatus[] convert(
1602      SnapshottableDirectoryListingProto sdlp) {
1603    if (sdlp == null)
1604      return null;
1605    List<SnapshottableDirectoryStatusProto> list = sdlp
1606        .getSnapshottableDirListingList();
1607    if (list.isEmpty()) {
1608      return new SnapshottableDirectoryStatus[0];
1609    } else {
1610      SnapshottableDirectoryStatus[] result = 
1611          new SnapshottableDirectoryStatus[list.size()];
1612      for (int i = 0; i < list.size(); i++) {
1613        result[i] = PBHelper.convert(list.get(i));
1614      }
1615      return result;
1616    }
1617  }
1618  
1619  public static SnapshottableDirectoryListingProto convert(
1620      SnapshottableDirectoryStatus[] status) {
1621    if (status == null)
1622      return null;
1623    SnapshottableDirectoryStatusProto[] protos = 
1624        new SnapshottableDirectoryStatusProto[status.length];
1625    for (int i = 0; i < status.length; i++) {
1626      protos[i] = PBHelper.convert(status[i]);
1627    }
1628    List<SnapshottableDirectoryStatusProto> protoList = Arrays.asList(protos);
1629    return SnapshottableDirectoryListingProto.newBuilder()
1630        .addAllSnapshottableDirListing(protoList).build();
1631  }
1632  
1633  public static DiffReportEntry convert(SnapshotDiffReportEntryProto entry) {
1634    if (entry == null) {
1635      return null;
1636    }
1637    DiffType type = DiffType.getTypeFromLabel(entry
1638        .getModificationLabel());
1639    return type == null ? null : 
1640      new DiffReportEntry(type, entry.getFullpath().toByteArray());
1641  }
1642  
1643  public static SnapshotDiffReportEntryProto convert(DiffReportEntry entry) {
1644    if (entry == null) {
1645      return null;
1646    }
1647    byte[] fullPath = entry.getRelativePath();
1648    ByteString fullPathString = ByteString
1649        .copyFrom(fullPath == null ? DFSUtil.EMPTY_BYTES : fullPath);
1650    
1651    String modification = entry.getType().getLabel();
1652    
1653    SnapshotDiffReportEntryProto entryProto = SnapshotDiffReportEntryProto
1654        .newBuilder().setFullpath(fullPathString)
1655        .setModificationLabel(modification).build();
1656    return entryProto;
1657  }
1658  
1659  public static SnapshotDiffReport convert(SnapshotDiffReportProto reportProto) {
1660    if (reportProto == null) {
1661      return null;
1662    }
1663    String snapshotDir = reportProto.getSnapshotRoot();
1664    String fromSnapshot = reportProto.getFromSnapshot();
1665    String toSnapshot = reportProto.getToSnapshot();
1666    List<SnapshotDiffReportEntryProto> list = reportProto
1667        .getDiffReportEntriesList();
1668    List<DiffReportEntry> entries = new ArrayList<DiffReportEntry>();
1669    for (SnapshotDiffReportEntryProto entryProto : list) {
1670      DiffReportEntry entry = convert(entryProto);
1671      if (entry != null)
1672        entries.add(entry);
1673    }
1674    return new SnapshotDiffReport(snapshotDir, fromSnapshot, toSnapshot,
1675        entries);
1676  }
1677  
1678  public static SnapshotDiffReportProto convert(SnapshotDiffReport report) {
1679    if (report == null) {
1680      return null;
1681    }
1682    List<DiffReportEntry> entries = report.getDiffList();
1683    List<SnapshotDiffReportEntryProto> entryProtos = 
1684        new ArrayList<SnapshotDiffReportEntryProto>();
1685    for (DiffReportEntry entry : entries) {
1686      SnapshotDiffReportEntryProto entryProto = convert(entry);
1687      if (entryProto != null)
1688        entryProtos.add(entryProto);
1689    }
1690    
1691    SnapshotDiffReportProto reportProto = SnapshotDiffReportProto.newBuilder()
1692        .setSnapshotRoot(report.getSnapshotRoot())
1693        .setFromSnapshot(report.getFromSnapshot())
1694        .setToSnapshot(report.getLaterSnapshotName())
1695        .addAllDiffReportEntries(entryProtos).build();
1696    return reportProto;
1697  }
1698
1699  public static DataChecksum.Type convert(HdfsProtos.ChecksumTypeProto type) {
1700    return DataChecksum.Type.valueOf(type.getNumber());
1701  }
1702
1703  public static CacheDirectiveInfoProto convert
1704      (CacheDirectiveInfo info) {
1705    CacheDirectiveInfoProto.Builder builder = 
1706        CacheDirectiveInfoProto.newBuilder();
1707    if (info.getId() != null) {
1708      builder.setId(info.getId());
1709    }
1710    if (info.getPath() != null) {
1711      builder.setPath(info.getPath().toUri().getPath());
1712    }
1713    if (info.getReplication() != null) {
1714      builder.setReplication(info.getReplication());
1715    }
1716    if (info.getPool() != null) {
1717      builder.setPool(info.getPool());
1718    }
1719    if (info.getExpiration() != null) {
1720      builder.setExpiration(convert(info.getExpiration()));
1721    }
1722    return builder.build();
1723  }
1724
1725  public static CacheDirectiveInfo convert
1726      (CacheDirectiveInfoProto proto) {
1727    CacheDirectiveInfo.Builder builder =
1728        new CacheDirectiveInfo.Builder();
1729    if (proto.hasId()) {
1730      builder.setId(proto.getId());
1731    }
1732    if (proto.hasPath()) {
1733      builder.setPath(new Path(proto.getPath()));
1734    }
1735    if (proto.hasReplication()) {
1736      builder.setReplication(Shorts.checkedCast(
1737          proto.getReplication()));
1738    }
1739    if (proto.hasPool()) {
1740      builder.setPool(proto.getPool());
1741    }
1742    if (proto.hasExpiration()) {
1743      builder.setExpiration(convert(proto.getExpiration()));
1744    }
1745    return builder.build();
1746  }
1747
1748  public static CacheDirectiveInfoExpirationProto convert(
1749      CacheDirectiveInfo.Expiration expiration) {
1750    return CacheDirectiveInfoExpirationProto.newBuilder()
1751        .setIsRelative(expiration.isRelative())
1752        .setMillis(expiration.getMillis())
1753        .build();
1754  }
1755
1756  public static CacheDirectiveInfo.Expiration convert(
1757      CacheDirectiveInfoExpirationProto proto) {
1758    if (proto.getIsRelative()) {
1759      return CacheDirectiveInfo.Expiration.newRelative(proto.getMillis());
1760    }
1761    return CacheDirectiveInfo.Expiration.newAbsolute(proto.getMillis());
1762  }
1763
1764  public static CacheDirectiveStatsProto convert(CacheDirectiveStats stats) {
1765    CacheDirectiveStatsProto.Builder builder = 
1766        CacheDirectiveStatsProto.newBuilder();
1767    builder.setBytesNeeded(stats.getBytesNeeded());
1768    builder.setBytesCached(stats.getBytesCached());
1769    builder.setFilesNeeded(stats.getFilesNeeded());
1770    builder.setFilesCached(stats.getFilesCached());
1771    builder.setHasExpired(stats.hasExpired());
1772    return builder.build();
1773  }
1774  
1775  public static CacheDirectiveStats convert(CacheDirectiveStatsProto proto) {
1776    CacheDirectiveStats.Builder builder = new CacheDirectiveStats.Builder();
1777    builder.setBytesNeeded(proto.getBytesNeeded());
1778    builder.setBytesCached(proto.getBytesCached());
1779    builder.setFilesNeeded(proto.getFilesNeeded());
1780    builder.setFilesCached(proto.getFilesCached());
1781    builder.setHasExpired(proto.getHasExpired());
1782    return builder.build();
1783  }
1784
1785  public static CacheDirectiveEntryProto convert(CacheDirectiveEntry entry) {
1786    CacheDirectiveEntryProto.Builder builder = 
1787        CacheDirectiveEntryProto.newBuilder();
1788    builder.setInfo(PBHelper.convert(entry.getInfo()));
1789    builder.setStats(PBHelper.convert(entry.getStats()));
1790    return builder.build();
1791  }
1792  
1793  public static CacheDirectiveEntry convert(CacheDirectiveEntryProto proto) {
1794    CacheDirectiveInfo info = PBHelper.convert(proto.getInfo());
1795    CacheDirectiveStats stats = PBHelper.convert(proto.getStats());
1796    return new CacheDirectiveEntry(info, stats);
1797  }
1798
1799  public static CachePoolInfoProto convert(CachePoolInfo info) {
1800    CachePoolInfoProto.Builder builder = CachePoolInfoProto.newBuilder();
1801    builder.setPoolName(info.getPoolName());
1802    if (info.getOwnerName() != null) {
1803      builder.setOwnerName(info.getOwnerName());
1804    }
1805    if (info.getGroupName() != null) {
1806      builder.setGroupName(info.getGroupName());
1807    }
1808    if (info.getMode() != null) {
1809      builder.setMode(info.getMode().toShort());
1810    }
1811    if (info.getLimit() != null) {
1812      builder.setLimit(info.getLimit());
1813    }
1814    if (info.getMaxRelativeExpiryMs() != null) {
1815      builder.setMaxRelativeExpiry(info.getMaxRelativeExpiryMs());
1816    }
1817    return builder.build();
1818  }
1819
1820  public static CachePoolInfo convert (CachePoolInfoProto proto) {
1821    // Pool name is a required field, the rest are optional
1822    String poolName = checkNotNull(proto.getPoolName());
1823    CachePoolInfo info = new CachePoolInfo(poolName);
1824    if (proto.hasOwnerName()) {
1825        info.setOwnerName(proto.getOwnerName());
1826    }
1827    if (proto.hasGroupName()) {
1828      info.setGroupName(proto.getGroupName());
1829    }
1830    if (proto.hasMode()) {
1831      info.setMode(new FsPermission((short)proto.getMode()));
1832    }
1833    if (proto.hasLimit())  {
1834      info.setLimit(proto.getLimit());
1835    }
1836    if (proto.hasMaxRelativeExpiry()) {
1837      info.setMaxRelativeExpiryMs(proto.getMaxRelativeExpiry());
1838    }
1839    return info;
1840  }
1841
1842  public static CachePoolStatsProto convert(CachePoolStats stats) {
1843    CachePoolStatsProto.Builder builder = CachePoolStatsProto.newBuilder();
1844    builder.setBytesNeeded(stats.getBytesNeeded());
1845    builder.setBytesCached(stats.getBytesCached());
1846    builder.setBytesOverlimit(stats.getBytesOverlimit());
1847    builder.setFilesNeeded(stats.getFilesNeeded());
1848    builder.setFilesCached(stats.getFilesCached());
1849    return builder.build();
1850  }
1851
1852  public static CachePoolStats convert (CachePoolStatsProto proto) {
1853    CachePoolStats.Builder builder = new CachePoolStats.Builder();
1854    builder.setBytesNeeded(proto.getBytesNeeded());
1855    builder.setBytesCached(proto.getBytesCached());
1856    builder.setBytesOverlimit(proto.getBytesOverlimit());
1857    builder.setFilesNeeded(proto.getFilesNeeded());
1858    builder.setFilesCached(proto.getFilesCached());
1859    return builder.build();
1860  }
1861
1862  public static CachePoolEntryProto convert(CachePoolEntry entry) {
1863    CachePoolEntryProto.Builder builder = CachePoolEntryProto.newBuilder();
1864    builder.setInfo(PBHelper.convert(entry.getInfo()));
1865    builder.setStats(PBHelper.convert(entry.getStats()));
1866    return builder.build();
1867  }
1868
1869  public static CachePoolEntry convert (CachePoolEntryProto proto) {
1870    CachePoolInfo info = PBHelper.convert(proto.getInfo());
1871    CachePoolStats stats = PBHelper.convert(proto.getStats());
1872    return new CachePoolEntry(info, stats);
1873  }
1874  
1875  public static HdfsProtos.ChecksumTypeProto convert(DataChecksum.Type type) {
1876    return HdfsProtos.ChecksumTypeProto.valueOf(type.id);
1877  }
1878
1879  public static InputStream vintPrefixed(final InputStream input)
1880      throws IOException {
1881    final int firstByte = input.read();
1882    if (firstByte == -1) {
1883      throw new EOFException("Premature EOF: no length prefix available");
1884    }
1885
1886    int size = CodedInputStream.readRawVarint32(firstByte, input);
1887    assert size >= 0;
1888    return new ExactSizeInputStream(input, size);
1889  }
1890}
1891