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    import static org.apache.hadoop.hdfs.protocol.proto.EncryptionZonesProtos
022        .EncryptionZoneProto;
023    import static org.apache.hadoop.hdfs.protocol.proto.HdfsProtos.CipherSuiteProto;
024    import static org.apache.hadoop.hdfs.protocol.proto.HdfsProtos.CryptoProtocolVersionProto;
025    
026    import java.io.EOFException;
027    import java.io.IOException;
028    import java.io.InputStream;
029    import java.util.ArrayList;
030    import java.util.Arrays;
031    import java.util.EnumSet;
032    import java.util.List;
033    
034    import org.apache.hadoop.fs.CacheFlag;
035    import org.apache.hadoop.fs.ContentSummary;
036    import org.apache.hadoop.fs.CreateFlag;
037    import org.apache.hadoop.fs.FsServerDefaults;
038    import org.apache.hadoop.fs.Path;
039    import org.apache.hadoop.fs.XAttr;
040    import org.apache.hadoop.fs.XAttrSetFlag;
041    import org.apache.hadoop.fs.permission.AclEntry;
042    import org.apache.hadoop.fs.permission.AclEntryScope;
043    import org.apache.hadoop.fs.permission.AclEntryType;
044    import org.apache.hadoop.fs.permission.AclStatus;
045    import org.apache.hadoop.fs.permission.FsAction;
046    import org.apache.hadoop.fs.permission.FsPermission;
047    import org.apache.hadoop.ha.HAServiceProtocol.HAServiceState;
048    import org.apache.hadoop.ha.proto.HAServiceProtocolProtos;
049    import org.apache.hadoop.hdfs.protocol.BlockStoragePolicy;
050    import org.apache.hadoop.hdfs.DFSUtil;
051    import org.apache.hadoop.hdfs.StorageType;
052    import org.apache.hadoop.hdfs.inotify.Event;
053    import org.apache.hadoop.hdfs.inotify.EventsList;
054    import org.apache.hadoop.hdfs.protocol.Block;
055    import org.apache.hadoop.hdfs.protocol.CacheDirectiveEntry;
056    import org.apache.hadoop.hdfs.protocol.CacheDirectiveInfo;
057    import org.apache.hadoop.hdfs.protocol.CacheDirectiveStats;
058    import org.apache.hadoop.hdfs.protocol.CachePoolEntry;
059    import org.apache.hadoop.hdfs.protocol.CachePoolInfo;
060    import org.apache.hadoop.hdfs.protocol.CachePoolStats;
061    import org.apache.hadoop.crypto.CipherOption;
062    import org.apache.hadoop.crypto.CipherSuite;
063    import org.apache.hadoop.hdfs.protocol.ClientProtocol;
064    import org.apache.hadoop.hdfs.protocol.CorruptFileBlocks;
065    import org.apache.hadoop.crypto.CryptoProtocolVersion;
066    import org.apache.hadoop.hdfs.protocol.DatanodeID;
067    import org.apache.hadoop.hdfs.protocol.DatanodeInfo;
068    import org.apache.hadoop.hdfs.protocol.DatanodeInfo.AdminStates;
069    import org.apache.hadoop.hdfs.protocol.DatanodeLocalInfo;
070    import org.apache.hadoop.hdfs.protocol.DirectoryListing;
071    import org.apache.hadoop.hdfs.protocol.EncryptionZone;
072    import org.apache.hadoop.hdfs.protocol.ExtendedBlock;
073    import org.apache.hadoop.fs.FileEncryptionInfo;
074    import org.apache.hadoop.hdfs.protocol.FsPermissionExtension;
075    import org.apache.hadoop.hdfs.protocol.HdfsConstants.DatanodeReportType;
076    import org.apache.hadoop.hdfs.protocol.HdfsConstants.RollingUpgradeAction;
077    import org.apache.hadoop.hdfs.protocol.HdfsConstants.SafeModeAction;
078    import org.apache.hadoop.hdfs.protocol.HdfsFileStatus;
079    import org.apache.hadoop.hdfs.protocol.HdfsLocatedFileStatus;
080    import org.apache.hadoop.hdfs.protocol.LocatedBlock;
081    import org.apache.hadoop.hdfs.protocol.LocatedBlocks;
082    import org.apache.hadoop.hdfs.protocol.RollingUpgradeInfo;
083    import org.apache.hadoop.hdfs.protocol.RollingUpgradeStatus;
084    import org.apache.hadoop.hdfs.protocol.SnapshotDiffReport;
085    import org.apache.hadoop.hdfs.protocol.SnapshotDiffReport.DiffReportEntry;
086    import org.apache.hadoop.hdfs.protocol.SnapshotDiffReport.DiffType;
087    import org.apache.hadoop.hdfs.protocol.SnapshottableDirectoryStatus;
088    import org.apache.hadoop.hdfs.protocol.proto.AclProtos.AclEntryProto;
089    import org.apache.hadoop.hdfs.protocol.proto.AclProtos.AclEntryProto.AclEntryScopeProto;
090    import org.apache.hadoop.hdfs.protocol.proto.AclProtos.AclEntryProto.AclEntryTypeProto;
091    import org.apache.hadoop.hdfs.protocol.proto.AclProtos.AclEntryProto.FsActionProto;
092    import org.apache.hadoop.hdfs.protocol.proto.AclProtos.AclStatusProto;
093    import org.apache.hadoop.hdfs.protocol.proto.AclProtos.GetAclStatusResponseProto;
094    import org.apache.hadoop.hdfs.protocol.proto.ClientNamenodeProtocolProtos;
095    import org.apache.hadoop.hdfs.protocol.proto.ClientNamenodeProtocolProtos.CacheDirectiveEntryProto;
096    import org.apache.hadoop.hdfs.protocol.proto.ClientNamenodeProtocolProtos.CacheDirectiveInfoExpirationProto;
097    import org.apache.hadoop.hdfs.protocol.proto.ClientNamenodeProtocolProtos.CacheDirectiveInfoProto;
098    import org.apache.hadoop.hdfs.protocol.proto.ClientNamenodeProtocolProtos.CacheDirectiveStatsProto;
099    import org.apache.hadoop.hdfs.protocol.proto.ClientNamenodeProtocolProtos.CacheFlagProto;
100    import org.apache.hadoop.hdfs.protocol.proto.ClientNamenodeProtocolProtos.CachePoolEntryProto;
101    import org.apache.hadoop.hdfs.protocol.proto.ClientNamenodeProtocolProtos.CachePoolInfoProto;
102    import org.apache.hadoop.hdfs.protocol.proto.ClientNamenodeProtocolProtos.CachePoolStatsProto;
103    import org.apache.hadoop.hdfs.protocol.proto.ClientNamenodeProtocolProtos.CreateFlagProto;
104    import org.apache.hadoop.hdfs.protocol.proto.ClientNamenodeProtocolProtos.DatanodeReportTypeProto;
105    import org.apache.hadoop.hdfs.protocol.proto.ClientNamenodeProtocolProtos.DatanodeStorageReportProto;
106    import org.apache.hadoop.hdfs.protocol.proto.ClientNamenodeProtocolProtos.GetEditsFromTxidResponseProto;
107    import org.apache.hadoop.hdfs.protocol.proto.ClientNamenodeProtocolProtos.GetFsStatsResponseProto;
108    import org.apache.hadoop.hdfs.protocol.proto.ClientNamenodeProtocolProtos.RollingUpgradeActionProto;
109    import org.apache.hadoop.hdfs.protocol.proto.ClientNamenodeProtocolProtos.RollingUpgradeInfoProto;
110    import org.apache.hadoop.hdfs.protocol.proto.ClientNamenodeProtocolProtos.SafeModeActionProto;
111    import org.apache.hadoop.hdfs.protocol.proto.DataTransferProtos.ShortCircuitShmIdProto;
112    import org.apache.hadoop.hdfs.protocol.proto.DataTransferProtos.ShortCircuitShmSlotProto;
113    import org.apache.hadoop.hdfs.protocol.proto.DatanodeProtocolProtos.BalancerBandwidthCommandProto;
114    import org.apache.hadoop.hdfs.protocol.proto.DatanodeProtocolProtos.BlockCommandProto;
115    import org.apache.hadoop.hdfs.protocol.proto.DatanodeProtocolProtos.BlockIdCommandProto;
116    import org.apache.hadoop.hdfs.protocol.proto.DatanodeProtocolProtos.BlockRecoveryCommandProto;
117    import org.apache.hadoop.hdfs.protocol.proto.DatanodeProtocolProtos.DatanodeCommandProto;
118    import org.apache.hadoop.hdfs.protocol.proto.DatanodeProtocolProtos.DatanodeRegistrationProto;
119    import org.apache.hadoop.hdfs.protocol.proto.DatanodeProtocolProtos.FinalizeCommandProto;
120    import org.apache.hadoop.hdfs.protocol.proto.DatanodeProtocolProtos.KeyUpdateCommandProto;
121    import org.apache.hadoop.hdfs.protocol.proto.DatanodeProtocolProtos.NNHAStatusHeartbeatProto;
122    import org.apache.hadoop.hdfs.protocol.proto.DatanodeProtocolProtos.ReceivedDeletedBlockInfoProto;
123    import org.apache.hadoop.hdfs.protocol.proto.DatanodeProtocolProtos.RegisterCommandProto;
124    import org.apache.hadoop.hdfs.protocol.proto.HdfsProtos;
125    import org.apache.hadoop.hdfs.protocol.proto.HdfsProtos.BlockKeyProto;
126    import org.apache.hadoop.hdfs.protocol.proto.HdfsProtos.BlockProto;
127    import org.apache.hadoop.hdfs.protocol.proto.HdfsProtos.BlockStoragePolicyProto;
128    import org.apache.hadoop.hdfs.protocol.proto.HdfsProtos.BlockWithLocationsProto;
129    import org.apache.hadoop.hdfs.protocol.proto.HdfsProtos.BlocksWithLocationsProto;
130    import org.apache.hadoop.hdfs.protocol.proto.HdfsProtos.CheckpointCommandProto;
131    import org.apache.hadoop.hdfs.protocol.proto.HdfsProtos.CheckpointSignatureProto;
132    import org.apache.hadoop.hdfs.protocol.proto.HdfsProtos.CipherOptionProto;
133    import org.apache.hadoop.hdfs.protocol.proto.HdfsProtos.ContentSummaryProto;
134    import org.apache.hadoop.hdfs.protocol.proto.HdfsProtos.CorruptFileBlocksProto;
135    import org.apache.hadoop.hdfs.protocol.proto.HdfsProtos.DataEncryptionKeyProto;
136    import org.apache.hadoop.hdfs.protocol.proto.HdfsProtos.DatanodeIDProto;
137    import org.apache.hadoop.hdfs.protocol.proto.HdfsProtos.DatanodeInfoProto;
138    import org.apache.hadoop.hdfs.protocol.proto.HdfsProtos.DatanodeInfoProto.AdminState;
139    import org.apache.hadoop.hdfs.protocol.proto.HdfsProtos.DatanodeInfosProto;
140    import org.apache.hadoop.hdfs.protocol.proto.HdfsProtos.DatanodeLocalInfoProto;
141    import org.apache.hadoop.hdfs.protocol.proto.HdfsProtos.DatanodeStorageProto;
142    import org.apache.hadoop.hdfs.protocol.proto.HdfsProtos.DatanodeStorageProto.StorageState;
143    import org.apache.hadoop.hdfs.protocol.proto.HdfsProtos.DirectoryListingProto;
144    import org.apache.hadoop.hdfs.protocol.proto.HdfsProtos.ExportedBlockKeysProto;
145    import org.apache.hadoop.hdfs.protocol.proto.HdfsProtos.ExtendedBlockProto;
146    import org.apache.hadoop.hdfs.protocol.proto.HdfsProtos.FsPermissionProto;
147    import org.apache.hadoop.hdfs.protocol.proto.HdfsProtos.FsServerDefaultsProto;
148    import org.apache.hadoop.hdfs.protocol.proto.HdfsProtos.HdfsFileStatusProto;
149    import org.apache.hadoop.hdfs.protocol.proto.HdfsProtos.HdfsFileStatusProto.FileType;
150    import org.apache.hadoop.hdfs.protocol.proto.HdfsProtos.LocatedBlockProto;
151    import org.apache.hadoop.hdfs.protocol.proto.HdfsProtos.LocatedBlockProto.Builder;
152    import org.apache.hadoop.hdfs.protocol.proto.HdfsProtos.LocatedBlocksProto;
153    import org.apache.hadoop.hdfs.protocol.proto.HdfsProtos.NamenodeCommandProto;
154    import org.apache.hadoop.hdfs.protocol.proto.HdfsProtos.NamenodeRegistrationProto;
155    import org.apache.hadoop.hdfs.protocol.proto.HdfsProtos.NamenodeRegistrationProto.NamenodeRoleProto;
156    import org.apache.hadoop.hdfs.protocol.proto.HdfsProtos.NamespaceInfoProto;
157    import org.apache.hadoop.hdfs.protocol.proto.HdfsProtos.RecoveringBlockProto;
158    import org.apache.hadoop.hdfs.protocol.proto.HdfsProtos.RemoteEditLogManifestProto;
159    import org.apache.hadoop.hdfs.protocol.proto.HdfsProtos.RemoteEditLogProto;
160    import org.apache.hadoop.hdfs.protocol.proto.HdfsProtos.ReplicaStateProto;
161    import org.apache.hadoop.hdfs.protocol.proto.HdfsProtos.RollingUpgradeStatusProto;
162    import org.apache.hadoop.hdfs.protocol.proto.HdfsProtos.SnapshotDiffReportEntryProto;
163    import org.apache.hadoop.hdfs.protocol.proto.HdfsProtos.SnapshotDiffReportProto;
164    import org.apache.hadoop.hdfs.protocol.proto.HdfsProtos.SnapshottableDirectoryListingProto;
165    import org.apache.hadoop.hdfs.protocol.proto.HdfsProtos.SnapshottableDirectoryStatusProto;
166    import org.apache.hadoop.hdfs.protocol.proto.HdfsProtos.StorageInfoProto;
167    import org.apache.hadoop.hdfs.protocol.proto.HdfsProtos.StorageReportProto;
168    import org.apache.hadoop.hdfs.protocol.proto.HdfsProtos.StorageTypeProto;
169    import org.apache.hadoop.hdfs.protocol.proto.HdfsProtos.StorageTypesProto;
170    import org.apache.hadoop.hdfs.protocol.proto.HdfsProtos.StorageUuidsProto;
171    import org.apache.hadoop.hdfs.protocol.proto.InotifyProtos;
172    import org.apache.hadoop.hdfs.protocol.proto.JournalProtocolProtos.JournalInfoProto;
173    import org.apache.hadoop.hdfs.protocol.proto.XAttrProtos.GetXAttrsResponseProto;
174    import org.apache.hadoop.hdfs.protocol.proto.XAttrProtos.ListXAttrsResponseProto;
175    import org.apache.hadoop.hdfs.protocol.proto.XAttrProtos.XAttrProto;
176    import org.apache.hadoop.hdfs.protocol.proto.XAttrProtos.XAttrProto.XAttrNamespaceProto;
177    import org.apache.hadoop.hdfs.protocol.proto.XAttrProtos.XAttrSetFlagProto;
178    import org.apache.hadoop.hdfs.security.token.block.BlockKey;
179    import org.apache.hadoop.hdfs.security.token.block.BlockTokenIdentifier;
180    import org.apache.hadoop.hdfs.security.token.block.DataEncryptionKey;
181    import org.apache.hadoop.hdfs.security.token.block.ExportedBlockKeys;
182    import org.apache.hadoop.hdfs.security.token.delegation.DelegationTokenIdentifier;
183    import org.apache.hadoop.hdfs.server.blockmanagement.BlockStoragePolicySuite;
184    import org.apache.hadoop.hdfs.server.common.HdfsServerConstants.NamenodeRole;
185    import org.apache.hadoop.hdfs.server.common.HdfsServerConstants.NodeType;
186    import org.apache.hadoop.hdfs.server.common.HdfsServerConstants.ReplicaState;
187    import org.apache.hadoop.hdfs.server.common.Storage;
188    import org.apache.hadoop.hdfs.server.common.StorageInfo;
189    import org.apache.hadoop.hdfs.server.namenode.CheckpointSignature;
190    import org.apache.hadoop.hdfs.server.namenode.INodeId;
191    import org.apache.hadoop.hdfs.server.protocol.BalancerBandwidthCommand;
192    import org.apache.hadoop.hdfs.server.protocol.BlockCommand;
193    import org.apache.hadoop.hdfs.server.protocol.BlockIdCommand;
194    import org.apache.hadoop.hdfs.server.protocol.BlockRecoveryCommand;
195    import org.apache.hadoop.hdfs.server.protocol.BlockRecoveryCommand.RecoveringBlock;
196    import org.apache.hadoop.hdfs.server.protocol.BlocksWithLocations;
197    import org.apache.hadoop.hdfs.server.protocol.BlocksWithLocations.BlockWithLocations;
198    import org.apache.hadoop.hdfs.server.protocol.CheckpointCommand;
199    import org.apache.hadoop.hdfs.server.protocol.DatanodeCommand;
200    import org.apache.hadoop.hdfs.server.protocol.DatanodeProtocol;
201    import org.apache.hadoop.hdfs.server.protocol.DatanodeRegistration;
202    import org.apache.hadoop.hdfs.server.protocol.DatanodeStorage;
203    import org.apache.hadoop.hdfs.server.protocol.DatanodeStorage.State;
204    import org.apache.hadoop.hdfs.server.protocol.DatanodeStorageReport;
205    import org.apache.hadoop.hdfs.server.protocol.FinalizeCommand;
206    import org.apache.hadoop.hdfs.server.protocol.JournalInfo;
207    import org.apache.hadoop.hdfs.server.protocol.KeyUpdateCommand;
208    import org.apache.hadoop.hdfs.server.protocol.NNHAStatusHeartbeat;
209    import org.apache.hadoop.hdfs.server.protocol.NamenodeCommand;
210    import org.apache.hadoop.hdfs.server.protocol.NamenodeRegistration;
211    import org.apache.hadoop.hdfs.server.protocol.NamespaceInfo;
212    import org.apache.hadoop.hdfs.server.protocol.ReceivedDeletedBlockInfo;
213    import org.apache.hadoop.hdfs.server.protocol.ReceivedDeletedBlockInfo.BlockStatus;
214    import org.apache.hadoop.hdfs.server.protocol.RegisterCommand;
215    import org.apache.hadoop.hdfs.server.protocol.RemoteEditLog;
216    import org.apache.hadoop.hdfs.server.protocol.RemoteEditLogManifest;
217    import org.apache.hadoop.hdfs.server.protocol.StorageReport;
218    import org.apache.hadoop.hdfs.shortcircuit.ShortCircuitShm.ShmId;
219    import org.apache.hadoop.hdfs.shortcircuit.ShortCircuitShm.SlotId;
220    import org.apache.hadoop.hdfs.util.ExactSizeInputStream;
221    import org.apache.hadoop.io.EnumSetWritable;
222    import org.apache.hadoop.io.Text;
223    import org.apache.hadoop.security.proto.SecurityProtos.TokenProto;
224    import org.apache.hadoop.security.token.Token;
225    import org.apache.hadoop.util.DataChecksum;
226    
227    import com.google.common.base.Preconditions;
228    import com.google.common.collect.Lists;
229    import com.google.common.primitives.Shorts;
230    import com.google.protobuf.ByteString;
231    import com.google.protobuf.CodedInputStream;
232    
233    /**
234     * Utilities for converting protobuf classes to and from implementation classes
235     * and other helper utilities to help in dealing with protobuf.
236     * 
237     * Note that when converting from an internal type to protobuf type, the
238     * converter never return null for protobuf type. The check for internal type
239     * being null must be done before calling the convert() method.
240     */
241    public class PBHelper {
242      private static final RegisterCommandProto REG_CMD_PROTO = 
243          RegisterCommandProto.newBuilder().build();
244      private static final RegisterCommand REG_CMD = new RegisterCommand();
245    
246      private static final AclEntryScope[] ACL_ENTRY_SCOPE_VALUES =
247          AclEntryScope.values();
248      private static final AclEntryType[] ACL_ENTRY_TYPE_VALUES =
249          AclEntryType.values();
250      private static final FsAction[] FSACTION_VALUES =
251          FsAction.values();
252      private static final XAttr.NameSpace[] XATTR_NAMESPACE_VALUES = 
253          XAttr.NameSpace.values();
254    
255      private PBHelper() {
256        /** Hidden constructor */
257      }
258    
259      public static ByteString getByteString(byte[] bytes) {
260        return ByteString.copyFrom(bytes);
261      }
262    
263      private static <T extends Enum<T>, U extends Enum<U>> U castEnum(T from, U[] to) {
264        return to[from.ordinal()];
265      }
266    
267      public static NamenodeRole convert(NamenodeRoleProto role) {
268        switch (role) {
269        case NAMENODE:
270          return NamenodeRole.NAMENODE;
271        case BACKUP:
272          return NamenodeRole.BACKUP;
273        case CHECKPOINT:
274          return NamenodeRole.CHECKPOINT;
275        }
276        return null;
277      }
278    
279      public static NamenodeRoleProto convert(NamenodeRole role) {
280        switch (role) {
281        case NAMENODE:
282          return NamenodeRoleProto.NAMENODE;
283        case BACKUP:
284          return NamenodeRoleProto.BACKUP;
285        case CHECKPOINT:
286          return NamenodeRoleProto.CHECKPOINT;
287        }
288        return null;
289      }
290    
291      public static BlockStoragePolicy[] convertStoragePolicies(
292          List<BlockStoragePolicyProto> policyProtos) {
293        if (policyProtos == null || policyProtos.size() == 0) {
294          return new BlockStoragePolicy[0];
295        }
296        BlockStoragePolicy[] policies = new BlockStoragePolicy[policyProtos.size()];
297        int i = 0;
298        for (BlockStoragePolicyProto proto : policyProtos) {
299          policies[i++] = convert(proto);
300        }
301        return policies;
302      }
303    
304      public static BlockStoragePolicy convert(BlockStoragePolicyProto proto) {
305        List<StorageTypeProto> cList = proto.getCreationPolicy()
306            .getStorageTypesList();
307        StorageType[] creationTypes = convertStorageTypes(cList, cList.size());
308        List<StorageTypeProto> cfList = proto.hasCreationFallbackPolicy() ? proto
309            .getCreationFallbackPolicy().getStorageTypesList() : null;
310        StorageType[] creationFallbackTypes = cfList == null ? StorageType
311            .EMPTY_ARRAY : convertStorageTypes(cfList, cfList.size());
312        List<StorageTypeProto> rfList = proto.hasReplicationFallbackPolicy() ?
313            proto.getReplicationFallbackPolicy().getStorageTypesList() : null;
314        StorageType[] replicationFallbackTypes = rfList == null ? StorageType
315            .EMPTY_ARRAY : convertStorageTypes(rfList, rfList.size());
316        return new BlockStoragePolicy((byte) proto.getPolicyId(), proto.getName(),
317            creationTypes, creationFallbackTypes, replicationFallbackTypes);
318      }
319    
320      public static BlockStoragePolicyProto convert(BlockStoragePolicy policy) {
321        BlockStoragePolicyProto.Builder builder = BlockStoragePolicyProto
322            .newBuilder().setPolicyId(policy.getId()).setName(policy.getName());
323        // creation storage types
324        StorageTypesProto creationProto = convert(policy.getStorageTypes());
325        Preconditions.checkArgument(creationProto != null);
326        builder.setCreationPolicy(creationProto);
327        // creation fallback
328        StorageTypesProto creationFallbackProto = convert(
329            policy.getCreationFallbacks());
330        if (creationFallbackProto != null) {
331          builder.setCreationFallbackPolicy(creationFallbackProto);
332        }
333        // replication fallback
334        StorageTypesProto replicationFallbackProto = convert(
335            policy.getReplicationFallbacks());
336        if (replicationFallbackProto != null) {
337          builder.setReplicationFallbackPolicy(replicationFallbackProto);
338        }
339        return builder.build();
340      }
341    
342      public static StorageTypesProto convert(StorageType[] types) {
343        if (types == null || types.length == 0) {
344          return null;
345        }
346        List<StorageTypeProto> list = convertStorageTypes(types);
347        return StorageTypesProto.newBuilder().addAllStorageTypes(list).build();
348      }
349    
350      public static StorageInfoProto convert(StorageInfo info) {
351        return StorageInfoProto.newBuilder().setClusterID(info.getClusterID())
352            .setCTime(info.getCTime()).setLayoutVersion(info.getLayoutVersion())
353            .setNamespceID(info.getNamespaceID()).build();
354      }
355    
356      public static StorageInfo convert(StorageInfoProto info, NodeType type) {
357        return new StorageInfo(info.getLayoutVersion(), info.getNamespceID(),
358            info.getClusterID(), info.getCTime(), type);
359      }
360    
361      public static NamenodeRegistrationProto convert(NamenodeRegistration reg) {
362        return NamenodeRegistrationProto.newBuilder()
363            .setHttpAddress(reg.getHttpAddress()).setRole(convert(reg.getRole()))
364            .setRpcAddress(reg.getAddress())
365            .setStorageInfo(convert((StorageInfo) reg)).build();
366      }
367    
368      public static NamenodeRegistration convert(NamenodeRegistrationProto reg) {
369        StorageInfo si = convert(reg.getStorageInfo(), NodeType.NAME_NODE);
370        return new NamenodeRegistration(reg.getRpcAddress(), reg.getHttpAddress(),
371            si, convert(reg.getRole()));
372      }
373    
374      // DatanodeId
375      public static DatanodeID convert(DatanodeIDProto dn) {
376        return new DatanodeID(dn.getIpAddr(), dn.getHostName(), dn.getDatanodeUuid(),
377            dn.getXferPort(), dn.getInfoPort(), dn.hasInfoSecurePort() ? dn
378            .getInfoSecurePort() : 0, dn.getIpcPort());
379      }
380    
381      public static DatanodeIDProto convert(DatanodeID dn) {
382        // For wire compatibility with older versions we transmit the StorageID
383        // which is the same as the DatanodeUuid. Since StorageID is a required
384        // field we pass the empty string if the DatanodeUuid is not yet known.
385        return DatanodeIDProto.newBuilder()
386            .setIpAddr(dn.getIpAddr())
387            .setHostName(dn.getHostName())
388            .setXferPort(dn.getXferPort())
389            .setDatanodeUuid(dn.getDatanodeUuid() != null ? dn.getDatanodeUuid() : "")
390            .setInfoPort(dn.getInfoPort())
391            .setInfoSecurePort(dn.getInfoSecurePort())
392            .setIpcPort(dn.getIpcPort()).build();
393      }
394    
395      // Arrays of DatanodeId
396      public static DatanodeIDProto[] convert(DatanodeID[] did) {
397        if (did == null)
398          return null;
399        final int len = did.length;
400        DatanodeIDProto[] result = new DatanodeIDProto[len];
401        for (int i = 0; i < len; ++i) {
402          result[i] = convert(did[i]);
403        }
404        return result;
405      }
406      
407      public static DatanodeID[] convert(DatanodeIDProto[] did) {
408        if (did == null) return null;
409        final int len = did.length;
410        DatanodeID[] result = new DatanodeID[len];
411        for (int i = 0; i < len; ++i) {
412          result[i] = convert(did[i]);
413        }
414        return result;
415      }
416      
417      // Block
418      public static BlockProto convert(Block b) {
419        return BlockProto.newBuilder().setBlockId(b.getBlockId())
420            .setGenStamp(b.getGenerationStamp()).setNumBytes(b.getNumBytes())
421            .build();
422      }
423    
424      public static Block convert(BlockProto b) {
425        return new Block(b.getBlockId(), b.getNumBytes(), b.getGenStamp());
426      }
427    
428      public static BlockWithLocationsProto convert(BlockWithLocations blk) {
429        return BlockWithLocationsProto.newBuilder()
430            .setBlock(convert(blk.getBlock()))
431            .addAllDatanodeUuids(Arrays.asList(blk.getDatanodeUuids()))
432            .addAllStorageUuids(Arrays.asList(blk.getStorageIDs()))
433            .addAllStorageTypes(convertStorageTypes(blk.getStorageTypes()))
434            .build();
435      }
436    
437      public static BlockWithLocations convert(BlockWithLocationsProto b) {
438        final List<String> datanodeUuids = b.getDatanodeUuidsList();
439        final List<String> storageUuids = b.getStorageUuidsList();
440        final List<StorageTypeProto> storageTypes = b.getStorageTypesList();
441        return new BlockWithLocations(convert(b.getBlock()),
442            datanodeUuids.toArray(new String[datanodeUuids.size()]),
443            storageUuids.toArray(new String[storageUuids.size()]),
444            convertStorageTypes(storageTypes, storageUuids.size()));
445      }
446    
447      public static BlocksWithLocationsProto convert(BlocksWithLocations blks) {
448        BlocksWithLocationsProto.Builder builder = BlocksWithLocationsProto
449            .newBuilder();
450        for (BlockWithLocations b : blks.getBlocks()) {
451          builder.addBlocks(convert(b));
452        }
453        return builder.build();
454      }
455    
456      public static BlocksWithLocations convert(BlocksWithLocationsProto blocks) {
457        List<BlockWithLocationsProto> b = blocks.getBlocksList();
458        BlockWithLocations[] ret = new BlockWithLocations[b.size()];
459        int i = 0;
460        for (BlockWithLocationsProto entry : b) {
461          ret[i++] = convert(entry);
462        }
463        return new BlocksWithLocations(ret);
464      }
465    
466      public static BlockKeyProto convert(BlockKey key) {
467        byte[] encodedKey = key.getEncodedKey();
468        ByteString keyBytes = ByteString.copyFrom(encodedKey == null ? 
469            DFSUtil.EMPTY_BYTES : encodedKey);
470        return BlockKeyProto.newBuilder().setKeyId(key.getKeyId())
471            .setKeyBytes(keyBytes).setExpiryDate(key.getExpiryDate()).build();
472      }
473    
474      public static BlockKey convert(BlockKeyProto k) {
475        return new BlockKey(k.getKeyId(), k.getExpiryDate(), k.getKeyBytes()
476            .toByteArray());
477      }
478    
479      public static ExportedBlockKeysProto convert(ExportedBlockKeys keys) {
480        ExportedBlockKeysProto.Builder builder = ExportedBlockKeysProto
481            .newBuilder();
482        builder.setIsBlockTokenEnabled(keys.isBlockTokenEnabled())
483            .setKeyUpdateInterval(keys.getKeyUpdateInterval())
484            .setTokenLifeTime(keys.getTokenLifetime())
485            .setCurrentKey(convert(keys.getCurrentKey()));
486        for (BlockKey k : keys.getAllKeys()) {
487          builder.addAllKeys(convert(k));
488        }
489        return builder.build();
490      }
491    
492      public static ExportedBlockKeys convert(ExportedBlockKeysProto keys) {
493        return new ExportedBlockKeys(keys.getIsBlockTokenEnabled(),
494            keys.getKeyUpdateInterval(), keys.getTokenLifeTime(),
495            convert(keys.getCurrentKey()), convertBlockKeys(keys.getAllKeysList()));
496      }
497    
498      public static CheckpointSignatureProto convert(CheckpointSignature s) {
499        return CheckpointSignatureProto.newBuilder()
500            .setBlockPoolId(s.getBlockpoolID())
501            .setCurSegmentTxId(s.getCurSegmentTxId())
502            .setMostRecentCheckpointTxId(s.getMostRecentCheckpointTxId())
503            .setStorageInfo(PBHelper.convert((StorageInfo) s)).build();
504      }
505    
506      public static CheckpointSignature convert(CheckpointSignatureProto s) {
507        StorageInfo si = PBHelper.convert(s.getStorageInfo(), NodeType.NAME_NODE);
508        return new CheckpointSignature(si, s.getBlockPoolId(),
509            s.getMostRecentCheckpointTxId(), s.getCurSegmentTxId());
510      }
511    
512      public static RemoteEditLogProto convert(RemoteEditLog log) {
513        return RemoteEditLogProto.newBuilder()
514            .setStartTxId(log.getStartTxId())
515            .setEndTxId(log.getEndTxId())
516            .setIsInProgress(log.isInProgress()).build();
517      }
518    
519      public static RemoteEditLog convert(RemoteEditLogProto l) {
520        return new RemoteEditLog(l.getStartTxId(), l.getEndTxId(),
521            l.getIsInProgress());
522      }
523    
524      public static RemoteEditLogManifestProto convert(
525          RemoteEditLogManifest manifest) {
526        RemoteEditLogManifestProto.Builder builder = RemoteEditLogManifestProto
527            .newBuilder();
528        for (RemoteEditLog log : manifest.getLogs()) {
529          builder.addLogs(convert(log));
530        }
531        return builder.build();
532      }
533    
534      public static RemoteEditLogManifest convert(
535          RemoteEditLogManifestProto manifest) {
536        List<RemoteEditLog> logs = new ArrayList<RemoteEditLog>(manifest
537            .getLogsList().size());
538        for (RemoteEditLogProto l : manifest.getLogsList()) {
539          logs.add(convert(l));
540        }
541        return new RemoteEditLogManifest(logs);
542      }
543    
544      public static CheckpointCommandProto convert(CheckpointCommand cmd) {
545        return CheckpointCommandProto.newBuilder()
546            .setSignature(convert(cmd.getSignature()))
547            .setNeedToReturnImage(cmd.needToReturnImage()).build();
548      }
549    
550      public static NamenodeCommandProto convert(NamenodeCommand cmd) {
551        if (cmd instanceof CheckpointCommand) {
552          return NamenodeCommandProto.newBuilder().setAction(cmd.getAction())
553              .setType(NamenodeCommandProto.Type.CheckPointCommand)
554              .setCheckpointCmd(convert((CheckpointCommand) cmd)).build();
555        }
556        return NamenodeCommandProto.newBuilder()
557            .setType(NamenodeCommandProto.Type.NamenodeCommand)
558            .setAction(cmd.getAction()).build();
559      }
560    
561      public static BlockKey[] convertBlockKeys(List<BlockKeyProto> list) {
562        BlockKey[] ret = new BlockKey[list.size()];
563        int i = 0;
564        for (BlockKeyProto k : list) {
565          ret[i++] = convert(k);
566        }
567        return ret;
568      }
569    
570      public static NamespaceInfo convert(NamespaceInfoProto info) {
571        StorageInfoProto storage = info.getStorageInfo();
572        return new NamespaceInfo(storage.getNamespceID(), storage.getClusterID(),
573            info.getBlockPoolID(), storage.getCTime(), info.getBuildVersion(),
574            info.getSoftwareVersion());
575      }
576    
577      public static NamenodeCommand convert(NamenodeCommandProto cmd) {
578        if (cmd == null) return null;
579        switch (cmd.getType()) {
580        case CheckPointCommand:
581          CheckpointCommandProto chkPt = cmd.getCheckpointCmd();
582          return new CheckpointCommand(PBHelper.convert(chkPt.getSignature()),
583              chkPt.getNeedToReturnImage());
584        default:
585          return new NamenodeCommand(cmd.getAction());
586        }
587      }
588      
589      public static ExtendedBlock convert(ExtendedBlockProto eb) {
590        if (eb == null) return null;
591        return new ExtendedBlock( eb.getPoolId(),  eb.getBlockId(),   eb.getNumBytes(),
592           eb.getGenerationStamp());
593      }
594      
595      public static ExtendedBlockProto convert(final ExtendedBlock b) {
596        if (b == null) return null;
597       return ExtendedBlockProto.newBuilder().
598          setPoolId(b.getBlockPoolId()).
599          setBlockId(b.getBlockId()).
600          setNumBytes(b.getNumBytes()).
601          setGenerationStamp(b.getGenerationStamp()).
602          build();
603      }
604      
605      public static RecoveringBlockProto convert(RecoveringBlock b) {
606        if (b == null) {
607          return null;
608        }
609        LocatedBlockProto lb = PBHelper.convert((LocatedBlock)b);
610        return RecoveringBlockProto.newBuilder().setBlock(lb)
611            .setNewGenStamp(b.getNewGenerationStamp()).build();
612      }
613    
614      public static RecoveringBlock convert(RecoveringBlockProto b) {
615        ExtendedBlock block = convert(b.getBlock().getB());
616        DatanodeInfo[] locs = convert(b.getBlock().getLocsList());
617        return new RecoveringBlock(block, locs, b.getNewGenStamp());
618      }
619      
620      public static DatanodeInfoProto.AdminState convert(
621          final DatanodeInfo.AdminStates inAs) {
622        switch (inAs) {
623        case NORMAL: return  DatanodeInfoProto.AdminState.NORMAL;
624        case DECOMMISSION_INPROGRESS: 
625            return DatanodeInfoProto.AdminState.DECOMMISSION_INPROGRESS;
626        case DECOMMISSIONED: return DatanodeInfoProto.AdminState.DECOMMISSIONED;
627        default: return DatanodeInfoProto.AdminState.NORMAL;
628        }
629      }
630      
631      static public DatanodeInfo convert(DatanodeInfoProto di) {
632        if (di == null) return null;
633        return new DatanodeInfo(
634            PBHelper.convert(di.getId()),
635            di.hasLocation() ? di.getLocation() : null , 
636            di.getCapacity(),  di.getDfsUsed(),  di.getRemaining(),
637            di.getBlockPoolUsed(), di.getCacheCapacity(), di.getCacheUsed(),
638            di.getLastUpdate(), di.getXceiverCount(),
639            PBHelper.convert(di.getAdminState())); 
640      }
641      
642      static public DatanodeInfoProto convertDatanodeInfo(DatanodeInfo di) {
643        if (di == null) return null;
644        return convert(di);
645      }
646      
647      
648      static public DatanodeInfo[] convert(DatanodeInfoProto di[]) {
649        if (di == null) return null;
650        DatanodeInfo[] result = new DatanodeInfo[di.length];
651        for (int i = 0; i < di.length; i++) {
652          result[i] = convert(di[i]);
653        }    
654        return result;
655      }
656    
657      public static List<? extends HdfsProtos.DatanodeInfoProto> convert(
658          DatanodeInfo[] dnInfos) {
659        return convert(dnInfos, 0);
660      }
661      
662      /**
663       * Copy from {@code dnInfos} to a target of list of same size starting at
664       * {@code startIdx}.
665       */
666      public static List<? extends HdfsProtos.DatanodeInfoProto> convert(
667          DatanodeInfo[] dnInfos, int startIdx) {
668        if (dnInfos == null)
669          return null;
670        ArrayList<HdfsProtos.DatanodeInfoProto> protos = Lists
671            .newArrayListWithCapacity(dnInfos.length);
672        for (int i = startIdx; i < dnInfos.length; i++) {
673          protos.add(convert(dnInfos[i]));
674        }
675        return protos;
676      }
677    
678      public static DatanodeInfo[] convert(List<DatanodeInfoProto> list) {
679        DatanodeInfo[] info = new DatanodeInfo[list.size()];
680        for (int i = 0; i < info.length; i++) {
681          info[i] = convert(list.get(i));
682        }
683        return info;
684      }
685      
686      public static DatanodeInfoProto convert(DatanodeInfo info) {
687        DatanodeInfoProto.Builder builder = DatanodeInfoProto.newBuilder();
688        if (info.getNetworkLocation() != null) {
689          builder.setLocation(info.getNetworkLocation());
690        }
691        builder
692            .setId(PBHelper.convert((DatanodeID)info))
693            .setCapacity(info.getCapacity())
694            .setDfsUsed(info.getDfsUsed())
695            .setRemaining(info.getRemaining())
696            .setBlockPoolUsed(info.getBlockPoolUsed())
697            .setCacheCapacity(info.getCacheCapacity())
698            .setCacheUsed(info.getCacheUsed())
699            .setLastUpdate(info.getLastUpdate())
700            .setXceiverCount(info.getXceiverCount())
701            .setAdminState(PBHelper.convert(info.getAdminState()))
702            .build();
703        return builder.build();
704      }
705    
706      public static DatanodeStorageReportProto convertDatanodeStorageReport(
707          DatanodeStorageReport report) {
708        return DatanodeStorageReportProto.newBuilder()
709            .setDatanodeInfo(convert(report.getDatanodeInfo()))
710            .addAllStorageReports(convertStorageReports(report.getStorageReports()))
711            .build();
712      }
713    
714      public static List<DatanodeStorageReportProto> convertDatanodeStorageReports(
715          DatanodeStorageReport[] reports) {
716        final List<DatanodeStorageReportProto> protos
717            = new ArrayList<DatanodeStorageReportProto>(reports.length);
718        for(int i = 0; i < reports.length; i++) {
719          protos.add(convertDatanodeStorageReport(reports[i]));
720        }
721        return protos;
722      }
723    
724      public static DatanodeStorageReport convertDatanodeStorageReport(
725          DatanodeStorageReportProto proto) {
726        return new DatanodeStorageReport(
727            convert(proto.getDatanodeInfo()),
728            convertStorageReports(proto.getStorageReportsList()));
729      }
730    
731      public static DatanodeStorageReport[] convertDatanodeStorageReports(
732          List<DatanodeStorageReportProto> protos) {
733        final DatanodeStorageReport[] reports
734            = new DatanodeStorageReport[protos.size()];
735        for(int i = 0; i < reports.length; i++) {
736          reports[i] = convertDatanodeStorageReport(protos.get(i));
737        }
738        return reports;
739      }
740    
741      public static AdminStates convert(AdminState adminState) {
742        switch(adminState) {
743        case DECOMMISSION_INPROGRESS:
744          return AdminStates.DECOMMISSION_INPROGRESS;
745        case DECOMMISSIONED:
746          return AdminStates.DECOMMISSIONED;
747        case NORMAL:
748        default:
749          return AdminStates.NORMAL;
750        }
751      }
752      
753      public static LocatedBlockProto convert(LocatedBlock b) {
754        if (b == null) return null;
755        Builder builder = LocatedBlockProto.newBuilder();
756        DatanodeInfo[] locs = b.getLocations();
757        List<DatanodeInfo> cachedLocs =
758            Lists.newLinkedList(Arrays.asList(b.getCachedLocations()));
759        for (int i = 0; i < locs.length; i++) {
760          DatanodeInfo loc = locs[i];
761          builder.addLocs(i, PBHelper.convert(loc));
762          boolean locIsCached = cachedLocs.contains(loc);
763          builder.addIsCached(locIsCached);
764          if (locIsCached) {
765            cachedLocs.remove(loc);
766          }
767        }
768        Preconditions.checkArgument(cachedLocs.size() == 0,
769            "Found additional cached replica locations that are not in the set of"
770            + " storage-backed locations!");
771    
772        StorageType[] storageTypes = b.getStorageTypes();
773        if (storageTypes != null) {
774          for (int i = 0; i < storageTypes.length; ++i) {
775            builder.addStorageTypes(PBHelper.convertStorageType(storageTypes[i]));
776          }
777        }
778        final String[] storageIDs = b.getStorageIDs();
779        if (storageIDs != null) {
780          builder.addAllStorageIDs(Arrays.asList(storageIDs));
781        }
782    
783        return builder.setB(PBHelper.convert(b.getBlock()))
784            .setBlockToken(PBHelper.convert(b.getBlockToken()))
785            .setCorrupt(b.isCorrupt()).setOffset(b.getStartOffset()).build();
786      }
787      
788      public static LocatedBlock convert(LocatedBlockProto proto) {
789        if (proto == null) return null;
790        List<DatanodeInfoProto> locs = proto.getLocsList();
791        DatanodeInfo[] targets = new DatanodeInfo[locs.size()];
792        for (int i = 0; i < locs.size(); i++) {
793          targets[i] = PBHelper.convert(locs.get(i));
794        }
795    
796        final StorageType[] storageTypes = convertStorageTypes(
797            proto.getStorageTypesList(), locs.size());
798    
799        final int storageIDsCount = proto.getStorageIDsCount();
800        final String[] storageIDs;
801        if (storageIDsCount == 0) {
802          storageIDs = null;
803        } else {
804          Preconditions.checkState(storageIDsCount == locs.size());
805          storageIDs = proto.getStorageIDsList().toArray(new String[storageIDsCount]);
806        }
807    
808        // Set values from the isCached list, re-using references from loc
809        List<DatanodeInfo> cachedLocs = new ArrayList<DatanodeInfo>(locs.size());
810        List<Boolean> isCachedList = proto.getIsCachedList();
811        for (int i=0; i<isCachedList.size(); i++) {
812          if (isCachedList.get(i)) {
813            cachedLocs.add(targets[i]);
814          }
815        }
816    
817        LocatedBlock lb = new LocatedBlock(PBHelper.convert(proto.getB()), targets,
818            storageIDs, storageTypes, proto.getOffset(), proto.getCorrupt(),
819            cachedLocs.toArray(new DatanodeInfo[0]));
820        lb.setBlockToken(PBHelper.convert(proto.getBlockToken()));
821    
822        return lb;
823      }
824    
825      public static TokenProto convert(Token<?> tok) {
826        return TokenProto.newBuilder().
827                  setIdentifier(ByteString.copyFrom(tok.getIdentifier())).
828                  setPassword(ByteString.copyFrom(tok.getPassword())).
829                  setKind(tok.getKind().toString()).
830                  setService(tok.getService().toString()).build(); 
831      }
832      
833      public static Token<BlockTokenIdentifier> convert(
834          TokenProto blockToken) {
835        return new Token<BlockTokenIdentifier>(blockToken.getIdentifier()
836            .toByteArray(), blockToken.getPassword().toByteArray(), new Text(
837            blockToken.getKind()), new Text(blockToken.getService()));
838      }
839    
840      
841      public static Token<DelegationTokenIdentifier> convertDelegationToken(
842          TokenProto blockToken) {
843        return new Token<DelegationTokenIdentifier>(blockToken.getIdentifier()
844            .toByteArray(), blockToken.getPassword().toByteArray(), new Text(
845            blockToken.getKind()), new Text(blockToken.getService()));
846      }
847    
848      public static ReplicaState convert(ReplicaStateProto state) {
849        switch (state) {
850        case RBW:
851          return ReplicaState.RBW;
852        case RUR:
853          return ReplicaState.RUR;
854        case RWR:
855          return ReplicaState.RWR;
856        case TEMPORARY:
857          return ReplicaState.TEMPORARY;
858        case FINALIZED:
859        default:
860          return ReplicaState.FINALIZED;
861        }
862      }
863    
864      public static ReplicaStateProto convert(ReplicaState state) {
865        switch (state) {
866        case RBW:
867          return ReplicaStateProto.RBW;
868        case RUR:
869          return ReplicaStateProto.RUR;
870        case RWR:
871          return ReplicaStateProto.RWR;
872        case TEMPORARY:
873          return ReplicaStateProto.TEMPORARY;
874        case FINALIZED:
875        default:
876          return ReplicaStateProto.FINALIZED;
877        }
878      }
879      
880      public static DatanodeRegistrationProto convert(
881          DatanodeRegistration registration) {
882        DatanodeRegistrationProto.Builder builder = DatanodeRegistrationProto
883            .newBuilder();
884        return builder.setDatanodeID(PBHelper.convert((DatanodeID) registration))
885            .setStorageInfo(PBHelper.convert(registration.getStorageInfo()))
886            .setKeys(PBHelper.convert(registration.getExportedKeys()))
887            .setSoftwareVersion(registration.getSoftwareVersion()).build();
888      }
889    
890      public static DatanodeRegistration convert(DatanodeRegistrationProto proto) {
891        StorageInfo si = convert(proto.getStorageInfo(), NodeType.DATA_NODE);
892        return new DatanodeRegistration(PBHelper.convert(proto.getDatanodeID()),
893            si, PBHelper.convert(proto.getKeys()), proto.getSoftwareVersion());
894      }
895    
896      public static DatanodeCommand convert(DatanodeCommandProto proto) {
897        switch (proto.getCmdType()) {
898        case BalancerBandwidthCommand:
899          return PBHelper.convert(proto.getBalancerCmd());
900        case BlockCommand:
901          return PBHelper.convert(proto.getBlkCmd());
902        case BlockRecoveryCommand:
903          return PBHelper.convert(proto.getRecoveryCmd());
904        case FinalizeCommand:
905          return PBHelper.convert(proto.getFinalizeCmd());
906        case KeyUpdateCommand:
907          return PBHelper.convert(proto.getKeyUpdateCmd());
908        case RegisterCommand:
909          return REG_CMD;
910        case BlockIdCommand:
911          return PBHelper.convert(proto.getBlkIdCmd());
912        default:
913          return null;
914        }
915      }
916      
917      public static BalancerBandwidthCommandProto convert(
918          BalancerBandwidthCommand bbCmd) {
919        return BalancerBandwidthCommandProto.newBuilder()
920            .setBandwidth(bbCmd.getBalancerBandwidthValue()).build();
921      }
922    
923      public static KeyUpdateCommandProto convert(KeyUpdateCommand cmd) {
924        return KeyUpdateCommandProto.newBuilder()
925            .setKeys(PBHelper.convert(cmd.getExportedKeys())).build();
926      }
927    
928      public static BlockRecoveryCommandProto convert(BlockRecoveryCommand cmd) {
929        BlockRecoveryCommandProto.Builder builder = BlockRecoveryCommandProto
930            .newBuilder();
931        for (RecoveringBlock b : cmd.getRecoveringBlocks()) {
932          builder.addBlocks(PBHelper.convert(b));
933        }
934        return builder.build();
935      }
936    
937      public static FinalizeCommandProto convert(FinalizeCommand cmd) {
938        return FinalizeCommandProto.newBuilder()
939            .setBlockPoolId(cmd.getBlockPoolId()).build();
940      }
941    
942      public static BlockCommandProto convert(BlockCommand cmd) {
943        BlockCommandProto.Builder builder = BlockCommandProto.newBuilder()
944            .setBlockPoolId(cmd.getBlockPoolId());
945        switch (cmd.getAction()) {
946        case DatanodeProtocol.DNA_TRANSFER:
947          builder.setAction(BlockCommandProto.Action.TRANSFER);
948          break;
949        case DatanodeProtocol.DNA_INVALIDATE:
950          builder.setAction(BlockCommandProto.Action.INVALIDATE);
951          break;
952        case DatanodeProtocol.DNA_SHUTDOWN:
953          builder.setAction(BlockCommandProto.Action.SHUTDOWN);
954          break;
955        default:
956          throw new AssertionError("Invalid action");
957        }
958        Block[] blocks = cmd.getBlocks();
959        for (int i = 0; i < blocks.length; i++) {
960          builder.addBlocks(PBHelper.convert(blocks[i]));
961        }
962        builder.addAllTargets(convert(cmd.getTargets()))
963               .addAllTargetStorageUuids(convert(cmd.getTargetStorageIDs()));
964        StorageType[][] types = cmd.getTargetStorageTypes();
965        if (types != null) {
966          builder.addAllTargetStorageTypes(convert(types));
967        }
968        return builder.build();
969      }
970    
971      private static List<StorageTypesProto> convert(StorageType[][] types) {
972        List<StorageTypesProto> list = Lists.newArrayList();
973        if (types != null) {
974          for (StorageType[] ts : types) {
975            StorageTypesProto.Builder builder = StorageTypesProto.newBuilder();
976            builder.addAllStorageTypes(convertStorageTypes(ts));
977            list.add(builder.build());
978          }
979        }
980        return list;
981      }
982    
983      public static BlockIdCommandProto convert(BlockIdCommand cmd) {
984        BlockIdCommandProto.Builder builder = BlockIdCommandProto.newBuilder()
985            .setBlockPoolId(cmd.getBlockPoolId());
986        switch (cmd.getAction()) {
987        case DatanodeProtocol.DNA_CACHE:
988          builder.setAction(BlockIdCommandProto.Action.CACHE);
989          break;
990        case DatanodeProtocol.DNA_UNCACHE:
991          builder.setAction(BlockIdCommandProto.Action.UNCACHE);
992          break;
993        default:
994          throw new AssertionError("Invalid action");
995        }
996        long[] blockIds = cmd.getBlockIds();
997        for (int i = 0; i < blockIds.length; i++) {
998          builder.addBlockIds(blockIds[i]);
999        }
1000        return builder.build();
1001      }
1002    
1003      private static List<DatanodeInfosProto> convert(DatanodeInfo[][] targets) {
1004        DatanodeInfosProto[] ret = new DatanodeInfosProto[targets.length];
1005        for (int i = 0; i < targets.length; i++) {
1006          ret[i] = DatanodeInfosProto.newBuilder()
1007              .addAllDatanodes(PBHelper.convert(targets[i])).build();
1008        }
1009        return Arrays.asList(ret);
1010      }
1011    
1012      private static List<StorageUuidsProto> convert(String[][] targetStorageUuids) {
1013        StorageUuidsProto[] ret = new StorageUuidsProto[targetStorageUuids.length];
1014        for (int i = 0; i < targetStorageUuids.length; i++) {
1015          ret[i] = StorageUuidsProto.newBuilder()
1016              .addAllStorageUuids(Arrays.asList(targetStorageUuids[i])).build();
1017        }
1018        return Arrays.asList(ret);
1019      }
1020    
1021      public static DatanodeCommandProto convert(DatanodeCommand datanodeCommand) {
1022        DatanodeCommandProto.Builder builder = DatanodeCommandProto.newBuilder();
1023        if (datanodeCommand == null) {
1024          return builder.setCmdType(DatanodeCommandProto.Type.NullDatanodeCommand)
1025              .build();
1026        }
1027        switch (datanodeCommand.getAction()) {
1028        case DatanodeProtocol.DNA_BALANCERBANDWIDTHUPDATE:
1029          builder.setCmdType(DatanodeCommandProto.Type.BalancerBandwidthCommand)
1030              .setBalancerCmd(
1031                  PBHelper.convert((BalancerBandwidthCommand) datanodeCommand));
1032          break;
1033        case DatanodeProtocol.DNA_ACCESSKEYUPDATE:
1034          builder
1035              .setCmdType(DatanodeCommandProto.Type.KeyUpdateCommand)
1036              .setKeyUpdateCmd(PBHelper.convert((KeyUpdateCommand) datanodeCommand));
1037          break;
1038        case DatanodeProtocol.DNA_RECOVERBLOCK:
1039          builder.setCmdType(DatanodeCommandProto.Type.BlockRecoveryCommand)
1040              .setRecoveryCmd(
1041                  PBHelper.convert((BlockRecoveryCommand) datanodeCommand));
1042          break;
1043        case DatanodeProtocol.DNA_FINALIZE:
1044          builder.setCmdType(DatanodeCommandProto.Type.FinalizeCommand)
1045              .setFinalizeCmd(PBHelper.convert((FinalizeCommand) datanodeCommand));
1046          break;
1047        case DatanodeProtocol.DNA_REGISTER:
1048          builder.setCmdType(DatanodeCommandProto.Type.RegisterCommand)
1049              .setRegisterCmd(REG_CMD_PROTO);
1050          break;
1051        case DatanodeProtocol.DNA_TRANSFER:
1052        case DatanodeProtocol.DNA_INVALIDATE:
1053        case DatanodeProtocol.DNA_SHUTDOWN:
1054          builder.setCmdType(DatanodeCommandProto.Type.BlockCommand).
1055            setBlkCmd(PBHelper.convert((BlockCommand) datanodeCommand));
1056          break;
1057        case DatanodeProtocol.DNA_CACHE:
1058        case DatanodeProtocol.DNA_UNCACHE:
1059          builder.setCmdType(DatanodeCommandProto.Type.BlockIdCommand).
1060            setBlkIdCmd(PBHelper.convert((BlockIdCommand) datanodeCommand));
1061          break;
1062        case DatanodeProtocol.DNA_UNKNOWN: //Not expected
1063        default:
1064          builder.setCmdType(DatanodeCommandProto.Type.NullDatanodeCommand);
1065        }
1066        return builder.build();
1067      }
1068    
1069      public static KeyUpdateCommand convert(KeyUpdateCommandProto keyUpdateCmd) {
1070        return new KeyUpdateCommand(PBHelper.convert(keyUpdateCmd.getKeys()));
1071      }
1072    
1073      public static FinalizeCommand convert(FinalizeCommandProto finalizeCmd) {
1074        return new FinalizeCommand(finalizeCmd.getBlockPoolId());
1075      }
1076    
1077      public static BlockRecoveryCommand convert(
1078          BlockRecoveryCommandProto recoveryCmd) {
1079        List<RecoveringBlockProto> list = recoveryCmd.getBlocksList();
1080        List<RecoveringBlock> recoveringBlocks = new ArrayList<RecoveringBlock>(
1081            list.size());
1082        
1083        for (RecoveringBlockProto rbp : list) {
1084          recoveringBlocks.add(PBHelper.convert(rbp));
1085        }
1086        return new BlockRecoveryCommand(recoveringBlocks);
1087      }
1088    
1089      public static BlockCommand convert(BlockCommandProto blkCmd) {
1090        List<BlockProto> blockProtoList = blkCmd.getBlocksList();
1091        Block[] blocks = new Block[blockProtoList.size()];
1092        for (int i = 0; i < blockProtoList.size(); i++) {
1093          blocks[i] = PBHelper.convert(blockProtoList.get(i));
1094        }
1095        List<DatanodeInfosProto> targetList = blkCmd.getTargetsList();
1096        DatanodeInfo[][] targets = new DatanodeInfo[targetList.size()][];
1097        for (int i = 0; i < targetList.size(); i++) {
1098          targets[i] = PBHelper.convert(targetList.get(i));
1099        }
1100    
1101        StorageType[][] targetStorageTypes = new StorageType[targetList.size()][];
1102        List<StorageTypesProto> targetStorageTypesList = blkCmd.getTargetStorageTypesList();
1103        if (targetStorageTypesList.isEmpty()) { // missing storage types
1104          for(int i = 0; i < targetStorageTypes.length; i++) {
1105            targetStorageTypes[i] = new StorageType[targets[i].length];
1106            Arrays.fill(targetStorageTypes[i], StorageType.DEFAULT);
1107          }
1108        } else {
1109          for(int i = 0; i < targetStorageTypes.length; i++) {
1110            List<StorageTypeProto> p = targetStorageTypesList.get(i).getStorageTypesList();
1111            targetStorageTypes[i] = convertStorageTypes(p, targets[i].length);
1112          }
1113        }
1114    
1115        List<StorageUuidsProto> targetStorageUuidsList = blkCmd.getTargetStorageUuidsList();
1116        String[][] targetStorageIDs = new String[targetStorageUuidsList.size()][];
1117        for(int i = 0; i < targetStorageIDs.length; i++) {
1118          List<String> storageIDs = targetStorageUuidsList.get(i).getStorageUuidsList();
1119          targetStorageIDs[i] = storageIDs.toArray(new String[storageIDs.size()]);
1120        }
1121    
1122        int action = DatanodeProtocol.DNA_UNKNOWN;
1123        switch (blkCmd.getAction()) {
1124        case TRANSFER:
1125          action = DatanodeProtocol.DNA_TRANSFER;
1126          break;
1127        case INVALIDATE:
1128          action = DatanodeProtocol.DNA_INVALIDATE;
1129          break;
1130        case SHUTDOWN:
1131          action = DatanodeProtocol.DNA_SHUTDOWN;
1132          break;
1133        default:
1134          throw new AssertionError("Unknown action type: " + blkCmd.getAction());
1135        }
1136        return new BlockCommand(action, blkCmd.getBlockPoolId(), blocks, targets,
1137            targetStorageTypes, targetStorageIDs);
1138      }
1139    
1140      public static BlockIdCommand convert(BlockIdCommandProto blkIdCmd) {
1141        int numBlockIds = blkIdCmd.getBlockIdsCount();
1142        long blockIds[] = new long[numBlockIds];
1143        for (int i = 0; i < numBlockIds; i++) {
1144          blockIds[i] = blkIdCmd.getBlockIds(i);
1145        }
1146        int action = DatanodeProtocol.DNA_UNKNOWN;
1147        switch (blkIdCmd.getAction()) {
1148        case CACHE:
1149          action = DatanodeProtocol.DNA_CACHE;
1150          break;
1151        case UNCACHE:
1152          action = DatanodeProtocol.DNA_UNCACHE;
1153          break;
1154        default:
1155          throw new AssertionError("Unknown action type: " + blkIdCmd.getAction());
1156        }
1157        return new BlockIdCommand(action, blkIdCmd.getBlockPoolId(), blockIds);
1158      }
1159    
1160      public static DatanodeInfo[] convert(DatanodeInfosProto datanodeInfosProto) {
1161        List<DatanodeInfoProto> proto = datanodeInfosProto.getDatanodesList();
1162        DatanodeInfo[] infos = new DatanodeInfo[proto.size()];
1163        for (int i = 0; i < infos.length; i++) {
1164          infos[i] = PBHelper.convert(proto.get(i));
1165        }
1166        return infos;
1167      }
1168    
1169      public static BalancerBandwidthCommand convert(
1170          BalancerBandwidthCommandProto balancerCmd) {
1171        return new BalancerBandwidthCommand(balancerCmd.getBandwidth());
1172      }
1173    
1174      public static ReceivedDeletedBlockInfoProto convert(
1175          ReceivedDeletedBlockInfo receivedDeletedBlockInfo) {
1176        ReceivedDeletedBlockInfoProto.Builder builder = 
1177            ReceivedDeletedBlockInfoProto.newBuilder();
1178        
1179        ReceivedDeletedBlockInfoProto.BlockStatus status;
1180        switch (receivedDeletedBlockInfo.getStatus()) {
1181        case RECEIVING_BLOCK:
1182          status = ReceivedDeletedBlockInfoProto.BlockStatus.RECEIVING;
1183          break;
1184        case RECEIVED_BLOCK:
1185          status = ReceivedDeletedBlockInfoProto.BlockStatus.RECEIVED;
1186          break;
1187        case DELETED_BLOCK:
1188          status = ReceivedDeletedBlockInfoProto.BlockStatus.DELETED;
1189          break;
1190        default:
1191          throw new IllegalArgumentException("Bad status: " +
1192              receivedDeletedBlockInfo.getStatus());
1193        }
1194        builder.setStatus(status);
1195        
1196        if (receivedDeletedBlockInfo.getDelHints() != null) {
1197          builder.setDeleteHint(receivedDeletedBlockInfo.getDelHints());
1198        }
1199        return builder.setBlock(PBHelper.convert(receivedDeletedBlockInfo.getBlock()))
1200            .build();
1201      }
1202    
1203      public static ReceivedDeletedBlockInfo convert(
1204          ReceivedDeletedBlockInfoProto proto) {
1205        ReceivedDeletedBlockInfo.BlockStatus status = null;
1206        switch (proto.getStatus()) {
1207        case RECEIVING:
1208          status = BlockStatus.RECEIVING_BLOCK;
1209          break;
1210        case RECEIVED:
1211          status = BlockStatus.RECEIVED_BLOCK;
1212          break;
1213        case DELETED:
1214          status = BlockStatus.DELETED_BLOCK;
1215          break;
1216        }
1217        return new ReceivedDeletedBlockInfo(
1218            PBHelper.convert(proto.getBlock()),
1219            status,
1220            proto.hasDeleteHint() ? proto.getDeleteHint() : null);
1221      }
1222      
1223      public static NamespaceInfoProto convert(NamespaceInfo info) {
1224        return NamespaceInfoProto.newBuilder()
1225            .setBlockPoolID(info.getBlockPoolID())
1226            .setBuildVersion(info.getBuildVersion())
1227            .setUnused(0)
1228            .setStorageInfo(PBHelper.convert((StorageInfo)info))
1229            .setSoftwareVersion(info.getSoftwareVersion()).build();
1230      }
1231      
1232      // Located Block Arrays and Lists
1233      public static LocatedBlockProto[] convertLocatedBlock(LocatedBlock[] lb) {
1234        if (lb == null) return null;
1235        return convertLocatedBlock2(Arrays.asList(lb)).toArray(
1236            new LocatedBlockProto[lb.length]);
1237      }
1238      
1239      public static LocatedBlock[] convertLocatedBlock(LocatedBlockProto[] lb) {
1240        if (lb == null) return null;
1241        return convertLocatedBlock(Arrays.asList(lb)).toArray(
1242            new LocatedBlock[lb.length]);
1243      }
1244      
1245      public static List<LocatedBlock> convertLocatedBlock(
1246          List<LocatedBlockProto> lb) {
1247        if (lb == null) return null;
1248        final int len = lb.size();
1249        List<LocatedBlock> result = 
1250            new ArrayList<LocatedBlock>(len);
1251        for (int i = 0; i < len; ++i) {
1252          result.add(PBHelper.convert(lb.get(i)));
1253        }
1254        return result;
1255      }
1256      
1257      public static List<LocatedBlockProto> convertLocatedBlock2(List<LocatedBlock> lb) {
1258        if (lb == null) return null;
1259        final int len = lb.size();
1260        List<LocatedBlockProto> result = new ArrayList<LocatedBlockProto>(len);
1261        for (int i = 0; i < len; ++i) {
1262          result.add(PBHelper.convert(lb.get(i)));
1263        }
1264        return result;
1265      }
1266      
1267      
1268      // LocatedBlocks
1269      public static LocatedBlocks convert(LocatedBlocksProto lb) {
1270        return new LocatedBlocks(
1271            lb.getFileLength(), lb.getUnderConstruction(),
1272            PBHelper.convertLocatedBlock(lb.getBlocksList()),
1273            lb.hasLastBlock() ? PBHelper.convert(lb.getLastBlock()) : null,
1274            lb.getIsLastBlockComplete(),
1275            lb.hasFileEncryptionInfo() ? convert(lb.getFileEncryptionInfo()) :
1276                null);
1277      }
1278      
1279      public static LocatedBlocksProto convert(LocatedBlocks lb) {
1280        if (lb == null) {
1281          return null;
1282        }
1283        LocatedBlocksProto.Builder builder = 
1284            LocatedBlocksProto.newBuilder();
1285        if (lb.getLastLocatedBlock() != null) {
1286          builder.setLastBlock(PBHelper.convert(lb.getLastLocatedBlock()));
1287        }
1288        if (lb.getFileEncryptionInfo() != null) {
1289          builder.setFileEncryptionInfo(convert(lb.getFileEncryptionInfo()));
1290        }
1291        return builder.setFileLength(lb.getFileLength())
1292            .setUnderConstruction(lb.isUnderConstruction())
1293            .addAllBlocks(PBHelper.convertLocatedBlock2(lb.getLocatedBlocks()))
1294            .setIsLastBlockComplete(lb.isLastBlockComplete()).build();
1295      }
1296      
1297      // DataEncryptionKey
1298      public static DataEncryptionKey convert(DataEncryptionKeyProto bet) {
1299        String encryptionAlgorithm = bet.getEncryptionAlgorithm();
1300        return new DataEncryptionKey(bet.getKeyId(),
1301            bet.getBlockPoolId(),
1302            bet.getNonce().toByteArray(),
1303            bet.getEncryptionKey().toByteArray(),
1304            bet.getExpiryDate(),
1305            encryptionAlgorithm.isEmpty() ? null : encryptionAlgorithm);
1306      }
1307      
1308      public static DataEncryptionKeyProto convert(DataEncryptionKey bet) {
1309        DataEncryptionKeyProto.Builder b = DataEncryptionKeyProto.newBuilder()
1310            .setKeyId(bet.keyId)
1311            .setBlockPoolId(bet.blockPoolId)
1312            .setNonce(ByteString.copyFrom(bet.nonce))
1313            .setEncryptionKey(ByteString.copyFrom(bet.encryptionKey))
1314            .setExpiryDate(bet.expiryDate);
1315        if (bet.encryptionAlgorithm != null) {
1316          b.setEncryptionAlgorithm(bet.encryptionAlgorithm);
1317        }
1318        return b.build();
1319      }
1320      
1321      public static FsServerDefaults convert(FsServerDefaultsProto fs) {
1322        if (fs == null) return null;
1323        return new FsServerDefaults(
1324            fs.getBlockSize(), fs.getBytesPerChecksum(), 
1325            fs.getWritePacketSize(), (short) fs.getReplication(),
1326            fs.getFileBufferSize(),
1327            fs.getEncryptDataTransfer(),
1328            fs.getTrashInterval(),
1329            PBHelper.convert(fs.getChecksumType()));
1330      }
1331      
1332      public static FsServerDefaultsProto convert(FsServerDefaults fs) {
1333        if (fs == null) return null;
1334        return FsServerDefaultsProto.newBuilder().
1335          setBlockSize(fs.getBlockSize()).
1336          setBytesPerChecksum(fs.getBytesPerChecksum()).
1337          setWritePacketSize(fs.getWritePacketSize())
1338          .setReplication(fs.getReplication())
1339          .setFileBufferSize(fs.getFileBufferSize())
1340          .setEncryptDataTransfer(fs.getEncryptDataTransfer())
1341          .setTrashInterval(fs.getTrashInterval())
1342          .setChecksumType(PBHelper.convert(fs.getChecksumType()))
1343          .build();
1344      }
1345      
1346      public static FsPermissionProto convert(FsPermission p) {
1347        return FsPermissionProto.newBuilder().setPerm(p.toExtendedShort()).build();
1348      }
1349      
1350      public static FsPermission convert(FsPermissionProto p) {
1351        return new FsPermissionExtension((short)p.getPerm());
1352      }
1353      
1354      
1355      // The creatFlag field in PB is a bitmask whose values are the same a the 
1356      // emum values of CreateFlag
1357      public static int convertCreateFlag(EnumSetWritable<CreateFlag> flag) {
1358        int value = 0;
1359        if (flag.contains(CreateFlag.APPEND)) {
1360          value |= CreateFlagProto.APPEND.getNumber();
1361        }
1362        if (flag.contains(CreateFlag.CREATE)) {
1363          value |= CreateFlagProto.CREATE.getNumber();
1364        }
1365        if (flag.contains(CreateFlag.OVERWRITE)) {
1366          value |= CreateFlagProto.OVERWRITE.getNumber();
1367        }
1368        if (flag.contains(CreateFlag.LAZY_PERSIST)) {
1369          value |= CreateFlagProto.LAZY_PERSIST.getNumber();
1370        }
1371        return value;
1372      }
1373      
1374      public static EnumSetWritable<CreateFlag> convertCreateFlag(int flag) {
1375        EnumSet<CreateFlag> result = 
1376           EnumSet.noneOf(CreateFlag.class);   
1377        if ((flag & CreateFlagProto.APPEND_VALUE) == CreateFlagProto.APPEND_VALUE) {
1378          result.add(CreateFlag.APPEND);
1379        }
1380        if ((flag & CreateFlagProto.CREATE_VALUE) == CreateFlagProto.CREATE_VALUE) {
1381          result.add(CreateFlag.CREATE);
1382        }
1383        if ((flag & CreateFlagProto.OVERWRITE_VALUE) 
1384            == CreateFlagProto.OVERWRITE_VALUE) {
1385          result.add(CreateFlag.OVERWRITE);
1386        }
1387        if ((flag & CreateFlagProto.LAZY_PERSIST_VALUE)
1388            == CreateFlagProto.LAZY_PERSIST_VALUE) {
1389          result.add(CreateFlag.LAZY_PERSIST);
1390        }
1391        return new EnumSetWritable<CreateFlag>(result);
1392      }
1393    
1394      public static int convertCacheFlags(EnumSet<CacheFlag> flags) {
1395        int value = 0;
1396        if (flags.contains(CacheFlag.FORCE)) {
1397          value |= CacheFlagProto.FORCE.getNumber();
1398        }
1399        return value;
1400      }
1401    
1402      public static EnumSet<CacheFlag> convertCacheFlags(int flags) {
1403        EnumSet<CacheFlag> result = EnumSet.noneOf(CacheFlag.class);
1404        if ((flags & CacheFlagProto.FORCE_VALUE) == CacheFlagProto.FORCE_VALUE) {
1405          result.add(CacheFlag.FORCE);
1406        }
1407        return result;
1408      }
1409    
1410      public static HdfsFileStatus convert(HdfsFileStatusProto fs) {
1411        if (fs == null)
1412          return null;
1413        return new HdfsLocatedFileStatus(
1414            fs.getLength(), fs.getFileType().equals(FileType.IS_DIR), 
1415            fs.getBlockReplication(), fs.getBlocksize(),
1416            fs.getModificationTime(), fs.getAccessTime(),
1417            PBHelper.convert(fs.getPermission()), fs.getOwner(), fs.getGroup(), 
1418            fs.getFileType().equals(FileType.IS_SYMLINK) ? 
1419                fs.getSymlink().toByteArray() : null,
1420            fs.getPath().toByteArray(),
1421            fs.hasFileId()? fs.getFileId(): INodeId.GRANDFATHER_INODE_ID,
1422            fs.hasLocations() ? PBHelper.convert(fs.getLocations()) : null,
1423            fs.hasChildrenNum() ? fs.getChildrenNum() : -1,
1424            fs.hasFileEncryptionInfo() ? convert(fs.getFileEncryptionInfo()) : null,
1425            fs.hasStoragePolicy() ? (byte) fs.getStoragePolicy()
1426                : BlockStoragePolicySuite.ID_UNSPECIFIED);
1427      }
1428    
1429      public static SnapshottableDirectoryStatus convert(
1430          SnapshottableDirectoryStatusProto sdirStatusProto) {
1431        if (sdirStatusProto == null) {
1432          return null;
1433        }
1434        final HdfsFileStatusProto status = sdirStatusProto.getDirStatus();
1435        return new SnapshottableDirectoryStatus(
1436            status.getModificationTime(),
1437            status.getAccessTime(),
1438            PBHelper.convert(status.getPermission()),
1439            status.getOwner(),
1440            status.getGroup(),
1441            status.getPath().toByteArray(),
1442            status.getFileId(),
1443            status.getChildrenNum(),
1444            sdirStatusProto.getSnapshotNumber(),
1445            sdirStatusProto.getSnapshotQuota(),
1446            sdirStatusProto.getParentFullpath().toByteArray());
1447      }
1448      
1449      public static HdfsFileStatusProto convert(HdfsFileStatus fs) {
1450        if (fs == null)
1451          return null;
1452        FileType fType = FileType.IS_FILE;
1453        if (fs.isDir()) {
1454          fType = FileType.IS_DIR;
1455        } else if (fs.isSymlink()) {
1456          fType = FileType.IS_SYMLINK;
1457        }
1458    
1459        HdfsFileStatusProto.Builder builder = 
1460         HdfsFileStatusProto.newBuilder().
1461          setLength(fs.getLen()).
1462          setFileType(fType).
1463          setBlockReplication(fs.getReplication()).
1464          setBlocksize(fs.getBlockSize()).
1465          setModificationTime(fs.getModificationTime()).
1466          setAccessTime(fs.getAccessTime()).
1467          setPermission(PBHelper.convert(fs.getPermission())).
1468          setOwner(fs.getOwner()).
1469          setGroup(fs.getGroup()).
1470          setFileId(fs.getFileId()).
1471          setChildrenNum(fs.getChildrenNum()).
1472          setPath(ByteString.copyFrom(fs.getLocalNameInBytes())).
1473          setStoragePolicy(fs.getStoragePolicy());
1474        if (fs.isSymlink())  {
1475          builder.setSymlink(ByteString.copyFrom(fs.getSymlinkInBytes()));
1476        }
1477        if (fs.getFileEncryptionInfo() != null) {
1478          builder.setFileEncryptionInfo(convert(fs.getFileEncryptionInfo()));
1479        }
1480        if (fs instanceof HdfsLocatedFileStatus) {
1481          final HdfsLocatedFileStatus lfs = (HdfsLocatedFileStatus) fs;
1482          LocatedBlocks locations = lfs.getBlockLocations();
1483          if (locations != null) {
1484            builder.setLocations(PBHelper.convert(locations));
1485          }
1486        }
1487        return builder.build();
1488      }
1489      
1490      public static SnapshottableDirectoryStatusProto convert(
1491          SnapshottableDirectoryStatus status) {
1492        if (status == null) {
1493          return null;
1494        }
1495        int snapshotNumber = status.getSnapshotNumber();
1496        int snapshotQuota = status.getSnapshotQuota();
1497        byte[] parentFullPath = status.getParentFullPath();
1498        ByteString parentFullPathBytes = ByteString.copyFrom(
1499            parentFullPath == null ? DFSUtil.EMPTY_BYTES : parentFullPath);
1500        HdfsFileStatusProto fs = convert(status.getDirStatus());
1501        SnapshottableDirectoryStatusProto.Builder builder = 
1502            SnapshottableDirectoryStatusProto
1503            .newBuilder().setSnapshotNumber(snapshotNumber)
1504            .setSnapshotQuota(snapshotQuota).setParentFullpath(parentFullPathBytes)
1505            .setDirStatus(fs);
1506        return builder.build();
1507      }
1508      
1509      public static HdfsFileStatusProto[] convert(HdfsFileStatus[] fs) {
1510        if (fs == null) return null;
1511        final int len = fs.length;
1512        HdfsFileStatusProto[] result = new HdfsFileStatusProto[len];
1513        for (int i = 0; i < len; ++i) {
1514          result[i] = PBHelper.convert(fs[i]);
1515        }
1516        return result;
1517      }
1518      
1519      public static HdfsFileStatus[] convert(HdfsFileStatusProto[] fs) {
1520        if (fs == null) return null;
1521        final int len = fs.length;
1522        HdfsFileStatus[] result = new HdfsFileStatus[len];
1523        for (int i = 0; i < len; ++i) {
1524          result[i] = PBHelper.convert(fs[i]);
1525        }
1526        return result;
1527      }
1528      
1529      public static DirectoryListing convert(DirectoryListingProto dl) {
1530        if (dl == null)
1531          return null;
1532        List<HdfsFileStatusProto> partList =  dl.getPartialListingList();
1533        return new DirectoryListing( 
1534            partList.isEmpty() ? new HdfsLocatedFileStatus[0] 
1535              : PBHelper.convert(
1536                  partList.toArray(new HdfsFileStatusProto[partList.size()])),
1537            dl.getRemainingEntries());
1538      }
1539    
1540      public static DirectoryListingProto convert(DirectoryListing d) {
1541        if (d == null)
1542          return null;
1543        return DirectoryListingProto.newBuilder().
1544            addAllPartialListing(Arrays.asList(
1545                PBHelper.convert(d.getPartialListing()))).
1546            setRemainingEntries(d.getRemainingEntries()).
1547            build();
1548      }
1549    
1550      public static long[] convert(GetFsStatsResponseProto res) {
1551        long[] result = new long[6];
1552        result[ClientProtocol.GET_STATS_CAPACITY_IDX] = res.getCapacity();
1553        result[ClientProtocol.GET_STATS_USED_IDX] = res.getUsed();
1554        result[ClientProtocol.GET_STATS_REMAINING_IDX] = res.getRemaining();
1555        result[ClientProtocol.GET_STATS_UNDER_REPLICATED_IDX] = res.getUnderReplicated();
1556        result[ClientProtocol.GET_STATS_CORRUPT_BLOCKS_IDX] = res.getCorruptBlocks();
1557        result[ClientProtocol.GET_STATS_MISSING_BLOCKS_IDX] = res.getMissingBlocks();
1558        return result;
1559      }
1560      
1561      public static GetFsStatsResponseProto convert(long[] fsStats) {
1562        GetFsStatsResponseProto.Builder result = GetFsStatsResponseProto
1563            .newBuilder();
1564        if (fsStats.length >= ClientProtocol.GET_STATS_CAPACITY_IDX + 1)
1565          result.setCapacity(fsStats[ClientProtocol.GET_STATS_CAPACITY_IDX]);
1566        if (fsStats.length >= ClientProtocol.GET_STATS_USED_IDX + 1)
1567          result.setUsed(fsStats[ClientProtocol.GET_STATS_USED_IDX]);
1568        if (fsStats.length >= ClientProtocol.GET_STATS_REMAINING_IDX + 1)
1569          result.setRemaining(fsStats[ClientProtocol.GET_STATS_REMAINING_IDX]);
1570        if (fsStats.length >= ClientProtocol.GET_STATS_UNDER_REPLICATED_IDX + 1)
1571          result.setUnderReplicated(
1572                  fsStats[ClientProtocol.GET_STATS_UNDER_REPLICATED_IDX]);
1573        if (fsStats.length >= ClientProtocol.GET_STATS_CORRUPT_BLOCKS_IDX + 1)
1574          result.setCorruptBlocks(
1575              fsStats[ClientProtocol.GET_STATS_CORRUPT_BLOCKS_IDX]);
1576        if (fsStats.length >= ClientProtocol.GET_STATS_MISSING_BLOCKS_IDX + 1)
1577          result.setMissingBlocks(
1578              fsStats[ClientProtocol.GET_STATS_MISSING_BLOCKS_IDX]);
1579        return result.build();
1580      }
1581      
1582      public static DatanodeReportTypeProto
1583        convert(DatanodeReportType t) {
1584        switch (t) {
1585        case ALL: return DatanodeReportTypeProto.ALL;
1586        case LIVE: return DatanodeReportTypeProto.LIVE;
1587        case DEAD: return DatanodeReportTypeProto.DEAD;
1588        case DECOMMISSIONING: return DatanodeReportTypeProto.DECOMMISSIONING;
1589        default: 
1590          throw new IllegalArgumentException("Unexpected data type report:" + t);
1591        }
1592      }
1593      
1594      public static DatanodeReportType 
1595        convert(DatanodeReportTypeProto t) {
1596        switch (t) {
1597        case ALL: return DatanodeReportType.ALL;
1598        case LIVE: return DatanodeReportType.LIVE;
1599        case DEAD: return DatanodeReportType.DEAD;
1600        case DECOMMISSIONING: return DatanodeReportType.DECOMMISSIONING;
1601        default: 
1602          throw new IllegalArgumentException("Unexpected data type report:" + t);
1603        }
1604      }
1605    
1606      public static SafeModeActionProto convert(
1607          SafeModeAction a) {
1608        switch (a) {
1609        case SAFEMODE_LEAVE:
1610          return SafeModeActionProto.SAFEMODE_LEAVE;
1611        case SAFEMODE_ENTER:
1612          return SafeModeActionProto.SAFEMODE_ENTER;
1613        case SAFEMODE_GET:
1614          return SafeModeActionProto.SAFEMODE_GET;
1615        default:
1616          throw new IllegalArgumentException("Unexpected SafeModeAction :" + a);
1617        }
1618      }
1619      
1620      public static SafeModeAction convert(
1621          ClientNamenodeProtocolProtos.SafeModeActionProto a) {
1622        switch (a) {
1623        case SAFEMODE_LEAVE:
1624          return SafeModeAction.SAFEMODE_LEAVE;
1625        case SAFEMODE_ENTER:
1626          return SafeModeAction.SAFEMODE_ENTER;
1627        case SAFEMODE_GET:
1628          return SafeModeAction.SAFEMODE_GET;
1629        default:
1630          throw new IllegalArgumentException("Unexpected SafeModeAction :" + a);
1631        }
1632      }
1633      
1634      public static RollingUpgradeActionProto convert(RollingUpgradeAction a) {
1635        switch (a) {
1636        case QUERY:
1637          return RollingUpgradeActionProto.QUERY;
1638        case PREPARE:
1639          return RollingUpgradeActionProto.START;
1640        case FINALIZE:
1641          return RollingUpgradeActionProto.FINALIZE;
1642        default:
1643          throw new IllegalArgumentException("Unexpected value: " + a);
1644        }
1645      }
1646      
1647      public static RollingUpgradeAction convert(RollingUpgradeActionProto a) {
1648        switch (a) {
1649        case QUERY:
1650          return RollingUpgradeAction.QUERY;
1651        case START:
1652          return RollingUpgradeAction.PREPARE;
1653        case FINALIZE:
1654          return RollingUpgradeAction.FINALIZE;
1655        default:
1656          throw new IllegalArgumentException("Unexpected value: " + a);
1657        }
1658      }
1659    
1660      public static RollingUpgradeStatusProto convertRollingUpgradeStatus(
1661          RollingUpgradeStatus status) {
1662        return RollingUpgradeStatusProto.newBuilder()
1663            .setBlockPoolId(status.getBlockPoolId())
1664            .build();
1665      }
1666    
1667      public static RollingUpgradeStatus convert(RollingUpgradeStatusProto proto) {
1668        return new RollingUpgradeStatus(proto.getBlockPoolId());
1669      }
1670    
1671      public static RollingUpgradeInfoProto convert(RollingUpgradeInfo info) {
1672        return RollingUpgradeInfoProto.newBuilder()
1673            .setStatus(convertRollingUpgradeStatus(info))
1674            .setCreatedRollbackImages(info.createdRollbackImages())
1675            .setStartTime(info.getStartTime())
1676            .setFinalizeTime(info.getFinalizeTime())
1677            .build();
1678      }
1679    
1680      public static RollingUpgradeInfo convert(RollingUpgradeInfoProto proto) {
1681        RollingUpgradeStatusProto status = proto.getStatus();
1682        return new RollingUpgradeInfo(status.getBlockPoolId(),
1683            proto.getCreatedRollbackImages(),
1684            proto.getStartTime(), proto.getFinalizeTime());
1685      }
1686    
1687      public static CorruptFileBlocks convert(CorruptFileBlocksProto c) {
1688        if (c == null)
1689          return null;
1690        List<String> fileList = c.getFilesList();
1691        return new CorruptFileBlocks(fileList.toArray(new String[fileList.size()]),
1692            c.getCookie());
1693      }
1694    
1695      public static CorruptFileBlocksProto convert(CorruptFileBlocks c) {
1696        if (c == null)
1697          return null;
1698        return CorruptFileBlocksProto.newBuilder().
1699            addAllFiles(Arrays.asList(c.getFiles())).
1700            setCookie(c.getCookie()).
1701            build();
1702      }
1703      
1704      public static ContentSummary convert(ContentSummaryProto cs) {
1705        if (cs == null) return null;
1706        return new ContentSummary(
1707          cs.getLength(), cs.getFileCount(), cs.getDirectoryCount(), cs.getQuota(),
1708          cs.getSpaceConsumed(), cs.getSpaceQuota());
1709      }
1710      
1711      public static ContentSummaryProto convert(ContentSummary cs) {
1712        if (cs == null) return null;
1713        return ContentSummaryProto.newBuilder().
1714            setLength(cs.getLength()).
1715            setFileCount(cs.getFileCount()).
1716            setDirectoryCount(cs.getDirectoryCount()).
1717            setQuota(cs.getQuota()).
1718            setSpaceConsumed(cs.getSpaceConsumed()).
1719            setSpaceQuota(cs.getSpaceQuota()).
1720            build();
1721      }
1722    
1723      public static NNHAStatusHeartbeat convert(NNHAStatusHeartbeatProto s) {
1724        if (s == null) return null;
1725        switch (s.getState()) {
1726        case ACTIVE:
1727          return new NNHAStatusHeartbeat(HAServiceState.ACTIVE, s.getTxid());
1728        case STANDBY:
1729          return new NNHAStatusHeartbeat(HAServiceState.STANDBY, s.getTxid());
1730        default:
1731          throw new IllegalArgumentException("Unexpected NNHAStatusHeartbeat.State:" + s.getState());
1732        }
1733      }
1734    
1735      public static NNHAStatusHeartbeatProto convert(NNHAStatusHeartbeat hb) {
1736        if (hb == null) return null;
1737        NNHAStatusHeartbeatProto.Builder builder =
1738          NNHAStatusHeartbeatProto.newBuilder();
1739        switch (hb.getState()) {
1740          case ACTIVE:
1741            builder.setState(NNHAStatusHeartbeatProto.State.ACTIVE);
1742            break;
1743          case STANDBY:
1744            builder.setState(NNHAStatusHeartbeatProto.State.STANDBY);
1745            break;
1746          default:
1747            throw new IllegalArgumentException("Unexpected NNHAStatusHeartbeat.State:" +
1748                hb.getState());
1749        }
1750        builder.setTxid(hb.getTxId());
1751        return builder.build();
1752      }
1753    
1754      public static DatanodeStorageProto convert(DatanodeStorage s) {
1755        return DatanodeStorageProto.newBuilder()
1756            .setState(PBHelper.convertState(s.getState()))
1757            .setStorageType(PBHelper.convertStorageType(s.getStorageType()))
1758            .setStorageUuid(s.getStorageID()).build();
1759      }
1760    
1761      private static StorageState convertState(State state) {
1762        switch(state) {
1763        case READ_ONLY_SHARED:
1764          return StorageState.READ_ONLY_SHARED;
1765        case NORMAL:
1766        default:
1767          return StorageState.NORMAL;
1768        }
1769      }
1770    
1771      public static List<StorageTypeProto> convertStorageTypes(
1772          StorageType[] types) {
1773        return convertStorageTypes(types, 0);
1774      }
1775    
1776      public static List<StorageTypeProto> convertStorageTypes(
1777          StorageType[] types, int startIdx) {
1778        if (types == null) {
1779          return null;
1780        }
1781        final List<StorageTypeProto> protos = new ArrayList<StorageTypeProto>(
1782            types.length);
1783        for (int i = startIdx; i < types.length; ++i) {
1784          protos.add(convertStorageType(types[i]));
1785        }
1786        return protos; 
1787      }
1788    
1789      public static StorageTypeProto convertStorageType(StorageType type) {
1790        switch(type) {
1791        case DISK:
1792          return StorageTypeProto.DISK;
1793        case SSD:
1794          return StorageTypeProto.SSD;
1795        case ARCHIVE:
1796          return StorageTypeProto.ARCHIVE;
1797        case RAM_DISK:
1798          return StorageTypeProto.RAM_DISK;
1799        default:
1800          throw new IllegalStateException(
1801              "BUG: StorageType not found, type=" + type);
1802        }
1803      }
1804    
1805      public static DatanodeStorage convert(DatanodeStorageProto s) {
1806        return new DatanodeStorage(s.getStorageUuid(),
1807                                   PBHelper.convertState(s.getState()),
1808                                   PBHelper.convertStorageType(s.getStorageType()));
1809      }
1810    
1811      private static State convertState(StorageState state) {
1812        switch(state) {
1813        case READ_ONLY_SHARED:
1814          return DatanodeStorage.State.READ_ONLY_SHARED;
1815        case NORMAL:
1816        default:
1817          return DatanodeStorage.State.NORMAL;
1818        }
1819      }
1820    
1821      public static StorageType convertStorageType(StorageTypeProto type) {
1822        switch(type) {
1823          case DISK:
1824            return StorageType.DISK;
1825          case SSD:
1826            return StorageType.SSD;
1827          case ARCHIVE:
1828            return StorageType.ARCHIVE;
1829          case RAM_DISK:
1830            return StorageType.RAM_DISK;
1831          default:
1832            throw new IllegalStateException(
1833                "BUG: StorageTypeProto not found, type=" + type);
1834        }
1835      }
1836    
1837      public static StorageType[] convertStorageTypes(
1838          List<StorageTypeProto> storageTypesList, int expectedSize) {
1839        final StorageType[] storageTypes = new StorageType[expectedSize];
1840        if (storageTypesList.size() != expectedSize) { // missing storage types
1841          Preconditions.checkState(storageTypesList.isEmpty());
1842          Arrays.fill(storageTypes, StorageType.DEFAULT);
1843        } else {
1844          for (int i = 0; i < storageTypes.length; ++i) {
1845            storageTypes[i] = convertStorageType(storageTypesList.get(i));
1846          }
1847        }
1848        return storageTypes;
1849      }
1850    
1851      public static StorageReportProto convert(StorageReport r) {
1852        StorageReportProto.Builder builder = StorageReportProto.newBuilder()
1853            .setBlockPoolUsed(r.getBlockPoolUsed()).setCapacity(r.getCapacity())
1854            .setDfsUsed(r.getDfsUsed()).setRemaining(r.getRemaining())
1855            .setStorageUuid(r.getStorage().getStorageID())
1856            .setStorage(convert(r.getStorage()));
1857        return builder.build();
1858      }
1859    
1860      public static StorageReport convert(StorageReportProto p) {
1861        return new StorageReport(
1862            p.hasStorage() ?
1863                convert(p.getStorage()) :
1864                new DatanodeStorage(p.getStorageUuid()),
1865            p.getFailed(), p.getCapacity(), p.getDfsUsed(), p.getRemaining(),
1866            p.getBlockPoolUsed());
1867      }
1868    
1869      public static StorageReport[] convertStorageReports(
1870          List<StorageReportProto> list) {
1871        final StorageReport[] report = new StorageReport[list.size()];
1872        for (int i = 0; i < report.length; i++) {
1873          report[i] = convert(list.get(i));
1874        }
1875        return report;
1876      }
1877    
1878      public static List<StorageReportProto> convertStorageReports(StorageReport[] storages) {
1879        final List<StorageReportProto> protos = new ArrayList<StorageReportProto>(
1880            storages.length);
1881        for(int i = 0; i < storages.length; i++) {
1882          protos.add(convert(storages[i]));
1883        }
1884        return protos;
1885      }
1886    
1887      public static JournalInfo convert(JournalInfoProto info) {
1888        int lv = info.hasLayoutVersion() ? info.getLayoutVersion() : 0;
1889        int nsID = info.hasNamespaceID() ? info.getNamespaceID() : 0;
1890        return new JournalInfo(lv, info.getClusterID(), nsID);
1891      }
1892    
1893      /**
1894       * Method used for converting {@link JournalInfoProto} sent from Namenode
1895       * to Journal receivers to {@link NamenodeRegistration}.
1896       */
1897      public static JournalInfoProto convert(JournalInfo j) {
1898        return JournalInfoProto.newBuilder().setClusterID(j.getClusterId())
1899            .setLayoutVersion(j.getLayoutVersion())
1900            .setNamespaceID(j.getNamespaceId()).build();
1901      } 
1902      
1903      public static SnapshottableDirectoryStatus[] convert(
1904          SnapshottableDirectoryListingProto sdlp) {
1905        if (sdlp == null)
1906          return null;
1907        List<SnapshottableDirectoryStatusProto> list = sdlp
1908            .getSnapshottableDirListingList();
1909        if (list.isEmpty()) {
1910          return new SnapshottableDirectoryStatus[0];
1911        } else {
1912          SnapshottableDirectoryStatus[] result = 
1913              new SnapshottableDirectoryStatus[list.size()];
1914          for (int i = 0; i < list.size(); i++) {
1915            result[i] = PBHelper.convert(list.get(i));
1916          }
1917          return result;
1918        }
1919      }
1920      
1921      public static SnapshottableDirectoryListingProto convert(
1922          SnapshottableDirectoryStatus[] status) {
1923        if (status == null)
1924          return null;
1925        SnapshottableDirectoryStatusProto[] protos = 
1926            new SnapshottableDirectoryStatusProto[status.length];
1927        for (int i = 0; i < status.length; i++) {
1928          protos[i] = PBHelper.convert(status[i]);
1929        }
1930        List<SnapshottableDirectoryStatusProto> protoList = Arrays.asList(protos);
1931        return SnapshottableDirectoryListingProto.newBuilder()
1932            .addAllSnapshottableDirListing(protoList).build();
1933      }
1934      
1935      public static DiffReportEntry convert(SnapshotDiffReportEntryProto entry) {
1936        if (entry == null) {
1937          return null;
1938        }
1939        DiffType type = DiffType.getTypeFromLabel(entry
1940            .getModificationLabel());
1941        return type == null ? null : new DiffReportEntry(type, entry.getFullpath()
1942            .toByteArray(), entry.hasTargetPath() ? entry.getTargetPath()
1943            .toByteArray() : null);
1944      }
1945      
1946      public static SnapshotDiffReportEntryProto convert(DiffReportEntry entry) {
1947        if (entry == null) {
1948          return null;
1949        }
1950        ByteString sourcePath = ByteString
1951            .copyFrom(entry.getSourcePath() == null ? DFSUtil.EMPTY_BYTES : entry
1952                .getSourcePath());
1953        String modification = entry.getType().getLabel();
1954        SnapshotDiffReportEntryProto.Builder builder = SnapshotDiffReportEntryProto
1955            .newBuilder().setFullpath(sourcePath)
1956            .setModificationLabel(modification);
1957        if (entry.getType() == DiffType.RENAME) {
1958          ByteString targetPath = ByteString
1959              .copyFrom(entry.getTargetPath() == null ? DFSUtil.EMPTY_BYTES : entry
1960                  .getTargetPath());
1961          builder.setTargetPath(targetPath);
1962        }
1963        return builder.build();
1964      }
1965      
1966      public static SnapshotDiffReport convert(SnapshotDiffReportProto reportProto) {
1967        if (reportProto == null) {
1968          return null;
1969        }
1970        String snapshotDir = reportProto.getSnapshotRoot();
1971        String fromSnapshot = reportProto.getFromSnapshot();
1972        String toSnapshot = reportProto.getToSnapshot();
1973        List<SnapshotDiffReportEntryProto> list = reportProto
1974            .getDiffReportEntriesList();
1975        List<DiffReportEntry> entries = new ArrayList<DiffReportEntry>();
1976        for (SnapshotDiffReportEntryProto entryProto : list) {
1977          DiffReportEntry entry = convert(entryProto);
1978          if (entry != null)
1979            entries.add(entry);
1980        }
1981        return new SnapshotDiffReport(snapshotDir, fromSnapshot, toSnapshot,
1982            entries);
1983      }
1984      
1985      public static SnapshotDiffReportProto convert(SnapshotDiffReport report) {
1986        if (report == null) {
1987          return null;
1988        }
1989        List<DiffReportEntry> entries = report.getDiffList();
1990        List<SnapshotDiffReportEntryProto> entryProtos = 
1991            new ArrayList<SnapshotDiffReportEntryProto>();
1992        for (DiffReportEntry entry : entries) {
1993          SnapshotDiffReportEntryProto entryProto = convert(entry);
1994          if (entryProto != null)
1995            entryProtos.add(entryProto);
1996        }
1997        
1998        SnapshotDiffReportProto reportProto = SnapshotDiffReportProto.newBuilder()
1999            .setSnapshotRoot(report.getSnapshotRoot())
2000            .setFromSnapshot(report.getFromSnapshot())
2001            .setToSnapshot(report.getLaterSnapshotName())
2002            .addAllDiffReportEntries(entryProtos).build();
2003        return reportProto;
2004      }
2005    
2006      public static DataChecksum.Type convert(HdfsProtos.ChecksumTypeProto type) {
2007        return DataChecksum.Type.valueOf(type.getNumber());
2008      }
2009    
2010      public static CacheDirectiveInfoProto convert
2011          (CacheDirectiveInfo info) {
2012        CacheDirectiveInfoProto.Builder builder = 
2013            CacheDirectiveInfoProto.newBuilder();
2014        if (info.getId() != null) {
2015          builder.setId(info.getId());
2016        }
2017        if (info.getPath() != null) {
2018          builder.setPath(info.getPath().toUri().getPath());
2019        }
2020        if (info.getReplication() != null) {
2021          builder.setReplication(info.getReplication());
2022        }
2023        if (info.getPool() != null) {
2024          builder.setPool(info.getPool());
2025        }
2026        if (info.getExpiration() != null) {
2027          builder.setExpiration(convert(info.getExpiration()));
2028        }
2029        return builder.build();
2030      }
2031    
2032      public static CacheDirectiveInfo convert
2033          (CacheDirectiveInfoProto proto) {
2034        CacheDirectiveInfo.Builder builder =
2035            new CacheDirectiveInfo.Builder();
2036        if (proto.hasId()) {
2037          builder.setId(proto.getId());
2038        }
2039        if (proto.hasPath()) {
2040          builder.setPath(new Path(proto.getPath()));
2041        }
2042        if (proto.hasReplication()) {
2043          builder.setReplication(Shorts.checkedCast(
2044              proto.getReplication()));
2045        }
2046        if (proto.hasPool()) {
2047          builder.setPool(proto.getPool());
2048        }
2049        if (proto.hasExpiration()) {
2050          builder.setExpiration(convert(proto.getExpiration()));
2051        }
2052        return builder.build();
2053      }
2054    
2055      public static CacheDirectiveInfoExpirationProto convert(
2056          CacheDirectiveInfo.Expiration expiration) {
2057        return CacheDirectiveInfoExpirationProto.newBuilder()
2058            .setIsRelative(expiration.isRelative())
2059            .setMillis(expiration.getMillis())
2060            .build();
2061      }
2062    
2063      public static CacheDirectiveInfo.Expiration convert(
2064          CacheDirectiveInfoExpirationProto proto) {
2065        if (proto.getIsRelative()) {
2066          return CacheDirectiveInfo.Expiration.newRelative(proto.getMillis());
2067        }
2068        return CacheDirectiveInfo.Expiration.newAbsolute(proto.getMillis());
2069      }
2070    
2071      public static CacheDirectiveStatsProto convert(CacheDirectiveStats stats) {
2072        CacheDirectiveStatsProto.Builder builder = 
2073            CacheDirectiveStatsProto.newBuilder();
2074        builder.setBytesNeeded(stats.getBytesNeeded());
2075        builder.setBytesCached(stats.getBytesCached());
2076        builder.setFilesNeeded(stats.getFilesNeeded());
2077        builder.setFilesCached(stats.getFilesCached());
2078        builder.setHasExpired(stats.hasExpired());
2079        return builder.build();
2080      }
2081      
2082      public static CacheDirectiveStats convert(CacheDirectiveStatsProto proto) {
2083        CacheDirectiveStats.Builder builder = new CacheDirectiveStats.Builder();
2084        builder.setBytesNeeded(proto.getBytesNeeded());
2085        builder.setBytesCached(proto.getBytesCached());
2086        builder.setFilesNeeded(proto.getFilesNeeded());
2087        builder.setFilesCached(proto.getFilesCached());
2088        builder.setHasExpired(proto.getHasExpired());
2089        return builder.build();
2090      }
2091    
2092      public static CacheDirectiveEntryProto convert(CacheDirectiveEntry entry) {
2093        CacheDirectiveEntryProto.Builder builder = 
2094            CacheDirectiveEntryProto.newBuilder();
2095        builder.setInfo(PBHelper.convert(entry.getInfo()));
2096        builder.setStats(PBHelper.convert(entry.getStats()));
2097        return builder.build();
2098      }
2099      
2100      public static CacheDirectiveEntry convert(CacheDirectiveEntryProto proto) {
2101        CacheDirectiveInfo info = PBHelper.convert(proto.getInfo());
2102        CacheDirectiveStats stats = PBHelper.convert(proto.getStats());
2103        return new CacheDirectiveEntry(info, stats);
2104      }
2105    
2106      public static CachePoolInfoProto convert(CachePoolInfo info) {
2107        CachePoolInfoProto.Builder builder = CachePoolInfoProto.newBuilder();
2108        builder.setPoolName(info.getPoolName());
2109        if (info.getOwnerName() != null) {
2110          builder.setOwnerName(info.getOwnerName());
2111        }
2112        if (info.getGroupName() != null) {
2113          builder.setGroupName(info.getGroupName());
2114        }
2115        if (info.getMode() != null) {
2116          builder.setMode(info.getMode().toShort());
2117        }
2118        if (info.getLimit() != null) {
2119          builder.setLimit(info.getLimit());
2120        }
2121        if (info.getMaxRelativeExpiryMs() != null) {
2122          builder.setMaxRelativeExpiry(info.getMaxRelativeExpiryMs());
2123        }
2124        return builder.build();
2125      }
2126    
2127      public static CachePoolInfo convert (CachePoolInfoProto proto) {
2128        // Pool name is a required field, the rest are optional
2129        String poolName = checkNotNull(proto.getPoolName());
2130        CachePoolInfo info = new CachePoolInfo(poolName);
2131        if (proto.hasOwnerName()) {
2132            info.setOwnerName(proto.getOwnerName());
2133        }
2134        if (proto.hasGroupName()) {
2135          info.setGroupName(proto.getGroupName());
2136        }
2137        if (proto.hasMode()) {
2138          info.setMode(new FsPermission((short)proto.getMode()));
2139        }
2140        if (proto.hasLimit())  {
2141          info.setLimit(proto.getLimit());
2142        }
2143        if (proto.hasMaxRelativeExpiry()) {
2144          info.setMaxRelativeExpiryMs(proto.getMaxRelativeExpiry());
2145        }
2146        return info;
2147      }
2148    
2149      public static CachePoolStatsProto convert(CachePoolStats stats) {
2150        CachePoolStatsProto.Builder builder = CachePoolStatsProto.newBuilder();
2151        builder.setBytesNeeded(stats.getBytesNeeded());
2152        builder.setBytesCached(stats.getBytesCached());
2153        builder.setBytesOverlimit(stats.getBytesOverlimit());
2154        builder.setFilesNeeded(stats.getFilesNeeded());
2155        builder.setFilesCached(stats.getFilesCached());
2156        return builder.build();
2157      }
2158    
2159      public static CachePoolStats convert (CachePoolStatsProto proto) {
2160        CachePoolStats.Builder builder = new CachePoolStats.Builder();
2161        builder.setBytesNeeded(proto.getBytesNeeded());
2162        builder.setBytesCached(proto.getBytesCached());
2163        builder.setBytesOverlimit(proto.getBytesOverlimit());
2164        builder.setFilesNeeded(proto.getFilesNeeded());
2165        builder.setFilesCached(proto.getFilesCached());
2166        return builder.build();
2167      }
2168    
2169      public static CachePoolEntryProto convert(CachePoolEntry entry) {
2170        CachePoolEntryProto.Builder builder = CachePoolEntryProto.newBuilder();
2171        builder.setInfo(PBHelper.convert(entry.getInfo()));
2172        builder.setStats(PBHelper.convert(entry.getStats()));
2173        return builder.build();
2174      }
2175    
2176      public static CachePoolEntry convert (CachePoolEntryProto proto) {
2177        CachePoolInfo info = PBHelper.convert(proto.getInfo());
2178        CachePoolStats stats = PBHelper.convert(proto.getStats());
2179        return new CachePoolEntry(info, stats);
2180      }
2181      
2182      public static HdfsProtos.ChecksumTypeProto convert(DataChecksum.Type type) {
2183        return HdfsProtos.ChecksumTypeProto.valueOf(type.id);
2184      }
2185    
2186      public static DatanodeLocalInfoProto convert(DatanodeLocalInfo info) {
2187        DatanodeLocalInfoProto.Builder builder = DatanodeLocalInfoProto.newBuilder();
2188        builder.setSoftwareVersion(info.getSoftwareVersion());
2189        builder.setConfigVersion(info.getConfigVersion());
2190        builder.setUptime(info.getUptime());
2191        return builder.build();
2192      }
2193    
2194      public static DatanodeLocalInfo convert(DatanodeLocalInfoProto proto) {
2195        return new DatanodeLocalInfo(proto.getSoftwareVersion(),
2196            proto.getConfigVersion(), proto.getUptime());
2197      }
2198    
2199      public static InputStream vintPrefixed(final InputStream input)
2200          throws IOException {
2201        final int firstByte = input.read();
2202        if (firstByte == -1) {
2203          throw new EOFException("Premature EOF: no length prefix available");
2204        }
2205    
2206        int size = CodedInputStream.readRawVarint32(firstByte, input);
2207        assert size >= 0;
2208        return new ExactSizeInputStream(input, size);
2209      }
2210    
2211      private static AclEntryScopeProto convert(AclEntryScope v) {
2212        return AclEntryScopeProto.valueOf(v.ordinal());
2213      }
2214    
2215      private static AclEntryScope convert(AclEntryScopeProto v) {
2216        return castEnum(v, ACL_ENTRY_SCOPE_VALUES);
2217      }
2218    
2219      private static AclEntryTypeProto convert(AclEntryType e) {
2220        return AclEntryTypeProto.valueOf(e.ordinal());
2221      }
2222    
2223      private static AclEntryType convert(AclEntryTypeProto v) {
2224        return castEnum(v, ACL_ENTRY_TYPE_VALUES);
2225      }
2226      
2227      private static XAttrNamespaceProto convert(XAttr.NameSpace v) {
2228        return XAttrNamespaceProto.valueOf(v.ordinal());
2229      }
2230      
2231      private static XAttr.NameSpace convert(XAttrNamespaceProto v) {
2232        return castEnum(v, XATTR_NAMESPACE_VALUES);
2233      }
2234    
2235      public static FsActionProto convert(FsAction v) {
2236        return FsActionProto.valueOf(v != null ? v.ordinal() : 0);
2237      }
2238    
2239      public static FsAction convert(FsActionProto v) {
2240        return castEnum(v, FSACTION_VALUES);
2241      }
2242    
2243      public static List<AclEntryProto> convertAclEntryProto(
2244          List<AclEntry> aclSpec) {
2245        ArrayList<AclEntryProto> r = Lists.newArrayListWithCapacity(aclSpec.size());
2246        for (AclEntry e : aclSpec) {
2247          AclEntryProto.Builder builder = AclEntryProto.newBuilder();
2248          builder.setType(convert(e.getType()));
2249          builder.setScope(convert(e.getScope()));
2250          builder.setPermissions(convert(e.getPermission()));
2251          if (e.getName() != null) {
2252            builder.setName(e.getName());
2253          }
2254          r.add(builder.build());
2255        }
2256        return r;
2257      }
2258    
2259      public static List<AclEntry> convertAclEntry(List<AclEntryProto> aclSpec) {
2260        ArrayList<AclEntry> r = Lists.newArrayListWithCapacity(aclSpec.size());
2261        for (AclEntryProto e : aclSpec) {
2262          AclEntry.Builder builder = new AclEntry.Builder();
2263          builder.setType(convert(e.getType()));
2264          builder.setScope(convert(e.getScope()));
2265          builder.setPermission(convert(e.getPermissions()));
2266          if (e.hasName()) {
2267            builder.setName(e.getName());
2268          }
2269          r.add(builder.build());
2270        }
2271        return r;
2272      }
2273    
2274      public static AclStatus convert(GetAclStatusResponseProto e) {
2275        AclStatusProto r = e.getResult();
2276        return new AclStatus.Builder().owner(r.getOwner()).group(r.getGroup())
2277            .stickyBit(r.getSticky())
2278            .addEntries(convertAclEntry(r.getEntriesList())).build();
2279      }
2280    
2281      public static GetAclStatusResponseProto convert(AclStatus e) {
2282        AclStatusProto r = AclStatusProto.newBuilder().setOwner(e.getOwner())
2283            .setGroup(e.getGroup()).setSticky(e.isStickyBit())
2284            .addAllEntries(convertAclEntryProto(e.getEntries())).build();
2285        return GetAclStatusResponseProto.newBuilder().setResult(r).build();
2286      }
2287      
2288      public static XAttrProto convertXAttrProto(XAttr a) {
2289        XAttrProto.Builder builder = XAttrProto.newBuilder();
2290        builder.setNamespace(convert(a.getNameSpace()));
2291        if (a.getName() != null) {
2292          builder.setName(a.getName());
2293        }
2294        if (a.getValue() != null) {
2295          builder.setValue(getByteString(a.getValue()));
2296        }
2297        return builder.build();
2298      }
2299      
2300      public static List<XAttrProto> convertXAttrProto(
2301          List<XAttr> xAttrSpec) {
2302        if (xAttrSpec == null) {
2303          return Lists.newArrayListWithCapacity(0);
2304        }
2305        ArrayList<XAttrProto> xAttrs = Lists.newArrayListWithCapacity(
2306            xAttrSpec.size());
2307        for (XAttr a : xAttrSpec) {
2308          XAttrProto.Builder builder = XAttrProto.newBuilder();
2309          builder.setNamespace(convert(a.getNameSpace()));
2310          if (a.getName() != null) {
2311            builder.setName(a.getName());
2312          }
2313          if (a.getValue() != null) {
2314            builder.setValue(getByteString(a.getValue()));
2315          }
2316          xAttrs.add(builder.build());
2317        }
2318        return xAttrs;
2319      }
2320      
2321      /**
2322       * The flag field in PB is a bitmask whose values are the same a the 
2323       * emum values of XAttrSetFlag
2324       */
2325      public static int convert(EnumSet<XAttrSetFlag> flag) {
2326        int value = 0;
2327        if (flag.contains(XAttrSetFlag.CREATE)) {
2328          value |= XAttrSetFlagProto.XATTR_CREATE.getNumber();
2329        }
2330        if (flag.contains(XAttrSetFlag.REPLACE)) {
2331          value |= XAttrSetFlagProto.XATTR_REPLACE.getNumber();
2332        }
2333        return value;
2334      }
2335     
2336      public static EnumSet<XAttrSetFlag> convert(int flag) {
2337        EnumSet<XAttrSetFlag> result = 
2338            EnumSet.noneOf(XAttrSetFlag.class);
2339        if ((flag & XAttrSetFlagProto.XATTR_CREATE_VALUE) == 
2340            XAttrSetFlagProto.XATTR_CREATE_VALUE) {
2341          result.add(XAttrSetFlag.CREATE);
2342        }
2343        if ((flag & XAttrSetFlagProto.XATTR_REPLACE_VALUE) == 
2344            XAttrSetFlagProto.XATTR_REPLACE_VALUE) {
2345          result.add(XAttrSetFlag.REPLACE);
2346        }
2347        return result;
2348      }
2349      
2350      public static XAttr convertXAttr(XAttrProto a) {
2351        XAttr.Builder builder = new XAttr.Builder();
2352        builder.setNameSpace(convert(a.getNamespace()));
2353        if (a.hasName()) {
2354          builder.setName(a.getName());
2355        }
2356        if (a.hasValue()) {
2357          builder.setValue(a.getValue().toByteArray());
2358        }
2359        return builder.build();
2360      }
2361      
2362      public static List<XAttr> convertXAttrs(List<XAttrProto> xAttrSpec) {
2363        ArrayList<XAttr> xAttrs = Lists.newArrayListWithCapacity(xAttrSpec.size());
2364        for (XAttrProto a : xAttrSpec) {
2365          XAttr.Builder builder = new XAttr.Builder();
2366          builder.setNameSpace(convert(a.getNamespace()));
2367          if (a.hasName()) {
2368            builder.setName(a.getName());
2369          }
2370          if (a.hasValue()) {
2371            builder.setValue(a.getValue().toByteArray());
2372          }
2373          xAttrs.add(builder.build());
2374        }
2375        return xAttrs;
2376      }
2377    
2378      public static List<XAttr> convert(GetXAttrsResponseProto a) {
2379        List<XAttrProto> xAttrs = a.getXAttrsList();
2380        return convertXAttrs(xAttrs);
2381      }
2382    
2383      public static GetXAttrsResponseProto convertXAttrsResponse(
2384          List<XAttr> xAttrs) {
2385        GetXAttrsResponseProto.Builder builder = GetXAttrsResponseProto
2386            .newBuilder();
2387        if (xAttrs != null) {
2388          builder.addAllXAttrs(convertXAttrProto(xAttrs));
2389        }
2390        return builder.build();
2391      }
2392    
2393      public static List<XAttr> convert(ListXAttrsResponseProto a) {
2394        final List<XAttrProto> xAttrs = a.getXAttrsList();
2395        return convertXAttrs(xAttrs);
2396      }
2397    
2398      public static ListXAttrsResponseProto convertListXAttrsResponse(
2399        List<XAttr> names) {
2400        ListXAttrsResponseProto.Builder builder =
2401          ListXAttrsResponseProto.newBuilder();
2402        if (names != null) {
2403          builder.addAllXAttrs(convertXAttrProto(names));
2404        }
2405        return builder.build();
2406      }
2407    
2408      public static EncryptionZoneProto convert(EncryptionZone zone) {
2409        return EncryptionZoneProto.newBuilder()
2410            .setId(zone.getId())
2411            .setPath(zone.getPath())
2412            .setSuite(convert(zone.getSuite()))
2413            .setCryptoProtocolVersion(convert(zone.getVersion()))
2414            .setKeyName(zone.getKeyName())
2415            .build();
2416      }
2417    
2418      public static EncryptionZone convert(EncryptionZoneProto proto) {
2419        return new EncryptionZone(proto.getId(), proto.getPath(),
2420            convert(proto.getSuite()), convert(proto.getCryptoProtocolVersion()),
2421            proto.getKeyName());
2422      }
2423    
2424      public static ShortCircuitShmSlotProto convert(SlotId slotId) {
2425        return ShortCircuitShmSlotProto.newBuilder().
2426            setShmId(convert(slotId.getShmId())).
2427            setSlotIdx(slotId.getSlotIdx()).
2428            build();
2429      }
2430    
2431      public static ShortCircuitShmIdProto convert(ShmId shmId) {
2432        return ShortCircuitShmIdProto.newBuilder().
2433            setHi(shmId.getHi()).
2434            setLo(shmId.getLo()).
2435            build();
2436    
2437      }
2438    
2439      public static SlotId convert(ShortCircuitShmSlotProto slotId) {
2440        return new SlotId(PBHelper.convert(slotId.getShmId()),
2441            slotId.getSlotIdx());
2442      }
2443    
2444      public static ShmId convert(ShortCircuitShmIdProto shmId) {
2445        return new ShmId(shmId.getHi(), shmId.getLo());
2446      }
2447    
2448      private static Event.CreateEvent.INodeType createTypeConvert(InotifyProtos.INodeType
2449          type) {
2450        switch (type) {
2451        case I_TYPE_DIRECTORY:
2452          return Event.CreateEvent.INodeType.DIRECTORY;
2453        case I_TYPE_FILE:
2454          return Event.CreateEvent.INodeType.FILE;
2455        case I_TYPE_SYMLINK:
2456          return Event.CreateEvent.INodeType.SYMLINK;
2457        default:
2458          return null;
2459        }
2460      }
2461    
2462      private static InotifyProtos.MetadataUpdateType metadataUpdateTypeConvert(
2463          Event.MetadataUpdateEvent.MetadataType type) {
2464        switch (type) {
2465        case TIMES:
2466          return InotifyProtos.MetadataUpdateType.META_TYPE_TIMES;
2467        case REPLICATION:
2468          return InotifyProtos.MetadataUpdateType.META_TYPE_REPLICATION;
2469        case OWNER:
2470          return InotifyProtos.MetadataUpdateType.META_TYPE_OWNER;
2471        case PERMS:
2472          return InotifyProtos.MetadataUpdateType.META_TYPE_PERMS;
2473        case ACLS:
2474          return InotifyProtos.MetadataUpdateType.META_TYPE_ACLS;
2475        case XATTRS:
2476          return InotifyProtos.MetadataUpdateType.META_TYPE_XATTRS;
2477        default:
2478          return null;
2479        }
2480      }
2481    
2482      private static Event.MetadataUpdateEvent.MetadataType metadataUpdateTypeConvert(
2483          InotifyProtos.MetadataUpdateType type) {
2484        switch (type) {
2485        case META_TYPE_TIMES:
2486          return Event.MetadataUpdateEvent.MetadataType.TIMES;
2487        case META_TYPE_REPLICATION:
2488          return Event.MetadataUpdateEvent.MetadataType.REPLICATION;
2489        case META_TYPE_OWNER:
2490          return Event.MetadataUpdateEvent.MetadataType.OWNER;
2491        case META_TYPE_PERMS:
2492          return Event.MetadataUpdateEvent.MetadataType.PERMS;
2493        case META_TYPE_ACLS:
2494          return Event.MetadataUpdateEvent.MetadataType.ACLS;
2495        case META_TYPE_XATTRS:
2496          return Event.MetadataUpdateEvent.MetadataType.XATTRS;
2497        default:
2498          return null;
2499        }
2500      }
2501    
2502      private static InotifyProtos.INodeType createTypeConvert(Event.CreateEvent.INodeType
2503          type) {
2504        switch (type) {
2505        case DIRECTORY:
2506          return InotifyProtos.INodeType.I_TYPE_DIRECTORY;
2507        case FILE:
2508          return InotifyProtos.INodeType.I_TYPE_FILE;
2509        case SYMLINK:
2510          return InotifyProtos.INodeType.I_TYPE_SYMLINK;
2511        default:
2512          return null;
2513        }
2514      }
2515    
2516      public static EventsList convert(GetEditsFromTxidResponseProto resp) throws
2517        IOException {
2518        List<Event> events = Lists.newArrayList();
2519        for (InotifyProtos.EventProto p : resp.getEventsList().getEventsList()) {
2520          switch(p.getType()) {
2521          case EVENT_CLOSE:
2522            InotifyProtos.CloseEventProto close =
2523                InotifyProtos.CloseEventProto.parseFrom(p.getContents());
2524            events.add(new Event.CloseEvent(close.getPath(), close.getFileSize(),
2525                close.getTimestamp()));
2526            break;
2527          case EVENT_CREATE:
2528            InotifyProtos.CreateEventProto create =
2529                InotifyProtos.CreateEventProto.parseFrom(p.getContents());
2530            events.add(new Event.CreateEvent.Builder()
2531                .iNodeType(createTypeConvert(create.getType()))
2532                .path(create.getPath())
2533                .ctime(create.getCtime())
2534                .ownerName(create.getOwnerName())
2535                .groupName(create.getGroupName())
2536                .perms(convert(create.getPerms()))
2537                .replication(create.getReplication())
2538                .symlinkTarget(create.getSymlinkTarget().isEmpty() ? null :
2539                create.getSymlinkTarget())
2540                .overwrite(create.getOverwrite()).build());
2541            break;
2542          case EVENT_METADATA:
2543            InotifyProtos.MetadataUpdateEventProto meta =
2544                InotifyProtos.MetadataUpdateEventProto.parseFrom(p.getContents());
2545            events.add(new Event.MetadataUpdateEvent.Builder()
2546                .path(meta.getPath())
2547                .metadataType(metadataUpdateTypeConvert(meta.getType()))
2548                .mtime(meta.getMtime())
2549                .atime(meta.getAtime())
2550                .replication(meta.getReplication())
2551                .ownerName(
2552                    meta.getOwnerName().isEmpty() ? null : meta.getOwnerName())
2553                .groupName(
2554                    meta.getGroupName().isEmpty() ? null : meta.getGroupName())
2555                .perms(meta.hasPerms() ? convert(meta.getPerms()) : null)
2556                .acls(meta.getAclsList().isEmpty() ? null : convertAclEntry(
2557                    meta.getAclsList()))
2558                .xAttrs(meta.getXAttrsList().isEmpty() ? null : convertXAttrs(
2559                    meta.getXAttrsList()))
2560                .xAttrsRemoved(meta.getXAttrsRemoved())
2561                .build());
2562            break;
2563          case EVENT_RENAME:
2564            InotifyProtos.RenameEventProto rename =
2565                InotifyProtos.RenameEventProto.parseFrom(p.getContents());
2566            events.add(new Event.RenameEvent(rename.getSrcPath(), rename.getDestPath(),
2567                rename.getTimestamp()));
2568            break;
2569          case EVENT_APPEND:
2570            InotifyProtos.AppendEventProto reopen =
2571                InotifyProtos.AppendEventProto.parseFrom(p.getContents());
2572            events.add(new Event.AppendEvent(reopen.getPath()));
2573            break;
2574          case EVENT_UNLINK:
2575            InotifyProtos.UnlinkEventProto unlink =
2576                InotifyProtos.UnlinkEventProto.parseFrom(p.getContents());
2577            events.add(new Event.UnlinkEvent(unlink.getPath(), unlink.getTimestamp()));
2578            break;
2579          default:
2580            throw new RuntimeException("Unexpected inotify event type: " +
2581                p.getType());
2582          }
2583        }
2584        return new EventsList(events, resp.getEventsList().getFirstTxid(),
2585            resp.getEventsList().getLastTxid(), resp.getEventsList().getSyncTxid());
2586      }
2587    
2588      public static GetEditsFromTxidResponseProto convertEditsResponse(EventsList el) {
2589        InotifyProtos.EventsListProto.Builder builder =
2590            InotifyProtos.EventsListProto.newBuilder();
2591        for (Event e : el.getEvents()) {
2592          switch(e.getEventType()) {
2593          case CLOSE:
2594            Event.CloseEvent ce = (Event.CloseEvent) e;
2595            builder.addEvents(InotifyProtos.EventProto.newBuilder()
2596                .setType(InotifyProtos.EventType.EVENT_CLOSE)
2597                .setContents(
2598                    InotifyProtos.CloseEventProto.newBuilder()
2599                        .setPath(ce.getPath())
2600                        .setFileSize(ce.getFileSize())
2601                        .setTimestamp(ce.getTimestamp()).build().toByteString()
2602                ).build());
2603            break;
2604          case CREATE:
2605            Event.CreateEvent ce2 = (Event.CreateEvent) e;
2606            builder.addEvents(InotifyProtos.EventProto.newBuilder()
2607                .setType(InotifyProtos.EventType.EVENT_CREATE)
2608                .setContents(
2609                    InotifyProtos.CreateEventProto.newBuilder()
2610                        .setType(createTypeConvert(ce2.getiNodeType()))
2611                        .setPath(ce2.getPath())
2612                        .setCtime(ce2.getCtime())
2613                        .setOwnerName(ce2.getOwnerName())
2614                        .setGroupName(ce2.getGroupName())
2615                        .setPerms(convert(ce2.getPerms()))
2616                        .setReplication(ce2.getReplication())
2617                        .setSymlinkTarget(ce2.getSymlinkTarget() == null ?
2618                            "" : ce2.getSymlinkTarget())
2619                        .setOverwrite(ce2.getOverwrite()).build().toByteString()
2620                ).build());
2621            break;
2622          case METADATA:
2623            Event.MetadataUpdateEvent me = (Event.MetadataUpdateEvent) e;
2624            InotifyProtos.MetadataUpdateEventProto.Builder metaB =
2625                InotifyProtos.MetadataUpdateEventProto.newBuilder()
2626                    .setPath(me.getPath())
2627                    .setType(metadataUpdateTypeConvert(me.getMetadataType()))
2628                    .setMtime(me.getMtime())
2629                    .setAtime(me.getAtime())
2630                    .setReplication(me.getReplication())
2631                    .setOwnerName(me.getOwnerName() == null ? "" :
2632                        me.getOwnerName())
2633                    .setGroupName(me.getGroupName() == null ? "" :
2634                        me.getGroupName())
2635                    .addAllAcls(me.getAcls() == null ?
2636                        Lists.<AclEntryProto>newArrayList() :
2637                        convertAclEntryProto(me.getAcls()))
2638                    .addAllXAttrs(me.getxAttrs() == null ?
2639                        Lists.<XAttrProto>newArrayList() :
2640                        convertXAttrProto(me.getxAttrs()))
2641                    .setXAttrsRemoved(me.isxAttrsRemoved());
2642            if (me.getPerms() != null) {
2643              metaB.setPerms(convert(me.getPerms()));
2644            }
2645            builder.addEvents(InotifyProtos.EventProto.newBuilder()
2646                .setType(InotifyProtos.EventType.EVENT_METADATA)
2647                .setContents(metaB.build().toByteString())
2648                .build());
2649            break;
2650          case RENAME:
2651            Event.RenameEvent re = (Event.RenameEvent) e;
2652            builder.addEvents(InotifyProtos.EventProto.newBuilder()
2653                .setType(InotifyProtos.EventType.EVENT_RENAME)
2654                .setContents(
2655                    InotifyProtos.RenameEventProto.newBuilder()
2656                        .setSrcPath(re.getSrcPath())
2657                        .setDestPath(re.getDstPath())
2658                        .setTimestamp(re.getTimestamp()).build().toByteString()
2659                ).build());
2660            break;
2661          case APPEND:
2662            Event.AppendEvent re2 = (Event.AppendEvent) e;
2663            builder.addEvents(InotifyProtos.EventProto.newBuilder()
2664                .setType(InotifyProtos.EventType.EVENT_APPEND)
2665                .setContents(
2666                    InotifyProtos.AppendEventProto.newBuilder()
2667                        .setPath(re2.getPath()).build().toByteString()
2668                ).build());
2669            break;
2670          case UNLINK:
2671            Event.UnlinkEvent ue = (Event.UnlinkEvent) e;
2672            builder.addEvents(InotifyProtos.EventProto.newBuilder()
2673                .setType(InotifyProtos.EventType.EVENT_UNLINK)
2674                .setContents(
2675                    InotifyProtos.UnlinkEventProto.newBuilder()
2676                        .setPath(ue.getPath())
2677                        .setTimestamp(ue.getTimestamp()).build().toByteString()
2678                ).build());
2679            break;
2680          default:
2681            throw new RuntimeException("Unexpected inotify event: " + e);
2682          }
2683        }
2684        builder.setFirstTxid(el.getFirstTxid());
2685        builder.setLastTxid(el.getLastTxid());
2686        builder.setSyncTxid(el.getSyncTxid());
2687        return GetEditsFromTxidResponseProto.newBuilder().setEventsList(
2688            builder.build()).build();
2689      }
2690      
2691      public static CipherOptionProto convert(CipherOption option) {
2692        if (option != null) {
2693          CipherOptionProto.Builder builder = CipherOptionProto.
2694              newBuilder();
2695          if (option.getCipherSuite() != null) {
2696            builder.setSuite(convert(option.getCipherSuite()));
2697          }
2698          if (option.getInKey() != null) {
2699            builder.setInKey(ByteString.copyFrom(option.getInKey()));
2700          }
2701          if (option.getInIv() != null) {
2702            builder.setInIv(ByteString.copyFrom(option.getInIv()));
2703          }
2704          if (option.getOutKey() != null) {
2705            builder.setOutKey(ByteString.copyFrom(option.getOutKey()));
2706          }
2707          if (option.getOutIv() != null) {
2708            builder.setOutIv(ByteString.copyFrom(option.getOutIv()));
2709          }
2710          return builder.build();
2711        }
2712        return null;
2713      }
2714      
2715      public static CipherOption convert(CipherOptionProto proto) {
2716        if (proto != null) {
2717          CipherSuite suite = null;
2718          if (proto.getSuite() != null) {
2719            suite = convert(proto.getSuite());
2720          }
2721          byte[] inKey = null;
2722          if (proto.getInKey() != null) {
2723            inKey = proto.getInKey().toByteArray();
2724          }
2725          byte[] inIv = null;
2726          if (proto.getInIv() != null) {
2727            inIv = proto.getInIv().toByteArray();
2728          }
2729          byte[] outKey = null;
2730          if (proto.getOutKey() != null) {
2731            outKey = proto.getOutKey().toByteArray();
2732          }
2733          byte[] outIv = null;
2734          if (proto.getOutIv() != null) {
2735            outIv = proto.getOutIv().toByteArray();
2736          }
2737          return new CipherOption(suite, inKey, inIv, outKey, outIv);
2738        }
2739        return null;
2740      }
2741      
2742      public static List<CipherOptionProto> convertCipherOptions(
2743          List<CipherOption> options) {
2744        if (options != null) {
2745          List<CipherOptionProto> protos = 
2746              Lists.newArrayListWithCapacity(options.size());
2747          for (CipherOption option : options) {
2748            protos.add(convert(option));
2749          }
2750          return protos;
2751        }
2752        return null;
2753      }
2754      
2755      public static List<CipherOption> convertCipherOptionProtos(
2756          List<CipherOptionProto> protos) {
2757        if (protos != null) {
2758          List<CipherOption> options = 
2759              Lists.newArrayListWithCapacity(protos.size());
2760          for (CipherOptionProto proto : protos) {
2761            options.add(convert(proto));
2762          }
2763          return options;
2764        }
2765        return null;
2766      }
2767    
2768      public static CipherSuiteProto convert(CipherSuite suite) {
2769        switch (suite) {
2770        case UNKNOWN:
2771          return CipherSuiteProto.UNKNOWN;
2772        case AES_CTR_NOPADDING:
2773          return CipherSuiteProto.AES_CTR_NOPADDING;
2774        default:
2775          return null;
2776        }
2777      }
2778    
2779      public static CipherSuite convert(CipherSuiteProto proto) {
2780        switch (proto) {
2781        case AES_CTR_NOPADDING:
2782          return CipherSuite.AES_CTR_NOPADDING;
2783        default:
2784          // Set to UNKNOWN and stash the unknown enum value
2785          CipherSuite suite = CipherSuite.UNKNOWN;
2786          suite.setUnknownValue(proto.getNumber());
2787          return suite;
2788        }
2789      }
2790    
2791      public static List<CryptoProtocolVersionProto> convert(
2792          CryptoProtocolVersion[] versions) {
2793        List<CryptoProtocolVersionProto> protos =
2794            Lists.newArrayListWithCapacity(versions.length);
2795        for (CryptoProtocolVersion v: versions) {
2796          protos.add(convert(v));
2797        }
2798        return protos;
2799      }
2800    
2801      public static CryptoProtocolVersion[] convertCryptoProtocolVersions(
2802          List<CryptoProtocolVersionProto> protos) {
2803        List<CryptoProtocolVersion> versions =
2804            Lists.newArrayListWithCapacity(protos.size());
2805        for (CryptoProtocolVersionProto p: protos) {
2806          versions.add(convert(p));
2807        }
2808        return versions.toArray(new CryptoProtocolVersion[] {});
2809      }
2810    
2811      public static CryptoProtocolVersion convert(CryptoProtocolVersionProto
2812          proto) {
2813        switch(proto) {
2814        case ENCRYPTION_ZONES:
2815          return CryptoProtocolVersion.ENCRYPTION_ZONES;
2816        default:
2817          // Set to UNKNOWN and stash the unknown enum value
2818          CryptoProtocolVersion version = CryptoProtocolVersion.UNKNOWN;
2819          version.setUnknownValue(proto.getNumber());
2820          return version;
2821        }
2822      }
2823    
2824      public static CryptoProtocolVersionProto convert(CryptoProtocolVersion
2825          version) {
2826        switch(version) {
2827        case UNKNOWN:
2828          return CryptoProtocolVersionProto.UNKNOWN_PROTOCOL_VERSION;
2829        case ENCRYPTION_ZONES:
2830          return CryptoProtocolVersionProto.ENCRYPTION_ZONES;
2831        default:
2832          return null;
2833        }
2834      }
2835    
2836      public static HdfsProtos.FileEncryptionInfoProto convert(
2837          FileEncryptionInfo info) {
2838        if (info == null) {
2839          return null;
2840        }
2841        return HdfsProtos.FileEncryptionInfoProto.newBuilder()
2842            .setSuite(convert(info.getCipherSuite()))
2843            .setCryptoProtocolVersion(convert(info.getCryptoProtocolVersion()))
2844            .setKey(getByteString(info.getEncryptedDataEncryptionKey()))
2845            .setIv(getByteString(info.getIV()))
2846            .setEzKeyVersionName(info.getEzKeyVersionName())
2847            .setKeyName(info.getKeyName())
2848            .build();
2849      }
2850    
2851      public static HdfsProtos.PerFileEncryptionInfoProto convertPerFileEncInfo(
2852          FileEncryptionInfo info) {
2853        if (info == null) {
2854          return null;
2855        }
2856        return HdfsProtos.PerFileEncryptionInfoProto.newBuilder()
2857            .setKey(getByteString(info.getEncryptedDataEncryptionKey()))
2858            .setIv(getByteString(info.getIV()))
2859            .setEzKeyVersionName(info.getEzKeyVersionName())
2860            .build();
2861      }
2862    
2863      public static HdfsProtos.ZoneEncryptionInfoProto convert(
2864          CipherSuite suite, CryptoProtocolVersion version, String keyName) {
2865        if (suite == null || version == null || keyName == null) {
2866          return null;
2867        }
2868        return HdfsProtos.ZoneEncryptionInfoProto.newBuilder()
2869            .setSuite(convert(suite))
2870            .setCryptoProtocolVersion(convert(version))
2871            .setKeyName(keyName)
2872            .build();
2873      }
2874    
2875      public static FileEncryptionInfo convert(
2876          HdfsProtos.FileEncryptionInfoProto proto) {
2877        if (proto == null) {
2878          return null;
2879        }
2880        CipherSuite suite = convert(proto.getSuite());
2881        CryptoProtocolVersion version = convert(proto.getCryptoProtocolVersion());
2882        byte[] key = proto.getKey().toByteArray();
2883        byte[] iv = proto.getIv().toByteArray();
2884        String ezKeyVersionName = proto.getEzKeyVersionName();
2885        String keyName = proto.getKeyName();
2886        return new FileEncryptionInfo(suite, version, key, iv, keyName,
2887            ezKeyVersionName);
2888      }
2889    
2890      public static FileEncryptionInfo convert(
2891          HdfsProtos.PerFileEncryptionInfoProto fileProto,
2892          CipherSuite suite, CryptoProtocolVersion version, String keyName) {
2893        if (fileProto == null || suite == null || version == null ||
2894            keyName == null) {
2895          return null;
2896        }
2897        byte[] key = fileProto.getKey().toByteArray();
2898        byte[] iv = fileProto.getIv().toByteArray();
2899        String ezKeyVersionName = fileProto.getEzKeyVersionName();
2900        return new FileEncryptionInfo(suite, version, key, iv, keyName,
2901            ezKeyVersionName);
2902      }
2903    
2904    }