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     */
018    package org.apache.hadoop.hdfs.protocolPB;
019    
020    import static com.google.common.base.Preconditions.checkNotNull;
021    
022    import java.io.EOFException;
023    import java.io.IOException;
024    import java.io.InputStream;
025    import java.util.ArrayList;
026    import java.util.Arrays;
027    import java.util.EnumSet;
028    import java.util.List;
029    
030    import com.google.common.base.Preconditions;
031    import org.apache.hadoop.fs.CacheFlag;
032    import org.apache.hadoop.fs.ContentSummary;
033    import org.apache.hadoop.fs.CreateFlag;
034    import org.apache.hadoop.fs.FsServerDefaults;
035    import org.apache.hadoop.fs.Path;
036    import org.apache.hadoop.fs.permission.FsPermission;
037    import org.apache.hadoop.ha.HAServiceProtocol.HAServiceState;
038    import org.apache.hadoop.hdfs.DFSUtil;
039    import org.apache.hadoop.hdfs.StorageType;
040    import org.apache.hadoop.hdfs.protocol.Block;
041    import org.apache.hadoop.hdfs.protocol.CacheDirectiveEntry;
042    import org.apache.hadoop.hdfs.protocol.CacheDirectiveStats;
043    import org.apache.hadoop.hdfs.protocol.CachePoolEntry;
044    import org.apache.hadoop.hdfs.protocol.CachePoolInfo;
045    import org.apache.hadoop.hdfs.protocol.CachePoolStats;
046    import org.apache.hadoop.hdfs.protocol.ClientProtocol;
047    import org.apache.hadoop.hdfs.protocol.CorruptFileBlocks;
048    import org.apache.hadoop.hdfs.protocol.DatanodeID;
049    import org.apache.hadoop.hdfs.protocol.DatanodeInfo;
050    import org.apache.hadoop.hdfs.protocol.CacheDirectiveInfo;
051    import org.apache.hadoop.hdfs.protocol.SnapshotDiffReport;
052    import org.apache.hadoop.hdfs.protocol.DatanodeInfo.AdminStates;
053    import org.apache.hadoop.hdfs.protocol.DirectoryListing;
054    import org.apache.hadoop.hdfs.protocol.ExtendedBlock;
055    import org.apache.hadoop.hdfs.protocol.HdfsConstants.DatanodeReportType;
056    import org.apache.hadoop.hdfs.protocol.HdfsConstants.SafeModeAction;
057    import org.apache.hadoop.hdfs.protocol.HdfsFileStatus;
058    import org.apache.hadoop.hdfs.protocol.HdfsLocatedFileStatus;
059    import org.apache.hadoop.hdfs.protocol.LocatedBlock;
060    import org.apache.hadoop.hdfs.protocol.LocatedBlocks;
061    import org.apache.hadoop.hdfs.protocol.SnapshotDiffReport.DiffReportEntry;
062    import org.apache.hadoop.hdfs.protocol.SnapshotDiffReport.DiffType;
063    import org.apache.hadoop.hdfs.protocol.SnapshottableDirectoryStatus;
064    import org.apache.hadoop.hdfs.protocol.proto.ClientNamenodeProtocolProtos;
065    import org.apache.hadoop.hdfs.protocol.proto.ClientNamenodeProtocolProtos.CacheDirectiveEntryProto;
066    import org.apache.hadoop.hdfs.protocol.proto.ClientNamenodeProtocolProtos.CacheDirectiveInfoExpirationProto;
067    import org.apache.hadoop.hdfs.protocol.proto.ClientNamenodeProtocolProtos.CacheDirectiveStatsProto;
068    import org.apache.hadoop.hdfs.protocol.proto.ClientNamenodeProtocolProtos.CacheFlagProto;
069    import org.apache.hadoop.hdfs.protocol.proto.ClientNamenodeProtocolProtos.CachePoolEntryProto;
070    import org.apache.hadoop.hdfs.protocol.proto.ClientNamenodeProtocolProtos.CachePoolInfoProto;
071    import org.apache.hadoop.hdfs.protocol.proto.ClientNamenodeProtocolProtos.CachePoolStatsProto;
072    import org.apache.hadoop.hdfs.protocol.proto.ClientNamenodeProtocolProtos.CreateFlagProto;
073    import org.apache.hadoop.hdfs.protocol.proto.ClientNamenodeProtocolProtos.DatanodeReportTypeProto;
074    import org.apache.hadoop.hdfs.protocol.proto.ClientNamenodeProtocolProtos.GetFsStatsResponseProto;
075    import org.apache.hadoop.hdfs.protocol.proto.ClientNamenodeProtocolProtos.SafeModeActionProto;
076    import org.apache.hadoop.hdfs.protocol.proto.ClientNamenodeProtocolProtos.CacheDirectiveInfoProto;
077    import org.apache.hadoop.hdfs.protocol.proto.DatanodeProtocolProtos.BalancerBandwidthCommandProto;
078    import org.apache.hadoop.hdfs.protocol.proto.DatanodeProtocolProtos.BlockCommandProto;
079    import org.apache.hadoop.hdfs.protocol.proto.DatanodeProtocolProtos.BlockIdCommandProto;
080    import org.apache.hadoop.hdfs.protocol.proto.DatanodeProtocolProtos.BlockRecoveryCommandProto;
081    import org.apache.hadoop.hdfs.protocol.proto.DatanodeProtocolProtos.DatanodeCommandProto;
082    import org.apache.hadoop.hdfs.protocol.proto.DatanodeProtocolProtos.DatanodeRegistrationProto;
083    import org.apache.hadoop.hdfs.protocol.proto.DatanodeProtocolProtos.DatanodeStorageProto;
084    import org.apache.hadoop.hdfs.protocol.proto.DatanodeProtocolProtos.DatanodeStorageProto.StorageState;
085    import org.apache.hadoop.hdfs.protocol.proto.DatanodeProtocolProtos.FinalizeCommandProto;
086    import org.apache.hadoop.hdfs.protocol.proto.DatanodeProtocolProtos.KeyUpdateCommandProto;
087    import org.apache.hadoop.hdfs.protocol.proto.DatanodeProtocolProtos.NNHAStatusHeartbeatProto;
088    import org.apache.hadoop.hdfs.protocol.proto.DatanodeProtocolProtos.ReceivedDeletedBlockInfoProto;
089    import org.apache.hadoop.hdfs.protocol.proto.DatanodeProtocolProtos.RegisterCommandProto;
090    import org.apache.hadoop.hdfs.protocol.proto.DatanodeProtocolProtos.StorageReportProto;
091    import org.apache.hadoop.hdfs.protocol.proto.HdfsProtos;
092    import org.apache.hadoop.hdfs.protocol.proto.HdfsProtos.BlockKeyProto;
093    import org.apache.hadoop.hdfs.protocol.proto.HdfsProtos.BlockProto;
094    import org.apache.hadoop.hdfs.protocol.proto.HdfsProtos.BlockWithLocationsProto;
095    import org.apache.hadoop.hdfs.protocol.proto.HdfsProtos.BlocksWithLocationsProto;
096    import org.apache.hadoop.hdfs.protocol.proto.HdfsProtos.CheckpointCommandProto;
097    import org.apache.hadoop.hdfs.protocol.proto.HdfsProtos.CheckpointSignatureProto;
098    import org.apache.hadoop.hdfs.protocol.proto.HdfsProtos.ContentSummaryProto;
099    import org.apache.hadoop.hdfs.protocol.proto.HdfsProtos.CorruptFileBlocksProto;
100    import org.apache.hadoop.hdfs.protocol.proto.HdfsProtos.DataEncryptionKeyProto;
101    import org.apache.hadoop.hdfs.protocol.proto.HdfsProtos.DatanodeIDProto;
102    import org.apache.hadoop.hdfs.protocol.proto.HdfsProtos.DatanodeInfoProto;
103    import org.apache.hadoop.hdfs.protocol.proto.HdfsProtos.DatanodeInfoProto.AdminState;
104    import org.apache.hadoop.hdfs.protocol.proto.HdfsProtos.DatanodeInfosProto;
105    import org.apache.hadoop.hdfs.protocol.proto.HdfsProtos.DirectoryListingProto;
106    import org.apache.hadoop.hdfs.protocol.proto.HdfsProtos.ExportedBlockKeysProto;
107    import org.apache.hadoop.hdfs.protocol.proto.HdfsProtos.ExtendedBlockProto;
108    import org.apache.hadoop.hdfs.protocol.proto.HdfsProtos.FsPermissionProto;
109    import org.apache.hadoop.hdfs.protocol.proto.HdfsProtos.FsServerDefaultsProto;
110    import org.apache.hadoop.hdfs.protocol.proto.HdfsProtos.HdfsFileStatusProto;
111    import org.apache.hadoop.hdfs.protocol.proto.HdfsProtos.HdfsFileStatusProto.FileType;
112    import org.apache.hadoop.hdfs.protocol.proto.HdfsProtos.LocatedBlockProto;
113    import org.apache.hadoop.hdfs.protocol.proto.HdfsProtos.LocatedBlockProto.Builder;
114    import org.apache.hadoop.hdfs.protocol.proto.HdfsProtos.LocatedBlocksProto;
115    import org.apache.hadoop.hdfs.protocol.proto.HdfsProtos.NamenodeCommandProto;
116    import org.apache.hadoop.hdfs.protocol.proto.HdfsProtos.NamenodeRegistrationProto;
117    import org.apache.hadoop.hdfs.protocol.proto.HdfsProtos.NamenodeRegistrationProto.NamenodeRoleProto;
118    import org.apache.hadoop.hdfs.protocol.proto.HdfsProtos.NamespaceInfoProto;
119    import org.apache.hadoop.hdfs.protocol.proto.HdfsProtos.RecoveringBlockProto;
120    import org.apache.hadoop.hdfs.protocol.proto.HdfsProtos.RemoteEditLogManifestProto;
121    import org.apache.hadoop.hdfs.protocol.proto.HdfsProtos.RemoteEditLogProto;
122    import org.apache.hadoop.hdfs.protocol.proto.HdfsProtos.ReplicaStateProto;
123    import org.apache.hadoop.hdfs.protocol.proto.HdfsProtos.SnapshotDiffReportEntryProto;
124    import org.apache.hadoop.hdfs.protocol.proto.HdfsProtos.SnapshotDiffReportProto;
125    import org.apache.hadoop.hdfs.protocol.proto.HdfsProtos.SnapshottableDirectoryListingProto;
126    import org.apache.hadoop.hdfs.protocol.proto.HdfsProtos.SnapshottableDirectoryStatusProto;
127    import org.apache.hadoop.hdfs.protocol.proto.HdfsProtos.StorageInfoProto;
128    import org.apache.hadoop.hdfs.protocol.proto.HdfsProtos.StorageTypeProto;
129    import org.apache.hadoop.hdfs.protocol.proto.HdfsProtos.StorageUuidsProto;
130    import org.apache.hadoop.hdfs.protocol.proto.JournalProtocolProtos.JournalInfoProto;
131    import org.apache.hadoop.hdfs.security.token.block.BlockKey;
132    import org.apache.hadoop.hdfs.security.token.block.BlockTokenIdentifier;
133    import org.apache.hadoop.hdfs.security.token.block.DataEncryptionKey;
134    import org.apache.hadoop.hdfs.security.token.block.ExportedBlockKeys;
135    import org.apache.hadoop.hdfs.security.token.delegation.DelegationTokenIdentifier;
136    import org.apache.hadoop.hdfs.server.common.HdfsServerConstants.NamenodeRole;
137    import org.apache.hadoop.hdfs.server.common.HdfsServerConstants.ReplicaState;
138    import org.apache.hadoop.hdfs.server.common.StorageInfo;
139    import org.apache.hadoop.hdfs.server.namenode.CheckpointSignature;
140    import org.apache.hadoop.hdfs.server.namenode.INodeId;
141    import org.apache.hadoop.hdfs.server.protocol.BalancerBandwidthCommand;
142    import org.apache.hadoop.hdfs.server.protocol.BlockCommand;
143    import org.apache.hadoop.hdfs.server.protocol.BlockIdCommand;
144    import org.apache.hadoop.hdfs.server.protocol.BlockRecoveryCommand;
145    import org.apache.hadoop.hdfs.server.protocol.BlockRecoveryCommand.RecoveringBlock;
146    import org.apache.hadoop.hdfs.server.protocol.BlocksWithLocations;
147    import org.apache.hadoop.hdfs.server.protocol.BlocksWithLocations.BlockWithLocations;
148    import org.apache.hadoop.hdfs.server.protocol.CheckpointCommand;
149    import org.apache.hadoop.hdfs.server.protocol.DatanodeCommand;
150    import org.apache.hadoop.hdfs.server.protocol.DatanodeProtocol;
151    import org.apache.hadoop.hdfs.server.protocol.DatanodeRegistration;
152    import org.apache.hadoop.hdfs.server.protocol.DatanodeStorage;
153    import org.apache.hadoop.hdfs.server.protocol.DatanodeStorage.State;
154    import org.apache.hadoop.hdfs.server.protocol.FinalizeCommand;
155    import org.apache.hadoop.hdfs.server.protocol.JournalInfo;
156    import org.apache.hadoop.hdfs.server.protocol.KeyUpdateCommand;
157    import org.apache.hadoop.hdfs.server.protocol.NNHAStatusHeartbeat;
158    import org.apache.hadoop.hdfs.server.protocol.NamenodeCommand;
159    import org.apache.hadoop.hdfs.server.protocol.NamenodeRegistration;
160    import org.apache.hadoop.hdfs.server.protocol.NamespaceInfo;
161    import org.apache.hadoop.hdfs.server.protocol.ReceivedDeletedBlockInfo;
162    import org.apache.hadoop.hdfs.server.protocol.ReceivedDeletedBlockInfo.BlockStatus;
163    import org.apache.hadoop.hdfs.server.protocol.RegisterCommand;
164    import org.apache.hadoop.hdfs.server.protocol.RemoteEditLog;
165    import org.apache.hadoop.hdfs.server.protocol.RemoteEditLogManifest;
166    import org.apache.hadoop.hdfs.server.protocol.StorageReport;
167    import org.apache.hadoop.hdfs.util.ExactSizeInputStream;
168    import org.apache.hadoop.io.EnumSetWritable;
169    import org.apache.hadoop.io.Text;
170    import org.apache.hadoop.security.proto.SecurityProtos.TokenProto;
171    import org.apache.hadoop.security.token.Token;
172    import org.apache.hadoop.util.DataChecksum;
173    
174    import com.google.common.base.Preconditions;
175    import com.google.common.collect.Lists;
176    import com.google.common.primitives.Shorts;
177    import com.google.protobuf.ByteString;
178    import 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     */
188    public 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