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