001/**
002 * Licensed to the Apache Software Foundation (ASF) under one
003 * or more contributor license agreements.  See the NOTICE file
004 * distributed with this work for additional information
005 * regarding copyright ownership.  The ASF licenses this file
006 * to you under the Apache License, Version 2.0 (the
007 * "License"); you may not use this file except in compliance
008 * with the License.  You may obtain a copy of the License at
009 *
010 *     http://www.apache.org/licenses/LICENSE-2.0
011 *
012 * Unless required by applicable law or agreed to in writing, software
013 * distributed under the License is distributed on an "AS IS" BASIS,
014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
015 * See the License for the specific language governing permissions and
016 * limitations under the License.
017 */
018package org.apache.hadoop.hdfs.protocolPB;
019
020import java.io.EOFException;
021import java.io.IOException;
022import java.io.InputStream;
023import java.util.ArrayList;
024import java.util.Arrays;
025import java.util.EnumSet;
026import java.util.List;
027
028import com.google.common.base.Preconditions;
029import com.google.common.collect.Lists;
030import com.google.common.primitives.Shorts;
031import com.google.protobuf.ByteString;
032import com.google.protobuf.CodedInputStream;
033
034import static com.google.common.base.Preconditions.checkNotNull;
035
036import org.apache.hadoop.crypto.CipherOption;
037import org.apache.hadoop.crypto.CipherSuite;
038import org.apache.hadoop.crypto.CryptoProtocolVersion;
039import org.apache.hadoop.hdfs.AddBlockFlag;
040import org.apache.hadoop.fs.CacheFlag;
041import org.apache.hadoop.fs.ContentSummary;
042import org.apache.hadoop.fs.CreateFlag;
043import org.apache.hadoop.fs.FileEncryptionInfo;
044import org.apache.hadoop.fs.FsServerDefaults;
045import org.apache.hadoop.fs.Path;
046import org.apache.hadoop.fs.QuotaUsage;
047import org.apache.hadoop.fs.StorageType;
048import org.apache.hadoop.fs.XAttr;
049import org.apache.hadoop.fs.XAttrSetFlag;
050import org.apache.hadoop.fs.permission.AclEntry;
051import org.apache.hadoop.fs.permission.AclEntryScope;
052import org.apache.hadoop.fs.permission.AclEntryType;
053import org.apache.hadoop.fs.permission.AclStatus;
054import org.apache.hadoop.fs.permission.FsAction;
055import org.apache.hadoop.fs.permission.FsPermission;
056import org.apache.hadoop.hdfs.DFSUtilClient;
057import org.apache.hadoop.hdfs.inotify.Event;
058import org.apache.hadoop.hdfs.inotify.EventBatch;
059import org.apache.hadoop.hdfs.inotify.EventBatchList;
060import org.apache.hadoop.hdfs.protocol.Block;
061import org.apache.hadoop.hdfs.protocol.BlockStoragePolicy;
062import org.apache.hadoop.hdfs.protocol.CacheDirectiveEntry;
063import org.apache.hadoop.hdfs.protocol.CacheDirectiveInfo;
064import org.apache.hadoop.hdfs.protocol.CacheDirectiveStats;
065import org.apache.hadoop.hdfs.protocol.CachePoolEntry;
066import org.apache.hadoop.hdfs.protocol.CachePoolInfo;
067import org.apache.hadoop.hdfs.protocol.CachePoolStats;
068import org.apache.hadoop.hdfs.protocol.ClientProtocol;
069import org.apache.hadoop.hdfs.protocol.CorruptFileBlocks;
070import org.apache.hadoop.hdfs.protocol.DatanodeID;
071import org.apache.hadoop.hdfs.protocol.DatanodeInfo;
072import org.apache.hadoop.hdfs.protocol.DatanodeInfo.AdminStates;
073import org.apache.hadoop.hdfs.protocol.DatanodeLocalInfo;
074import org.apache.hadoop.hdfs.protocol.DirectoryListing;
075import org.apache.hadoop.hdfs.protocol.EncryptionZone;
076import org.apache.hadoop.hdfs.protocol.ExtendedBlock;
077import org.apache.hadoop.hdfs.protocol.FsPermissionExtension;
078import org.apache.hadoop.hdfs.protocol.HdfsConstants;
079import org.apache.hadoop.hdfs.protocol.HdfsConstants.DatanodeReportType;
080import org.apache.hadoop.hdfs.protocol.HdfsConstants.RollingUpgradeAction;
081import org.apache.hadoop.hdfs.protocol.HdfsConstants.SafeModeAction;
082import org.apache.hadoop.hdfs.protocol.HdfsFileStatus;
083import org.apache.hadoop.hdfs.protocol.HdfsLocatedFileStatus;
084import org.apache.hadoop.hdfs.protocol.LocatedBlock;
085import org.apache.hadoop.hdfs.protocol.LocatedBlocks;
086import org.apache.hadoop.hdfs.protocol.RollingUpgradeInfo;
087import org.apache.hadoop.hdfs.protocol.RollingUpgradeStatus;
088import org.apache.hadoop.hdfs.protocol.SnapshotDiffReport;
089import org.apache.hadoop.hdfs.protocol.SnapshotDiffReport.DiffReportEntry;
090import org.apache.hadoop.hdfs.protocol.SnapshotDiffReport.DiffType;
091import org.apache.hadoop.hdfs.protocol.SnapshottableDirectoryStatus;
092import org.apache.hadoop.hdfs.protocol.proto.AclProtos.AclEntryProto;
093import org.apache.hadoop.hdfs.protocol.proto.AclProtos.AclEntryProto.AclEntryScopeProto;
094import org.apache.hadoop.hdfs.protocol.proto.AclProtos.AclEntryProto.AclEntryTypeProto;
095import org.apache.hadoop.hdfs.protocol.proto.AclProtos.AclEntryProto.FsActionProto;
096import org.apache.hadoop.hdfs.protocol.proto.AclProtos.AclStatusProto;
097import org.apache.hadoop.hdfs.protocol.proto.AclProtos.GetAclStatusResponseProto;
098import org.apache.hadoop.hdfs.protocol.proto.ClientNamenodeProtocolProtos.AddBlockFlagProto;
099import org.apache.hadoop.hdfs.protocol.proto.ClientNamenodeProtocolProtos.CacheDirectiveEntryProto;
100import org.apache.hadoop.hdfs.protocol.proto.ClientNamenodeProtocolProtos.CacheDirectiveInfoExpirationProto;
101import org.apache.hadoop.hdfs.protocol.proto.ClientNamenodeProtocolProtos.CacheDirectiveInfoProto;
102import org.apache.hadoop.hdfs.protocol.proto.ClientNamenodeProtocolProtos.CacheDirectiveStatsProto;
103import org.apache.hadoop.hdfs.protocol.proto.ClientNamenodeProtocolProtos.CacheFlagProto;
104import org.apache.hadoop.hdfs.protocol.proto.ClientNamenodeProtocolProtos.CachePoolEntryProto;
105import org.apache.hadoop.hdfs.protocol.proto.ClientNamenodeProtocolProtos.CachePoolInfoProto;
106import org.apache.hadoop.hdfs.protocol.proto.ClientNamenodeProtocolProtos.CachePoolStatsProto;
107import org.apache.hadoop.hdfs.protocol.proto.ClientNamenodeProtocolProtos.CreateFlagProto;
108import org.apache.hadoop.hdfs.protocol.proto.ClientNamenodeProtocolProtos.DatanodeReportTypeProto;
109import org.apache.hadoop.hdfs.protocol.proto.ClientNamenodeProtocolProtos.DatanodeStorageReportProto;
110import org.apache.hadoop.hdfs.protocol.proto.ClientNamenodeProtocolProtos.GetEditsFromTxidResponseProto;
111import org.apache.hadoop.hdfs.protocol.proto.ClientNamenodeProtocolProtos.GetFsStatsResponseProto;
112import org.apache.hadoop.hdfs.protocol.proto.ClientNamenodeProtocolProtos.RollingUpgradeActionProto;
113import org.apache.hadoop.hdfs.protocol.proto.ClientNamenodeProtocolProtos.RollingUpgradeInfoProto;
114import org.apache.hadoop.hdfs.protocol.proto.ClientNamenodeProtocolProtos.SafeModeActionProto;
115import org.apache.hadoop.hdfs.protocol.proto.DataTransferProtos.ShortCircuitShmIdProto;
116import org.apache.hadoop.hdfs.protocol.proto.DataTransferProtos.ShortCircuitShmSlotProto;
117import org.apache.hadoop.hdfs.protocol.proto.EncryptionZonesProtos.EncryptionZoneProto;
118import org.apache.hadoop.hdfs.protocol.proto.HdfsProtos;
119import org.apache.hadoop.hdfs.protocol.proto.HdfsProtos.BlockProto;
120import org.apache.hadoop.hdfs.protocol.proto.HdfsProtos.BlockStoragePolicyProto;
121import org.apache.hadoop.hdfs.protocol.proto.HdfsProtos.ContentSummaryProto;
122import org.apache.hadoop.hdfs.protocol.proto.HdfsProtos.CorruptFileBlocksProto;
123import org.apache.hadoop.hdfs.protocol.proto.HdfsProtos.CryptoProtocolVersionProto;
124import org.apache.hadoop.hdfs.protocol.proto.HdfsProtos.DataEncryptionKeyProto;
125import org.apache.hadoop.hdfs.protocol.proto.HdfsProtos.DatanodeIDProto;
126import org.apache.hadoop.hdfs.protocol.proto.HdfsProtos.DatanodeInfoProto;
127import org.apache.hadoop.hdfs.protocol.proto.HdfsProtos.DatanodeInfoProto.AdminState;
128import org.apache.hadoop.hdfs.protocol.proto.HdfsProtos.DatanodeInfosProto;
129import org.apache.hadoop.hdfs.protocol.proto.HdfsProtos.DatanodeLocalInfoProto;
130import org.apache.hadoop.hdfs.protocol.proto.HdfsProtos.DatanodeStorageProto;
131import org.apache.hadoop.hdfs.protocol.proto.HdfsProtos.DatanodeStorageProto.StorageState;
132import org.apache.hadoop.hdfs.protocol.proto.HdfsProtos.DirectoryListingProto;
133import org.apache.hadoop.hdfs.protocol.proto.HdfsProtos.ExtendedBlockProto;
134import org.apache.hadoop.hdfs.protocol.proto.HdfsProtos.FsPermissionProto;
135import org.apache.hadoop.hdfs.protocol.proto.HdfsProtos.FsServerDefaultsProto;
136import org.apache.hadoop.hdfs.protocol.proto.HdfsProtos.HdfsFileStatusProto;
137import org.apache.hadoop.hdfs.protocol.proto.HdfsProtos.HdfsFileStatusProto.FileType;
138import org.apache.hadoop.hdfs.protocol.proto.HdfsProtos.LocatedBlockProto;
139import org.apache.hadoop.hdfs.protocol.proto.HdfsProtos.LocatedBlockProto.Builder;
140import org.apache.hadoop.hdfs.protocol.proto.HdfsProtos.LocatedBlocksProto;
141import org.apache.hadoop.hdfs.protocol.proto.HdfsProtos.QuotaUsageProto;
142import org.apache.hadoop.hdfs.protocol.proto.HdfsProtos.RollingUpgradeStatusProto;
143import org.apache.hadoop.hdfs.protocol.proto.HdfsProtos.SnapshotDiffReportEntryProto;
144import org.apache.hadoop.hdfs.protocol.proto.HdfsProtos.SnapshotDiffReportProto;
145import org.apache.hadoop.hdfs.protocol.proto.HdfsProtos.SnapshottableDirectoryListingProto;
146import org.apache.hadoop.hdfs.protocol.proto.HdfsProtos.SnapshottableDirectoryStatusProto;
147import org.apache.hadoop.hdfs.protocol.proto.HdfsProtos.StorageReportProto;
148import org.apache.hadoop.hdfs.protocol.proto.HdfsProtos.StorageTypeProto;
149import org.apache.hadoop.hdfs.protocol.proto.HdfsProtos.StorageTypesProto;
150import org.apache.hadoop.hdfs.protocol.proto.InotifyProtos;
151import org.apache.hadoop.hdfs.protocol.proto.XAttrProtos.GetXAttrsResponseProto;
152import org.apache.hadoop.hdfs.protocol.proto.XAttrProtos.ListXAttrsResponseProto;
153import org.apache.hadoop.hdfs.protocol.proto.XAttrProtos.XAttrProto;
154import org.apache.hadoop.hdfs.protocol.proto.XAttrProtos.XAttrProto.XAttrNamespaceProto;
155import org.apache.hadoop.hdfs.protocol.proto.XAttrProtos.XAttrSetFlagProto;
156import org.apache.hadoop.hdfs.security.token.block.BlockTokenIdentifier;
157import org.apache.hadoop.hdfs.security.token.block.DataEncryptionKey;
158import org.apache.hadoop.hdfs.security.token.delegation.DelegationTokenIdentifier;
159import org.apache.hadoop.hdfs.server.protocol.DatanodeStorage;
160import org.apache.hadoop.hdfs.server.protocol.DatanodeStorage.State;
161import org.apache.hadoop.hdfs.server.protocol.DatanodeStorageReport;
162import org.apache.hadoop.hdfs.server.protocol.StorageReport;
163import org.apache.hadoop.hdfs.shortcircuit.ShortCircuitShm.ShmId;
164import org.apache.hadoop.hdfs.shortcircuit.ShortCircuitShm.SlotId;
165import org.apache.hadoop.io.EnumSetWritable;
166import org.apache.hadoop.io.Text;
167import org.apache.hadoop.security.proto.SecurityProtos.TokenProto;
168import org.apache.hadoop.security.token.Token;
169import org.apache.hadoop.util.DataChecksum;
170import org.apache.hadoop.util.LimitInputStream;
171
172/**
173 * Utilities for converting protobuf classes to and from hdfs-client side
174 * implementation classes and other helper utilities to help in dealing with
175 * protobuf.
176 *
177 * Note that when converting from an internal type to protobuf type, the
178 * converter never return null for protobuf type. The check for internal type
179 * being null must be done before calling the convert() method.
180 */
181public class PBHelperClient {
182  private static final XAttr.NameSpace[] XATTR_NAMESPACE_VALUES =
183      XAttr.NameSpace.values();
184  private static final AclEntryType[] ACL_ENTRY_TYPE_VALUES =
185      AclEntryType.values();
186  private static final AclEntryScope[] ACL_ENTRY_SCOPE_VALUES =
187      AclEntryScope.values();
188  private static final FsAction[] FSACTION_VALUES =
189      FsAction.values();
190
191  private PBHelperClient() {
192    /** Hidden constructor */
193  }
194
195  public static ByteString getByteString(byte[] bytes) {
196    // return singleton to reduce object allocation
197    return (bytes.length == 0) ? ByteString.EMPTY : ByteString.copyFrom(bytes);
198  }
199
200  public static ShmId convert(ShortCircuitShmIdProto shmId) {
201    return new ShmId(shmId.getHi(), shmId.getLo());
202  }
203
204  public static DataChecksum.Type convert(HdfsProtos.ChecksumTypeProto type) {
205    return DataChecksum.Type.valueOf(type.getNumber());
206  }
207
208  public static HdfsProtos.ChecksumTypeProto convert(DataChecksum.Type type) {
209    return HdfsProtos.ChecksumTypeProto.valueOf(type.id);
210  }
211
212  public static ExtendedBlockProto convert(final ExtendedBlock b) {
213    if (b == null) return null;
214    return ExtendedBlockProto.newBuilder().
215        setPoolId(b.getBlockPoolId()).
216        setBlockId(b.getBlockId()).
217        setNumBytes(b.getNumBytes()).
218        setGenerationStamp(b.getGenerationStamp()).
219        build();
220  }
221
222  public static TokenProto convert(Token<?> tok) {
223    return TokenProto.newBuilder().
224        setIdentifier(getByteString(tok.getIdentifier())).
225        setPassword(getByteString(tok.getPassword())).
226        setKind(tok.getKind().toString()).
227        setService(tok.getService().toString()).build();
228  }
229
230  public static ShortCircuitShmIdProto convert(ShmId shmId) {
231    return ShortCircuitShmIdProto.newBuilder().
232        setHi(shmId.getHi()).
233        setLo(shmId.getLo()).
234        build();
235
236  }
237
238  public static ShortCircuitShmSlotProto convert(SlotId slotId) {
239    return ShortCircuitShmSlotProto.newBuilder().
240        setShmId(convert(slotId.getShmId())).
241        setSlotIdx(slotId.getSlotIdx()).
242        build();
243  }
244
245  public static DatanodeIDProto convert(DatanodeID dn) {
246    // For wire compatibility with older versions we transmit the StorageID
247    // which is the same as the DatanodeUuid. Since StorageID is a required
248    // field we pass the empty string if the DatanodeUuid is not yet known.
249    return DatanodeIDProto.newBuilder()
250        .setIpAddr(dn.getIpAddr())
251        .setHostName(dn.getHostName())
252        .setXferPort(dn.getXferPort())
253        .setDatanodeUuid(dn.getDatanodeUuid() != null ?
254            dn.getDatanodeUuid() : "")
255        .setInfoPort(dn.getInfoPort())
256        .setInfoSecurePort(dn.getInfoSecurePort())
257        .setIpcPort(dn.getIpcPort()).build();
258  }
259
260  public static DatanodeInfoProto.AdminState convert(
261      final DatanodeInfo.AdminStates inAs) {
262    switch (inAs) {
263    case NORMAL: return  DatanodeInfoProto.AdminState.NORMAL;
264    case DECOMMISSION_INPROGRESS:
265      return DatanodeInfoProto.AdminState.DECOMMISSION_INPROGRESS;
266    case DECOMMISSIONED: return DatanodeInfoProto.AdminState.DECOMMISSIONED;
267    default: return DatanodeInfoProto.AdminState.NORMAL;
268    }
269  }
270
271  public static DatanodeInfoProto convert(DatanodeInfo info) {
272    DatanodeInfoProto.Builder builder = DatanodeInfoProto.newBuilder();
273    if (info.getNetworkLocation() != null) {
274      builder.setLocation(info.getNetworkLocation());
275    }
276    if (info.getUpgradeDomain() != null) {
277      builder.setUpgradeDomain(info.getUpgradeDomain());
278    }
279    builder
280        .setId(convert((DatanodeID) info))
281        .setCapacity(info.getCapacity())
282        .setDfsUsed(info.getDfsUsed())
283        .setNonDfsUsed(info.getNonDfsUsed())
284        .setRemaining(info.getRemaining())
285        .setBlockPoolUsed(info.getBlockPoolUsed())
286        .setCacheCapacity(info.getCacheCapacity())
287        .setCacheUsed(info.getCacheUsed())
288        .setLastUpdate(info.getLastUpdate())
289        .setLastUpdateMonotonic(info.getLastUpdateMonotonic())
290        .setXceiverCount(info.getXceiverCount())
291        .setAdminState(convert(info.getAdminState()))
292        .build();
293    return builder.build();
294  }
295
296  public static List<? extends HdfsProtos.DatanodeInfoProto> convert(
297      DatanodeInfo[] dnInfos) {
298    return convert(dnInfos, 0);
299  }
300
301  /**
302   * Copy from {@code dnInfos} to a target of list of same size starting at
303   * {@code startIdx}.
304   */
305  public static List<? extends HdfsProtos.DatanodeInfoProto> convert(
306      DatanodeInfo[] dnInfos, int startIdx) {
307    if (dnInfos == null)
308      return null;
309    ArrayList<HdfsProtos.DatanodeInfoProto> protos = Lists
310        .newArrayListWithCapacity(dnInfos.length);
311    for (int i = startIdx; i < dnInfos.length; i++) {
312      protos.add(convert(dnInfos[i]));
313    }
314    return protos;
315  }
316
317  public static List<Boolean> convert(boolean[] targetPinnings, int idx) {
318    List<Boolean> pinnings = new ArrayList<>();
319    if (targetPinnings == null) {
320      pinnings.add(Boolean.FALSE);
321    } else {
322      for (; idx < targetPinnings.length; ++idx) {
323        pinnings.add(targetPinnings[idx]);
324      }
325    }
326    return pinnings;
327  }
328
329  public static ExtendedBlock convert(ExtendedBlockProto eb) {
330    if (eb == null) return null;
331    return new ExtendedBlock( eb.getPoolId(), eb.getBlockId(), eb.getNumBytes(),
332        eb.getGenerationStamp());
333  }
334
335  public static DatanodeLocalInfo convert(DatanodeLocalInfoProto proto) {
336    return new DatanodeLocalInfo(proto.getSoftwareVersion(),
337        proto.getConfigVersion(), proto.getUptime());
338  }
339
340  static public DatanodeInfoProto convertDatanodeInfo(DatanodeInfo di) {
341    if (di == null) return null;
342    return convert(di);
343  }
344
345  public static StorageTypeProto convertStorageType(StorageType type) {
346    switch(type) {
347    case DISK:
348      return StorageTypeProto.DISK;
349    case SSD:
350      return StorageTypeProto.SSD;
351    case ARCHIVE:
352      return StorageTypeProto.ARCHIVE;
353    case RAM_DISK:
354      return StorageTypeProto.RAM_DISK;
355    default:
356      throw new IllegalStateException(
357          "BUG: StorageType not found, type=" + type);
358    }
359  }
360
361  public static StorageType convertStorageType(StorageTypeProto type) {
362    switch(type) {
363    case DISK:
364      return StorageType.DISK;
365    case SSD:
366      return StorageType.SSD;
367    case ARCHIVE:
368      return StorageType.ARCHIVE;
369    case RAM_DISK:
370      return StorageType.RAM_DISK;
371    default:
372      throw new IllegalStateException(
373          "BUG: StorageTypeProto not found, type=" + type);
374    }
375  }
376
377  public static List<StorageTypeProto> convertStorageTypes(
378      StorageType[] types) {
379    return convertStorageTypes(types, 0);
380  }
381
382  public static List<StorageTypeProto> convertStorageTypes(
383      StorageType[] types, int startIdx) {
384    if (types == null) {
385      return null;
386    }
387    final List<StorageTypeProto> protos = new ArrayList<>(
388        types.length);
389    for (int i = startIdx; i < types.length; ++i) {
390      protos.add(convertStorageType(types[i]));
391    }
392    return protos;
393  }
394
395  public static InputStream vintPrefixed(final InputStream input)
396      throws IOException {
397    final int firstByte = input.read();
398    if (firstByte == -1) {
399      throw new EOFException(
400          "Unexpected EOF while trying to read response from server");
401    }
402
403    int size = CodedInputStream.readRawVarint32(firstByte, input);
404    assert size >= 0;
405    return new LimitInputStream(input, size);
406  }
407
408  public static CipherOption convert(HdfsProtos.CipherOptionProto proto) {
409    if (proto != null) {
410      CipherSuite suite = null;
411      if (proto.getSuite() != null) {
412        suite = convert(proto.getSuite());
413      }
414      byte[] inKey = null;
415      if (proto.getInKey() != null) {
416        inKey = proto.getInKey().toByteArray();
417      }
418      byte[] inIv = null;
419      if (proto.getInIv() != null) {
420        inIv = proto.getInIv().toByteArray();
421      }
422      byte[] outKey = null;
423      if (proto.getOutKey() != null) {
424        outKey = proto.getOutKey().toByteArray();
425      }
426      byte[] outIv = null;
427      if (proto.getOutIv() != null) {
428        outIv = proto.getOutIv().toByteArray();
429      }
430      return new CipherOption(suite, inKey, inIv, outKey, outIv);
431    }
432    return null;
433  }
434
435  public static CipherSuite convert(HdfsProtos.CipherSuiteProto proto) {
436    switch (proto) {
437    case AES_CTR_NOPADDING:
438      return CipherSuite.AES_CTR_NOPADDING;
439    default:
440      // Set to UNKNOWN and stash the unknown enum value
441      CipherSuite suite = CipherSuite.UNKNOWN;
442      suite.setUnknownValue(proto.getNumber());
443      return suite;
444    }
445  }
446
447  public static HdfsProtos.CipherOptionProto convert(CipherOption option) {
448    if (option != null) {
449      HdfsProtos.CipherOptionProto.Builder builder =
450          HdfsProtos.CipherOptionProto.newBuilder();
451      if (option.getCipherSuite() != null) {
452        builder.setSuite(convert(option.getCipherSuite()));
453      }
454      if (option.getInKey() != null) {
455        builder.setInKey(getByteString(option.getInKey()));
456      }
457      if (option.getInIv() != null) {
458        builder.setInIv(getByteString(option.getInIv()));
459      }
460      if (option.getOutKey() != null) {
461        builder.setOutKey(getByteString(option.getOutKey()));
462      }
463      if (option.getOutIv() != null) {
464        builder.setOutIv(getByteString(option.getOutIv()));
465      }
466      return builder.build();
467    }
468    return null;
469  }
470
471  public static HdfsProtos.CipherSuiteProto convert(CipherSuite suite) {
472    switch (suite) {
473    case UNKNOWN:
474      return HdfsProtos.CipherSuiteProto.UNKNOWN;
475    case AES_CTR_NOPADDING:
476      return HdfsProtos.CipherSuiteProto.AES_CTR_NOPADDING;
477    default:
478      return null;
479    }
480  }
481
482  public static List<HdfsProtos.CipherOptionProto> convertCipherOptions(
483      List<CipherOption> options) {
484    if (options != null) {
485      List<HdfsProtos.CipherOptionProto> protos =
486          Lists.newArrayListWithCapacity(options.size());
487      for (CipherOption option : options) {
488        protos.add(convert(option));
489      }
490      return protos;
491    }
492    return null;
493  }
494
495  public static List<CipherOption> convertCipherOptionProtos(
496      List<HdfsProtos.CipherOptionProto> protos) {
497    if (protos != null) {
498      List<CipherOption> options =
499          Lists.newArrayListWithCapacity(protos.size());
500      for (HdfsProtos.CipherOptionProto proto : protos) {
501        options.add(convert(proto));
502      }
503      return options;
504    }
505    return null;
506  }
507
508  public static LocatedBlock convert(LocatedBlockProto proto) {
509    if (proto == null) return null;
510    List<DatanodeInfoProto> locs = proto.getLocsList();
511    DatanodeInfo[] targets = new DatanodeInfo[locs.size()];
512    for (int i = 0; i < locs.size(); i++) {
513      targets[i] = convert(locs.get(i));
514    }
515
516    final StorageType[] storageTypes = convertStorageTypes(
517        proto.getStorageTypesList(), locs.size());
518
519    final int storageIDsCount = proto.getStorageIDsCount();
520    final String[] storageIDs;
521    if (storageIDsCount == 0) {
522      storageIDs = null;
523    } else {
524      Preconditions.checkState(storageIDsCount == locs.size());
525      storageIDs = proto.getStorageIDsList()
526          .toArray(new String[storageIDsCount]);
527    }
528
529    // Set values from the isCached list, re-using references from loc
530    List<DatanodeInfo> cachedLocs = new ArrayList<>(locs.size());
531    List<Boolean> isCachedList = proto.getIsCachedList();
532    for (int i=0; i<isCachedList.size(); i++) {
533      if (isCachedList.get(i)) {
534        cachedLocs.add(targets[i]);
535      }
536    }
537
538    LocatedBlock lb = new LocatedBlock(convert(proto.getB()), targets,
539        storageIDs, storageTypes, proto.getOffset(), proto.getCorrupt(),
540        cachedLocs.toArray(new DatanodeInfo[0]));
541    lb.setBlockToken(convert(proto.getBlockToken()));
542
543    return lb;
544  }
545
546  static public DatanodeInfo convert(DatanodeInfoProto di) {
547    if (di == null) {
548      return null;
549    }
550    DatanodeInfo dinfo = new DatanodeInfo(convert(di.getId()),
551        di.hasLocation() ? di.getLocation() : null, di.getCapacity(),
552        di.getDfsUsed(), di.getRemaining(), di.getBlockPoolUsed(),
553        di.getCacheCapacity(), di.getCacheUsed(), di.getLastUpdate(),
554        di.getLastUpdateMonotonic(), di.getXceiverCount(),
555        convert(di.getAdminState()),
556        di.hasUpgradeDomain() ? di.getUpgradeDomain() : null);
557    if (di.hasNonDfsUsed()) {
558      dinfo.setNonDfsUsed(di.getNonDfsUsed());
559    } else {
560      // use the legacy way for older datanodes
561      long nonDFSUsed = di.getCapacity() - di.getDfsUsed() - di.getRemaining();
562      dinfo.setNonDfsUsed(nonDFSUsed < 0 ? 0 : nonDFSUsed);
563    }
564    return dinfo;
565  }
566
567  public static StorageType[] convertStorageTypes(
568      List<StorageTypeProto> storageTypesList, int expectedSize) {
569    final StorageType[] storageTypes = new StorageType[expectedSize];
570    if (storageTypesList.size() != expectedSize) {
571      // missing storage types
572      Preconditions.checkState(storageTypesList.isEmpty());
573      Arrays.fill(storageTypes, StorageType.DEFAULT);
574    } else {
575      for (int i = 0; i < storageTypes.length; ++i) {
576        storageTypes[i] = convertStorageType(storageTypesList.get(i));
577      }
578    }
579    return storageTypes;
580  }
581
582  public static Token<BlockTokenIdentifier> convert(
583      TokenProto blockToken) {
584    return new Token<>(blockToken.getIdentifier()
585        .toByteArray(), blockToken.getPassword().toByteArray(), new Text(
586        blockToken.getKind()), new Text(blockToken.getService()));
587  }
588
589  // DatanodeId
590  public static DatanodeID convert(DatanodeIDProto dn) {
591    return new DatanodeID(dn.getIpAddr(), dn.getHostName(),
592        dn.getDatanodeUuid(), dn.getXferPort(), dn.getInfoPort(),
593        dn.hasInfoSecurePort() ? dn.getInfoSecurePort() : 0, dn.getIpcPort());
594  }
595
596  public static AdminStates convert(AdminState adminState) {
597    switch(adminState) {
598    case DECOMMISSION_INPROGRESS:
599      return AdminStates.DECOMMISSION_INPROGRESS;
600    case DECOMMISSIONED:
601      return AdminStates.DECOMMISSIONED;
602    case NORMAL:
603    default:
604      return AdminStates.NORMAL;
605    }
606  }
607
608  // LocatedBlocks
609  public static LocatedBlocks convert(LocatedBlocksProto lb) {
610    return new LocatedBlocks(
611        lb.getFileLength(), lb.getUnderConstruction(),
612        convertLocatedBlock(lb.getBlocksList()),
613        lb.hasLastBlock() ? convert(lb.getLastBlock()) : null,
614        lb.getIsLastBlockComplete(),
615        lb.hasFileEncryptionInfo() ? convert(lb.getFileEncryptionInfo()) :
616            null);
617  }
618
619  public static BlockStoragePolicy[] convertStoragePolicies(
620      List<BlockStoragePolicyProto> policyProtos) {
621    if (policyProtos == null || policyProtos.size() == 0) {
622      return new BlockStoragePolicy[0];
623    }
624    BlockStoragePolicy[] policies = new BlockStoragePolicy[policyProtos.size()];
625    int i = 0;
626    for (BlockStoragePolicyProto proto : policyProtos) {
627      policies[i++] = convert(proto);
628    }
629    return policies;
630  }
631
632  public static EventBatchList convert(GetEditsFromTxidResponseProto resp)
633      throws IOException {
634    final InotifyProtos.EventsListProto list = resp.getEventsList();
635    final long firstTxid = list.getFirstTxid();
636    final long lastTxid = list.getLastTxid();
637
638    List<EventBatch> batches = Lists.newArrayList();
639    if (list.getEventsList().size() > 0) {
640      throw new IOException("Can't handle old inotify server response.");
641    }
642    for (InotifyProtos.EventBatchProto bp : list.getBatchList()) {
643      long txid = bp.getTxid();
644      if ((txid != -1) && ((txid < firstTxid) || (txid > lastTxid))) {
645        throw new IOException("Error converting TxidResponseProto: got a " +
646            "transaction id " + txid + " that was outside the range of [" +
647            firstTxid + ", " + lastTxid + "].");
648      }
649      List<Event> events = Lists.newArrayList();
650      for (InotifyProtos.EventProto p : bp.getEventsList()) {
651        switch (p.getType()) {
652        case EVENT_CLOSE:
653          InotifyProtos.CloseEventProto close =
654              InotifyProtos.CloseEventProto.parseFrom(p.getContents());
655          events.add(new Event.CloseEvent(close.getPath(),
656              close.getFileSize(), close.getTimestamp()));
657          break;
658        case EVENT_CREATE:
659          InotifyProtos.CreateEventProto create =
660              InotifyProtos.CreateEventProto.parseFrom(p.getContents());
661          events.add(new Event.CreateEvent.Builder()
662              .iNodeType(createTypeConvert(create.getType()))
663              .path(create.getPath())
664              .ctime(create.getCtime())
665              .ownerName(create.getOwnerName())
666              .groupName(create.getGroupName())
667              .perms(convert(create.getPerms()))
668              .replication(create.getReplication())
669              .symlinkTarget(create.getSymlinkTarget().isEmpty() ? null :
670                  create.getSymlinkTarget())
671              .defaultBlockSize(create.getDefaultBlockSize())
672              .overwrite(create.getOverwrite()).build());
673          break;
674        case EVENT_METADATA:
675          InotifyProtos.MetadataUpdateEventProto meta =
676              InotifyProtos.MetadataUpdateEventProto.parseFrom(p.getContents());
677          events.add(new Event.MetadataUpdateEvent.Builder()
678              .path(meta.getPath())
679              .metadataType(metadataUpdateTypeConvert(meta.getType()))
680              .mtime(meta.getMtime())
681              .atime(meta.getAtime())
682              .replication(meta.getReplication())
683              .ownerName(
684                  meta.getOwnerName().isEmpty() ? null : meta.getOwnerName())
685              .groupName(
686                  meta.getGroupName().isEmpty() ? null : meta.getGroupName())
687              .perms(meta.hasPerms() ? convert(meta.getPerms()) : null)
688              .acls(meta.getAclsList().isEmpty() ? null : convertAclEntry(
689                  meta.getAclsList()))
690              .xAttrs(meta.getXAttrsList().isEmpty() ? null : convertXAttrs(
691                  meta.getXAttrsList()))
692              .xAttrsRemoved(meta.getXAttrsRemoved())
693              .build());
694          break;
695        case EVENT_RENAME:
696          InotifyProtos.RenameEventProto rename =
697              InotifyProtos.RenameEventProto.parseFrom(p.getContents());
698          events.add(new Event.RenameEvent.Builder()
699              .srcPath(rename.getSrcPath())
700              .dstPath(rename.getDestPath())
701              .timestamp(rename.getTimestamp())
702              .build());
703          break;
704        case EVENT_APPEND:
705          InotifyProtos.AppendEventProto append =
706              InotifyProtos.AppendEventProto.parseFrom(p.getContents());
707          events.add(new Event.AppendEvent.Builder().path(append.getPath())
708              .newBlock(append.hasNewBlock() && append.getNewBlock())
709              .build());
710          break;
711        case EVENT_UNLINK:
712          InotifyProtos.UnlinkEventProto unlink =
713              InotifyProtos.UnlinkEventProto.parseFrom(p.getContents());
714          events.add(new Event.UnlinkEvent.Builder()
715              .path(unlink.getPath())
716              .timestamp(unlink.getTimestamp())
717              .build());
718          break;
719        case EVENT_TRUNCATE:
720          InotifyProtos.TruncateEventProto truncate =
721              InotifyProtos.TruncateEventProto.parseFrom(p.getContents());
722          events.add(new Event.TruncateEvent(truncate.getPath(),
723              truncate.getFileSize(), truncate.getTimestamp()));
724          break;
725        default:
726          throw new RuntimeException("Unexpected inotify event type: " +
727              p.getType());
728        }
729      }
730      batches.add(new EventBatch(txid, events.toArray(new Event[0])));
731    }
732    return new EventBatchList(batches, resp.getEventsList().getFirstTxid(),
733        resp.getEventsList().getLastTxid(), resp.getEventsList().getSyncTxid());
734  }
735
736  // Located Block Arrays and Lists
737  public static LocatedBlockProto[] convertLocatedBlock(LocatedBlock[] lb) {
738    if (lb == null) return null;
739    return convertLocatedBlock2(Arrays.asList(lb)).toArray(
740        new LocatedBlockProto[lb.length]);
741  }
742
743  public static List<LocatedBlockProto> convertLocatedBlock2(List<LocatedBlock> lb) {
744    if (lb == null) return null;
745    final int len = lb.size();
746    List<LocatedBlockProto> result = new ArrayList<>(len);
747    for (int i = 0; i < len; ++i) {
748      result.add(convert(lb.get(i)));
749    }
750    return result;
751  }
752
753  public static LocatedBlockProto convert(LocatedBlock b) {
754    if (b == null) return null;
755    Builder builder = LocatedBlockProto.newBuilder();
756    DatanodeInfo[] locs = b.getLocations();
757    List<DatanodeInfo> cachedLocs =
758        Lists.newLinkedList(Arrays.asList(b.getCachedLocations()));
759    for (int i = 0; i < locs.length; i++) {
760      DatanodeInfo loc = locs[i];
761      builder.addLocs(i, convert(loc));
762      boolean locIsCached = cachedLocs.contains(loc);
763      builder.addIsCached(locIsCached);
764      if (locIsCached) {
765        cachedLocs.remove(loc);
766      }
767    }
768    Preconditions.checkArgument(cachedLocs.size() == 0,
769        "Found additional cached replica locations that are not in the set of"
770        + " storage-backed locations!");
771
772    StorageType[] storageTypes = b.getStorageTypes();
773    if (storageTypes != null) {
774      for (int i = 0; i < storageTypes.length; ++i) {
775        builder.addStorageTypes(convertStorageType(storageTypes[i]));
776      }
777    }
778    final String[] storageIDs = b.getStorageIDs();
779    if (storageIDs != null) {
780      builder.addAllStorageIDs(Arrays.asList(storageIDs));
781    }
782
783    return builder.setB(convert(b.getBlock()))
784        .setBlockToken(convert(b.getBlockToken()))
785        .setCorrupt(b.isCorrupt()).setOffset(b.getStartOffset()).build();
786  }
787
788  public static BlockStoragePolicy convert(BlockStoragePolicyProto proto) {
789    List<StorageTypeProto> cList = proto.getCreationPolicy()
790        .getStorageTypesList();
791    StorageType[] creationTypes = convertStorageTypes(cList, cList.size());
792    List<StorageTypeProto> cfList = proto.hasCreationFallbackPolicy() ? proto
793        .getCreationFallbackPolicy().getStorageTypesList() : null;
794    StorageType[] creationFallbackTypes = cfList == null ? StorageType
795        .EMPTY_ARRAY : convertStorageTypes(cfList, cfList.size());
796    List<StorageTypeProto> rfList = proto.hasReplicationFallbackPolicy() ?
797        proto.getReplicationFallbackPolicy().getStorageTypesList() : null;
798    StorageType[] replicationFallbackTypes = rfList == null ? StorageType
799        .EMPTY_ARRAY : convertStorageTypes(rfList, rfList.size());
800    return new BlockStoragePolicy((byte) proto.getPolicyId(), proto.getName(),
801        creationTypes, creationFallbackTypes, replicationFallbackTypes);
802  }
803
804  public static FsActionProto convert(FsAction v) {
805    return FsActionProto.valueOf(v != null ? v.ordinal() : 0);
806  }
807
808  public static XAttrProto convertXAttrProto(XAttr a) {
809    XAttrProto.Builder builder = XAttrProto.newBuilder();
810    builder.setNamespace(convert(a.getNameSpace()));
811    if (a.getName() != null) {
812      builder.setName(a.getName());
813    }
814    if (a.getValue() != null) {
815      builder.setValue(getByteString(a.getValue()));
816    }
817    return builder.build();
818  }
819
820  public static List<XAttr> convert(ListXAttrsResponseProto a) {
821    final List<XAttrProto> xAttrs = a.getXAttrsList();
822    return convertXAttrs(xAttrs);
823  }
824
825  public static List<XAttr> convert(GetXAttrsResponseProto a) {
826    List<XAttrProto> xAttrs = a.getXAttrsList();
827    return convertXAttrs(xAttrs);
828  }
829
830  public static List<XAttr> convertXAttrs(List<XAttrProto> xAttrSpec) {
831    ArrayList<XAttr> xAttrs = Lists.newArrayListWithCapacity(xAttrSpec.size());
832    for (XAttrProto a : xAttrSpec) {
833      XAttr.Builder builder = new XAttr.Builder();
834      builder.setNameSpace(convert(a.getNamespace()));
835      if (a.hasName()) {
836        builder.setName(a.getName());
837      }
838      if (a.hasValue()) {
839        builder.setValue(a.getValue().toByteArray());
840      }
841      xAttrs.add(builder.build());
842    }
843    return xAttrs;
844  }
845
846  static XAttrNamespaceProto convert(XAttr.NameSpace v) {
847    return XAttrNamespaceProto.valueOf(v.ordinal());
848  }
849
850  static XAttr.NameSpace convert(XAttrNamespaceProto v) {
851    return castEnum(v, XATTR_NAMESPACE_VALUES);
852  }
853
854  static <T extends Enum<T>, U extends Enum<U>> U castEnum(T from, U[] to) {
855    return to[from.ordinal()];
856  }
857
858  static InotifyProtos.MetadataUpdateType metadataUpdateTypeConvert(
859      Event.MetadataUpdateEvent.MetadataType type) {
860    switch (type) {
861    case TIMES:
862      return InotifyProtos.MetadataUpdateType.META_TYPE_TIMES;
863    case REPLICATION:
864      return InotifyProtos.MetadataUpdateType.META_TYPE_REPLICATION;
865    case OWNER:
866      return InotifyProtos.MetadataUpdateType.META_TYPE_OWNER;
867    case PERMS:
868      return InotifyProtos.MetadataUpdateType.META_TYPE_PERMS;
869    case ACLS:
870      return InotifyProtos.MetadataUpdateType.META_TYPE_ACLS;
871    case XATTRS:
872      return InotifyProtos.MetadataUpdateType.META_TYPE_XATTRS;
873    default:
874      return null;
875    }
876  }
877
878  private static Event.MetadataUpdateEvent.MetadataType metadataUpdateTypeConvert(
879      InotifyProtos.MetadataUpdateType type) {
880    switch (type) {
881    case META_TYPE_TIMES:
882      return Event.MetadataUpdateEvent.MetadataType.TIMES;
883    case META_TYPE_REPLICATION:
884      return Event.MetadataUpdateEvent.MetadataType.REPLICATION;
885    case META_TYPE_OWNER:
886      return Event.MetadataUpdateEvent.MetadataType.OWNER;
887    case META_TYPE_PERMS:
888      return Event.MetadataUpdateEvent.MetadataType.PERMS;
889    case META_TYPE_ACLS:
890      return Event.MetadataUpdateEvent.MetadataType.ACLS;
891    case META_TYPE_XATTRS:
892      return Event.MetadataUpdateEvent.MetadataType.XATTRS;
893    default:
894      return null;
895    }
896  }
897
898  static InotifyProtos.INodeType createTypeConvert(Event.CreateEvent.INodeType
899      type) {
900    switch (type) {
901    case DIRECTORY:
902      return InotifyProtos.INodeType.I_TYPE_DIRECTORY;
903    case FILE:
904      return InotifyProtos.INodeType.I_TYPE_FILE;
905    case SYMLINK:
906      return InotifyProtos.INodeType.I_TYPE_SYMLINK;
907    default:
908      return null;
909    }
910  }
911
912  public static List<LocatedBlock> convertLocatedBlock(
913      List<LocatedBlockProto> lb) {
914    if (lb == null) return null;
915    final int len = lb.size();
916    List<LocatedBlock> result = new ArrayList<>(len);
917    for (int i = 0; i < len; ++i) {
918      result.add(convert(lb.get(i)));
919    }
920    return result;
921  }
922
923  public static List<AclEntry> convertAclEntry(List<AclEntryProto> aclSpec) {
924    ArrayList<AclEntry> r = Lists.newArrayListWithCapacity(aclSpec.size());
925    for (AclEntryProto e : aclSpec) {
926      AclEntry.Builder builder = new AclEntry.Builder();
927      builder.setType(convert(e.getType()));
928      builder.setScope(convert(e.getScope()));
929      builder.setPermission(convert(e.getPermissions()));
930      if (e.hasName()) {
931        builder.setName(e.getName());
932      }
933      r.add(builder.build());
934    }
935    return r;
936  }
937
938  static AclEntryScopeProto convert(AclEntryScope v) {
939    return AclEntryScopeProto.valueOf(v.ordinal());
940  }
941
942  private static AclEntryScope convert(AclEntryScopeProto v) {
943    return castEnum(v, ACL_ENTRY_SCOPE_VALUES);
944  }
945
946  static AclEntryTypeProto convert(AclEntryType e) {
947    return AclEntryTypeProto.valueOf(e.ordinal());
948  }
949
950  private static AclEntryType convert(AclEntryTypeProto v) {
951    return castEnum(v, ACL_ENTRY_TYPE_VALUES);
952  }
953
954  public static FsAction convert(FsActionProto v) {
955    return castEnum(v, FSACTION_VALUES);
956  }
957
958  public static FsPermission convert(FsPermissionProto p) {
959    return new FsPermissionExtension((short)p.getPerm());
960  }
961
962  private static Event.CreateEvent.INodeType createTypeConvert(
963      InotifyProtos.INodeType type) {
964    switch (type) {
965    case I_TYPE_DIRECTORY:
966      return Event.CreateEvent.INodeType.DIRECTORY;
967    case I_TYPE_FILE:
968      return Event.CreateEvent.INodeType.FILE;
969    case I_TYPE_SYMLINK:
970      return Event.CreateEvent.INodeType.SYMLINK;
971    default:
972      return null;
973    }
974  }
975
976  public static HdfsProtos.FileEncryptionInfoProto convert(
977      FileEncryptionInfo info) {
978    if (info == null) {
979      return null;
980    }
981    return HdfsProtos.FileEncryptionInfoProto.newBuilder()
982        .setSuite(convert(info.getCipherSuite()))
983        .setCryptoProtocolVersion(convert(info.getCryptoProtocolVersion()))
984        .setKey(getByteString(info.getEncryptedDataEncryptionKey()))
985        .setIv(getByteString(info.getIV()))
986        .setEzKeyVersionName(info.getEzKeyVersionName())
987        .setKeyName(info.getKeyName())
988        .build();
989  }
990
991  public static CryptoProtocolVersionProto convert(CryptoProtocolVersion
992      version) {
993    switch(version) {
994    case UNKNOWN:
995      return CryptoProtocolVersionProto.UNKNOWN_PROTOCOL_VERSION;
996    case ENCRYPTION_ZONES:
997      return CryptoProtocolVersionProto.ENCRYPTION_ZONES;
998    default:
999      return null;
1000    }
1001  }
1002
1003  public static FileEncryptionInfo convert(
1004      HdfsProtos.FileEncryptionInfoProto proto) {
1005    if (proto == null) {
1006      return null;
1007    }
1008    CipherSuite suite = convert(proto.getSuite());
1009    CryptoProtocolVersion version = convert(proto.getCryptoProtocolVersion());
1010    byte[] key = proto.getKey().toByteArray();
1011    byte[] iv = proto.getIv().toByteArray();
1012    String ezKeyVersionName = proto.getEzKeyVersionName();
1013    String keyName = proto.getKeyName();
1014    return new FileEncryptionInfo(suite, version, key, iv, keyName,
1015        ezKeyVersionName);
1016  }
1017
1018  public static CryptoProtocolVersion convert(CryptoProtocolVersionProto
1019      proto) {
1020    switch(proto) {
1021    case ENCRYPTION_ZONES:
1022      return CryptoProtocolVersion.ENCRYPTION_ZONES;
1023    default:
1024      // Set to UNKNOWN and stash the unknown enum value
1025      CryptoProtocolVersion version = CryptoProtocolVersion.UNKNOWN;
1026      version.setUnknownValue(proto.getNumber());
1027      return version;
1028    }
1029  }
1030
1031  public static List<XAttrProto> convertXAttrProto(
1032      List<XAttr> xAttrSpec) {
1033    if (xAttrSpec == null) {
1034      return Lists.newArrayListWithCapacity(0);
1035    }
1036    ArrayList<XAttrProto> xAttrs = Lists.newArrayListWithCapacity(
1037        xAttrSpec.size());
1038    for (XAttr a : xAttrSpec) {
1039      XAttrProto.Builder builder = XAttrProto.newBuilder();
1040      builder.setNamespace(convert(a.getNameSpace()));
1041      if (a.getName() != null) {
1042        builder.setName(a.getName());
1043      }
1044      if (a.getValue() != null) {
1045        builder.setValue(getByteString(a.getValue()));
1046      }
1047      xAttrs.add(builder.build());
1048    }
1049    return xAttrs;
1050  }
1051
1052  /**
1053   * The flag field in PB is a bitmask whose values are the same a the
1054   * emum values of XAttrSetFlag
1055   */
1056  public static int convert(EnumSet<XAttrSetFlag> flag) {
1057    int value = 0;
1058    if (flag.contains(XAttrSetFlag.CREATE)) {
1059      value |= XAttrSetFlagProto.XATTR_CREATE.getNumber();
1060    }
1061    if (flag.contains(XAttrSetFlag.REPLACE)) {
1062      value |= XAttrSetFlagProto.XATTR_REPLACE.getNumber();
1063    }
1064    return value;
1065  }
1066
1067  public static EncryptionZone convert(EncryptionZoneProto proto) {
1068    return new EncryptionZone(proto.getId(), proto.getPath(),
1069        convert(proto.getSuite()), convert(proto.getCryptoProtocolVersion()),
1070        proto.getKeyName());
1071  }
1072
1073  public static AclStatus convert(GetAclStatusResponseProto e) {
1074    AclStatusProto r = e.getResult();
1075    AclStatus.Builder builder = new AclStatus.Builder();
1076    builder.owner(r.getOwner()).group(r.getGroup()).stickyBit(r.getSticky())
1077        .addEntries(convertAclEntry(r.getEntriesList()));
1078    if (r.hasPermission()) {
1079      builder.setPermission(convert(r.getPermission()));
1080    }
1081    return builder.build();
1082  }
1083
1084  public static List<AclEntryProto> convertAclEntryProto(
1085      List<AclEntry> aclSpec) {
1086    ArrayList<AclEntryProto> r = Lists.newArrayListWithCapacity(aclSpec.size());
1087    for (AclEntry e : aclSpec) {
1088      AclEntryProto.Builder builder = AclEntryProto.newBuilder();
1089      builder.setType(convert(e.getType()));
1090      builder.setScope(convert(e.getScope()));
1091      builder.setPermissions(convert(e.getPermission()));
1092      if (e.getName() != null) {
1093        builder.setName(e.getName());
1094      }
1095      r.add(builder.build());
1096    }
1097    return r;
1098  }
1099
1100  public static CachePoolEntry convert(CachePoolEntryProto proto) {
1101    CachePoolInfo info = convert(proto.getInfo());
1102    CachePoolStats stats = convert(proto.getStats());
1103    return new CachePoolEntry(info, stats);
1104  }
1105
1106  public static CachePoolInfo convert (CachePoolInfoProto proto) {
1107    // Pool name is a required field, the rest are optional
1108    String poolName = checkNotNull(proto.getPoolName());
1109    CachePoolInfo info = new CachePoolInfo(poolName);
1110    if (proto.hasOwnerName()) {
1111      info.setOwnerName(proto.getOwnerName());
1112    }
1113    if (proto.hasGroupName()) {
1114      info.setGroupName(proto.getGroupName());
1115    }
1116    if (proto.hasMode()) {
1117      info.setMode(new FsPermission((short)proto.getMode()));
1118    }
1119    if (proto.hasLimit())  {
1120      info.setLimit(proto.getLimit());
1121    }
1122    if (proto.hasMaxRelativeExpiry()) {
1123      info.setMaxRelativeExpiryMs(proto.getMaxRelativeExpiry());
1124    }
1125    return info;
1126  }
1127
1128  public static CachePoolStats convert (CachePoolStatsProto proto) {
1129    CachePoolStats.Builder builder = new CachePoolStats.Builder();
1130    builder.setBytesNeeded(proto.getBytesNeeded());
1131    builder.setBytesCached(proto.getBytesCached());
1132    builder.setBytesOverlimit(proto.getBytesOverlimit());
1133    builder.setFilesNeeded(proto.getFilesNeeded());
1134    builder.setFilesCached(proto.getFilesCached());
1135    return builder.build();
1136  }
1137
1138  public static CachePoolInfoProto convert(CachePoolInfo info) {
1139    CachePoolInfoProto.Builder builder = CachePoolInfoProto.newBuilder();
1140    builder.setPoolName(info.getPoolName());
1141    if (info.getOwnerName() != null) {
1142      builder.setOwnerName(info.getOwnerName());
1143    }
1144    if (info.getGroupName() != null) {
1145      builder.setGroupName(info.getGroupName());
1146    }
1147    if (info.getMode() != null) {
1148      builder.setMode(info.getMode().toShort());
1149    }
1150    if (info.getLimit() != null) {
1151      builder.setLimit(info.getLimit());
1152    }
1153    if (info.getMaxRelativeExpiryMs() != null) {
1154      builder.setMaxRelativeExpiry(info.getMaxRelativeExpiryMs());
1155    }
1156    return builder.build();
1157  }
1158
1159  public static CacheDirectiveInfoProto convert(CacheDirectiveInfo info) {
1160    CacheDirectiveInfoProto.Builder builder =
1161        CacheDirectiveInfoProto.newBuilder();
1162    if (info.getId() != null) {
1163      builder.setId(info.getId());
1164    }
1165    if (info.getPath() != null) {
1166      builder.setPath(info.getPath().toUri().getPath());
1167    }
1168    if (info.getReplication() != null) {
1169      builder.setReplication(info.getReplication());
1170    }
1171    if (info.getPool() != null) {
1172      builder.setPool(info.getPool());
1173    }
1174    if (info.getExpiration() != null) {
1175      builder.setExpiration(convert(info.getExpiration()));
1176    }
1177    return builder.build();
1178  }
1179
1180  public static CacheDirectiveInfoExpirationProto convert(
1181      CacheDirectiveInfo.Expiration expiration) {
1182    return CacheDirectiveInfoExpirationProto.newBuilder()
1183        .setIsRelative(expiration.isRelative())
1184        .setMillis(expiration.getMillis())
1185        .build();
1186  }
1187
1188  public static CacheDirectiveEntry convert(CacheDirectiveEntryProto proto) {
1189    CacheDirectiveInfo info = convert(proto.getInfo());
1190    CacheDirectiveStats stats = convert(proto.getStats());
1191    return new CacheDirectiveEntry(info, stats);
1192  }
1193
1194  public static CacheDirectiveStats convert(CacheDirectiveStatsProto proto) {
1195    CacheDirectiveStats.Builder builder = new CacheDirectiveStats.Builder();
1196    builder.setBytesNeeded(proto.getBytesNeeded());
1197    builder.setBytesCached(proto.getBytesCached());
1198    builder.setFilesNeeded(proto.getFilesNeeded());
1199    builder.setFilesCached(proto.getFilesCached());
1200    builder.setHasExpired(proto.getHasExpired());
1201    return builder.build();
1202  }
1203
1204  public static CacheDirectiveInfo convert(CacheDirectiveInfoProto proto) {
1205    CacheDirectiveInfo.Builder builder = new CacheDirectiveInfo.Builder();
1206    if (proto.hasId()) {
1207      builder.setId(proto.getId());
1208    }
1209    if (proto.hasPath()) {
1210      builder.setPath(new Path(proto.getPath()));
1211    }
1212    if (proto.hasReplication()) {
1213      builder.setReplication(Shorts.checkedCast(
1214          proto.getReplication()));
1215    }
1216    if (proto.hasPool()) {
1217      builder.setPool(proto.getPool());
1218    }
1219    if (proto.hasExpiration()) {
1220      builder.setExpiration(convert(proto.getExpiration()));
1221    }
1222    return builder.build();
1223  }
1224
1225  public static CacheDirectiveInfo.Expiration convert(
1226      CacheDirectiveInfoExpirationProto proto) {
1227    if (proto.getIsRelative()) {
1228      return CacheDirectiveInfo.Expiration.newRelative(proto.getMillis());
1229    }
1230    return CacheDirectiveInfo.Expiration.newAbsolute(proto.getMillis());
1231  }
1232
1233  public static int convertCacheFlags(EnumSet<CacheFlag> flags) {
1234    int value = 0;
1235    if (flags.contains(CacheFlag.FORCE)) {
1236      value |= CacheFlagProto.FORCE.getNumber();
1237    }
1238    return value;
1239  }
1240
1241  public static SnapshotDiffReport convert(
1242      SnapshotDiffReportProto reportProto) {
1243    if (reportProto == null) {
1244      return null;
1245    }
1246    String snapshotDir = reportProto.getSnapshotRoot();
1247    String fromSnapshot = reportProto.getFromSnapshot();
1248    String toSnapshot = reportProto.getToSnapshot();
1249    List<SnapshotDiffReportEntryProto> list = reportProto
1250        .getDiffReportEntriesList();
1251    List<DiffReportEntry> entries = new ArrayList<>();
1252    for (SnapshotDiffReportEntryProto entryProto : list) {
1253      DiffReportEntry entry = convert(entryProto);
1254      if (entry != null)
1255        entries.add(entry);
1256    }
1257    return new SnapshotDiffReport(snapshotDir, fromSnapshot, toSnapshot,
1258        entries);
1259  }
1260
1261  public static DiffReportEntry convert(SnapshotDiffReportEntryProto entry) {
1262    if (entry == null) {
1263      return null;
1264    }
1265    DiffType type = DiffType.getTypeFromLabel(entry
1266        .getModificationLabel());
1267    return type == null ? null : new DiffReportEntry(type, entry.getFullpath()
1268        .toByteArray(), entry.hasTargetPath() ? entry.getTargetPath()
1269        .toByteArray() : null);
1270  }
1271
1272  public static SnapshottableDirectoryStatus[] convert(
1273      SnapshottableDirectoryListingProto sdlp) {
1274    if (sdlp == null)
1275      return null;
1276    List<SnapshottableDirectoryStatusProto> list = sdlp
1277        .getSnapshottableDirListingList();
1278    if (list.isEmpty()) {
1279      return new SnapshottableDirectoryStatus[0];
1280    } else {
1281      SnapshottableDirectoryStatus[] result =
1282          new SnapshottableDirectoryStatus[list.size()];
1283      for (int i = 0; i < list.size(); i++) {
1284        result[i] = convert(list.get(i));
1285      }
1286      return result;
1287    }
1288  }
1289
1290  public static SnapshottableDirectoryStatus convert(
1291      SnapshottableDirectoryStatusProto sdirStatusProto) {
1292    if (sdirStatusProto == null) {
1293      return null;
1294    }
1295    final HdfsFileStatusProto status = sdirStatusProto.getDirStatus();
1296    return new SnapshottableDirectoryStatus(
1297        status.getModificationTime(),
1298        status.getAccessTime(),
1299        convert(status.getPermission()),
1300        status.getOwner(),
1301        status.getGroup(),
1302        status.getPath().toByteArray(),
1303        status.getFileId(),
1304        status.getChildrenNum(),
1305        sdirStatusProto.getSnapshotNumber(),
1306        sdirStatusProto.getSnapshotQuota(),
1307        sdirStatusProto.getParentFullpath().toByteArray());
1308  }
1309
1310  // DataEncryptionKey
1311  public static DataEncryptionKey convert(DataEncryptionKeyProto bet) {
1312    String encryptionAlgorithm = bet.getEncryptionAlgorithm();
1313    return new DataEncryptionKey(bet.getKeyId(),
1314        bet.getBlockPoolId(),
1315        bet.getNonce().toByteArray(),
1316        bet.getEncryptionKey().toByteArray(),
1317        bet.getExpiryDate(),
1318        encryptionAlgorithm.isEmpty() ? null : encryptionAlgorithm);
1319  }
1320
1321  public static Token<DelegationTokenIdentifier> convertDelegationToken(
1322      TokenProto blockToken) {
1323    return new Token<>(blockToken.getIdentifier()
1324        .toByteArray(), blockToken.getPassword().toByteArray(), new Text(
1325        blockToken.getKind()), new Text(blockToken.getService()));
1326  }
1327
1328  // Arrays of DatanodeId
1329  public static DatanodeIDProto[] convert(DatanodeID[] did) {
1330    if (did == null)
1331      return null;
1332    final int len = did.length;
1333    DatanodeIDProto[] result = new DatanodeIDProto[len];
1334    for (int i = 0; i < len; ++i) {
1335      result[i] = convert(did[i]);
1336    }
1337    return result;
1338  }
1339
1340  public static FsPermissionProto convert(FsPermission p) {
1341    return FsPermissionProto.newBuilder().setPerm(p.toExtendedShort()).build();
1342  }
1343
1344  public static HdfsFileStatus convert(HdfsFileStatusProto fs) {
1345    if (fs == null)
1346      return null;
1347    return new HdfsLocatedFileStatus(
1348        fs.getLength(), fs.getFileType().equals(FileType.IS_DIR),
1349        fs.getBlockReplication(), fs.getBlocksize(),
1350        fs.getModificationTime(), fs.getAccessTime(),
1351        convert(fs.getPermission()), fs.getOwner(), fs.getGroup(),
1352        fs.getFileType().equals(FileType.IS_SYMLINK) ?
1353            fs.getSymlink().toByteArray() : null,
1354        fs.getPath().toByteArray(),
1355        fs.hasFileId()? fs.getFileId(): HdfsConstants.GRANDFATHER_INODE_ID,
1356        fs.hasLocations() ? convert(fs.getLocations()) : null,
1357        fs.hasChildrenNum() ? fs.getChildrenNum() : -1,
1358        fs.hasFileEncryptionInfo() ? convert(fs.getFileEncryptionInfo()) : null,
1359        fs.hasStoragePolicy() ? (byte) fs.getStoragePolicy()
1360            : HdfsConstants.BLOCK_STORAGE_POLICY_ID_UNSPECIFIED);
1361  }
1362
1363  public static CorruptFileBlocks convert(CorruptFileBlocksProto c) {
1364    if (c == null)
1365      return null;
1366    List<String> fileList = c.getFilesList();
1367    return new CorruptFileBlocks(fileList.toArray(new String[fileList.size()]),
1368        c.getCookie());
1369  }
1370
1371  public static ContentSummary convert(ContentSummaryProto cs) {
1372    if (cs == null) return null;
1373    ContentSummary.Builder builder = new ContentSummary.Builder();
1374    builder.length(cs.getLength()).
1375        fileCount(cs.getFileCount()).
1376        directoryCount(cs.getDirectoryCount()).
1377        snapshotLength(cs.getSnapshotLength()).
1378        snapshotFileCount(cs.getSnapshotFileCount()).
1379        snapshotDirectoryCount(cs.getSnapshotDirectoryCount()).
1380        snapshotSpaceConsumed(cs.getSnapshotSpaceConsumed()).
1381        quota(cs.getQuota()).
1382        spaceConsumed(cs.getSpaceConsumed()).
1383        spaceQuota(cs.getSpaceQuota());
1384    if (cs.hasTypeQuotaInfos()) {
1385      addStorageTypes(cs.getTypeQuotaInfos(), builder);
1386    }
1387    return builder.build();
1388  }
1389
1390  public static QuotaUsage convert(QuotaUsageProto qu) {
1391    if (qu == null) {
1392      return null;
1393    }
1394    QuotaUsage.Builder builder = new QuotaUsage.Builder();
1395    builder.fileAndDirectoryCount(qu.getFileAndDirectoryCount()).
1396        quota(qu.getQuota()).
1397        spaceConsumed(qu.getSpaceConsumed()).
1398        spaceQuota(qu.getSpaceQuota());
1399    if (qu.hasTypeQuotaInfos()) {
1400      addStorageTypes(qu.getTypeQuotaInfos(), builder);
1401    }
1402    return builder.build();
1403  }
1404
1405  public static QuotaUsageProto convert(QuotaUsage qu) {
1406    if (qu == null) {
1407      return null;
1408    }
1409    QuotaUsageProto.Builder builder = QuotaUsageProto.newBuilder();
1410    builder.setFileAndDirectoryCount(qu.getFileAndDirectoryCount()).
1411        setQuota(qu.getQuota()).
1412        setSpaceConsumed(qu.getSpaceConsumed()).
1413        setSpaceQuota(qu.getSpaceQuota());
1414    if (qu.isTypeQuotaSet() || qu.isTypeConsumedAvailable()) {
1415      builder.setTypeQuotaInfos(getBuilder(qu));
1416    }
1417    return builder.build();
1418  }
1419
1420  public static RollingUpgradeActionProto convert(RollingUpgradeAction a) {
1421    switch (a) {
1422    case QUERY:
1423      return RollingUpgradeActionProto.QUERY;
1424    case PREPARE:
1425      return RollingUpgradeActionProto.START;
1426    case FINALIZE:
1427      return RollingUpgradeActionProto.FINALIZE;
1428    default:
1429      throw new IllegalArgumentException("Unexpected value: " + a);
1430    }
1431  }
1432
1433  public static RollingUpgradeInfo convert(RollingUpgradeInfoProto proto) {
1434    RollingUpgradeStatusProto status = proto.getStatus();
1435    return new RollingUpgradeInfo(status.getBlockPoolId(),
1436        proto.getCreatedRollbackImages(),
1437        proto.getStartTime(), proto.getFinalizeTime());
1438  }
1439
1440  public static DatanodeStorageReport[] convertDatanodeStorageReports(
1441      List<DatanodeStorageReportProto> protos) {
1442    final DatanodeStorageReport[] reports
1443        = new DatanodeStorageReport[protos.size()];
1444    for(int i = 0; i < reports.length; i++) {
1445      reports[i] = convertDatanodeStorageReport(protos.get(i));
1446    }
1447    return reports;
1448  }
1449
1450  public static DatanodeStorageReport convertDatanodeStorageReport(
1451      DatanodeStorageReportProto proto) {
1452    return new DatanodeStorageReport(
1453        convert(proto.getDatanodeInfo()),
1454        convertStorageReports(proto.getStorageReportsList()));
1455  }
1456
1457  public static StorageReport[] convertStorageReports(
1458      List<StorageReportProto> list) {
1459    final StorageReport[] report = new StorageReport[list.size()];
1460    for (int i = 0; i < report.length; i++) {
1461      report[i] = convert(list.get(i));
1462    }
1463    return report;
1464  }
1465
1466  public static StorageReport convert(StorageReportProto p) {
1467    long nonDfsUsed = p.hasNonDfsUsed() ? p.getNonDfsUsed() : p.getCapacity()
1468        - p.getDfsUsed() - p.getRemaining();
1469    return new StorageReport(p.hasStorage() ? convert(p.getStorage())
1470        : new DatanodeStorage(p.getStorageUuid()), p.getFailed(),
1471        p.getCapacity(), p.getDfsUsed(), p.getRemaining(),
1472        p.getBlockPoolUsed(), nonDfsUsed);
1473  }
1474
1475  public static DatanodeStorage convert(DatanodeStorageProto s) {
1476    return new DatanodeStorage(s.getStorageUuid(),
1477        convertState(s.getState()), convertStorageType(s.getStorageType()));
1478  }
1479
1480  private static State convertState(StorageState state) {
1481    switch(state) {
1482    case READ_ONLY_SHARED:
1483      return State.READ_ONLY_SHARED;
1484    case NORMAL:
1485    default:
1486      return State.NORMAL;
1487    }
1488  }
1489
1490  public static SafeModeActionProto convert(SafeModeAction a) {
1491    switch (a) {
1492    case SAFEMODE_LEAVE:
1493      return SafeModeActionProto.SAFEMODE_LEAVE;
1494    case SAFEMODE_ENTER:
1495      return SafeModeActionProto.SAFEMODE_ENTER;
1496    case SAFEMODE_GET:
1497      return SafeModeActionProto.SAFEMODE_GET;
1498    case SAFEMODE_FORCE_EXIT:
1499      return  SafeModeActionProto.SAFEMODE_FORCE_EXIT;
1500    default:
1501      throw new IllegalArgumentException("Unexpected SafeModeAction :" + a);
1502    }
1503  }
1504
1505  public static DatanodeInfo[] convert(List<DatanodeInfoProto> list) {
1506    DatanodeInfo[] info = new DatanodeInfo[list.size()];
1507    for (int i = 0; i < info.length; i++) {
1508      info[i] = convert(list.get(i));
1509    }
1510    return info;
1511  }
1512
1513  public static long[] convert(GetFsStatsResponseProto res) {
1514    long[] result = new long[ClientProtocol.STATS_ARRAY_LENGTH];
1515    result[ClientProtocol.GET_STATS_CAPACITY_IDX] = res.getCapacity();
1516    result[ClientProtocol.GET_STATS_USED_IDX] = res.getUsed();
1517    result[ClientProtocol.GET_STATS_REMAINING_IDX] = res.getRemaining();
1518    result[ClientProtocol.GET_STATS_UNDER_REPLICATED_IDX] =
1519        res.getUnderReplicated();
1520    result[ClientProtocol.GET_STATS_CORRUPT_BLOCKS_IDX] =
1521        res.getCorruptBlocks();
1522    result[ClientProtocol.GET_STATS_MISSING_BLOCKS_IDX] =
1523        res.getMissingBlocks();
1524    result[ClientProtocol.GET_STATS_MISSING_REPL_ONE_BLOCKS_IDX] =
1525        res.getMissingReplOneBlocks();
1526    result[ClientProtocol.GET_STATS_BYTES_IN_FUTURE_BLOCKS_IDX] =
1527        res.hasBlocksInFuture() ? res.getBlocksInFuture() : 0;
1528    result[ClientProtocol.GET_STATS_PENDING_DELETION_BLOCKS_IDX] =
1529        res.getPendingDeletionBlocks();
1530    return result;
1531  }
1532
1533  public static DatanodeReportTypeProto convert(DatanodeReportType t) {
1534    switch (t) {
1535    case ALL: return DatanodeReportTypeProto.ALL;
1536    case LIVE: return DatanodeReportTypeProto.LIVE;
1537    case DEAD: return DatanodeReportTypeProto.DEAD;
1538    case DECOMMISSIONING: return DatanodeReportTypeProto.DECOMMISSIONING;
1539    default:
1540      throw new IllegalArgumentException("Unexpected data type report:" + t);
1541    }
1542  }
1543
1544  public static DirectoryListing convert(DirectoryListingProto dl) {
1545    if (dl == null)
1546      return null;
1547    List<HdfsFileStatusProto> partList =  dl.getPartialListingList();
1548    return new DirectoryListing(partList.isEmpty() ?
1549        new HdfsLocatedFileStatus[0] :
1550        convert(partList.toArray(new HdfsFileStatusProto[partList.size()])),
1551        dl.getRemainingEntries());
1552  }
1553
1554  public static HdfsFileStatus[] convert(HdfsFileStatusProto[] fs) {
1555    if (fs == null) return null;
1556    final int len = fs.length;
1557    HdfsFileStatus[] result = new HdfsFileStatus[len];
1558    for (int i = 0; i < len; ++i) {
1559      result[i] = convert(fs[i]);
1560    }
1561    return result;
1562  }
1563
1564  // The creatFlag field in PB is a bitmask whose values are the same a the
1565  // emum values of CreateFlag
1566  public static int convertCreateFlag(EnumSetWritable<CreateFlag> flag) {
1567    int value = 0;
1568    if (flag.contains(CreateFlag.APPEND)) {
1569      value |= CreateFlagProto.APPEND.getNumber();
1570    }
1571    if (flag.contains(CreateFlag.CREATE)) {
1572      value |= CreateFlagProto.CREATE.getNumber();
1573    }
1574    if (flag.contains(CreateFlag.OVERWRITE)) {
1575      value |= CreateFlagProto.OVERWRITE.getNumber();
1576    }
1577    if (flag.contains(CreateFlag.LAZY_PERSIST)) {
1578      value |= CreateFlagProto.LAZY_PERSIST.getNumber();
1579    }
1580    if (flag.contains(CreateFlag.NEW_BLOCK)) {
1581      value |= CreateFlagProto.NEW_BLOCK.getNumber();
1582    }
1583    return value;
1584  }
1585
1586  public static FsServerDefaults convert(FsServerDefaultsProto fs) {
1587    if (fs == null) return null;
1588    return new FsServerDefaults(
1589        fs.getBlockSize(), fs.getBytesPerChecksum(),
1590        fs.getWritePacketSize(), (short) fs.getReplication(),
1591        fs.getFileBufferSize(),
1592        fs.getEncryptDataTransfer(),
1593        fs.getTrashInterval(),
1594        convert(fs.getChecksumType()));
1595  }
1596
1597  public static List<CryptoProtocolVersionProto> convert(
1598      CryptoProtocolVersion[] versions) {
1599    List<CryptoProtocolVersionProto> protos =
1600        Lists.newArrayListWithCapacity(versions.length);
1601    for (CryptoProtocolVersion v: versions) {
1602      protos.add(convert(v));
1603    }
1604    return protos;
1605  }
1606
1607  static List<StorageTypesProto> convert(StorageType[][] types) {
1608    List<StorageTypesProto> list = Lists.newArrayList();
1609    if (types != null) {
1610      for (StorageType[] ts : types) {
1611        StorageTypesProto.Builder builder = StorageTypesProto.newBuilder();
1612        builder.addAllStorageTypes(convertStorageTypes(ts));
1613        list.add(builder.build());
1614      }
1615    }
1616    return list;
1617  }
1618
1619  public static BlockStoragePolicyProto convert(BlockStoragePolicy policy) {
1620    BlockStoragePolicyProto.Builder builder = BlockStoragePolicyProto
1621        .newBuilder().setPolicyId(policy.getId()).setName(policy.getName());
1622    // creation storage types
1623    StorageTypesProto creationProto = convert(policy.getStorageTypes());
1624    Preconditions.checkArgument(creationProto != null);
1625    builder.setCreationPolicy(creationProto);
1626    // creation fallback
1627    StorageTypesProto creationFallbackProto = convert(
1628        policy.getCreationFallbacks());
1629    if (creationFallbackProto != null) {
1630      builder.setCreationFallbackPolicy(creationFallbackProto);
1631    }
1632    // replication fallback
1633    StorageTypesProto replicationFallbackProto = convert(
1634        policy.getReplicationFallbacks());
1635    if (replicationFallbackProto != null) {
1636      builder.setReplicationFallbackPolicy(replicationFallbackProto);
1637    }
1638    return builder.build();
1639  }
1640
1641  public static StorageTypesProto convert(StorageType[] types) {
1642    if (types == null || types.length == 0) {
1643      return null;
1644    }
1645    List<StorageTypeProto> list = convertStorageTypes(types);
1646    return StorageTypesProto.newBuilder().addAllStorageTypes(list).build();
1647  }
1648
1649  public static DatanodeID[] convert(DatanodeIDProto[] did) {
1650    if (did == null) return null;
1651    final int len = did.length;
1652    DatanodeID[] result = new DatanodeID[len];
1653    for (int i = 0; i < len; ++i) {
1654      result[i] = convert(did[i]);
1655    }
1656    return result;
1657  }
1658
1659  // Block
1660  public static BlockProto convert(Block b) {
1661    return BlockProto.newBuilder().setBlockId(b.getBlockId())
1662        .setGenStamp(b.getGenerationStamp()).setNumBytes(b.getNumBytes())
1663        .build();
1664  }
1665
1666  public static Block convert(BlockProto b) {
1667    return new Block(b.getBlockId(), b.getNumBytes(), b.getGenStamp());
1668  }
1669
1670  static public DatanodeInfo[] convert(DatanodeInfoProto di[]) {
1671    if (di == null) return null;
1672    DatanodeInfo[] result = new DatanodeInfo[di.length];
1673    for (int i = 0; i < di.length; i++) {
1674      result[i] = convert(di[i]);
1675    }
1676    return result;
1677  }
1678
1679  public static DatanodeStorageReportProto convertDatanodeStorageReport(
1680      DatanodeStorageReport report) {
1681    return DatanodeStorageReportProto.newBuilder()
1682        .setDatanodeInfo(convert(report.getDatanodeInfo()))
1683        .addAllStorageReports(convertStorageReports(report.getStorageReports()))
1684        .build();
1685  }
1686
1687  public static List<DatanodeStorageReportProto> convertDatanodeStorageReports(
1688      DatanodeStorageReport[] reports) {
1689    final List<DatanodeStorageReportProto> protos
1690        = new ArrayList<>(reports.length);
1691    for (DatanodeStorageReport report : reports) {
1692      protos.add(convertDatanodeStorageReport(report));
1693    }
1694    return protos;
1695  }
1696
1697  public static LocatedBlock[] convertLocatedBlock(LocatedBlockProto[] lb) {
1698    if (lb == null) return null;
1699    return convertLocatedBlock(Arrays.asList(lb)).toArray(
1700        new LocatedBlock[lb.length]);
1701  }
1702
1703  public static LocatedBlocksProto convert(LocatedBlocks lb) {
1704    if (lb == null) {
1705      return null;
1706    }
1707    LocatedBlocksProto.Builder builder =
1708        LocatedBlocksProto.newBuilder();
1709    if (lb.getLastLocatedBlock() != null) {
1710      builder.setLastBlock(convert(lb.getLastLocatedBlock()));
1711    }
1712    if (lb.getFileEncryptionInfo() != null) {
1713      builder.setFileEncryptionInfo(convert(lb.getFileEncryptionInfo()));
1714    }
1715    return builder.setFileLength(lb.getFileLength())
1716        .setUnderConstruction(lb.isUnderConstruction())
1717        .addAllBlocks(convertLocatedBlock2(lb.getLocatedBlocks()))
1718        .setIsLastBlockComplete(lb.isLastBlockComplete()).build();
1719  }
1720
1721  public static DataEncryptionKeyProto convert(DataEncryptionKey bet) {
1722    DataEncryptionKeyProto.Builder b = DataEncryptionKeyProto.newBuilder()
1723        .setKeyId(bet.keyId)
1724        .setBlockPoolId(bet.blockPoolId)
1725        .setNonce(getByteString(bet.nonce))
1726        .setEncryptionKey(getByteString(bet.encryptionKey))
1727        .setExpiryDate(bet.expiryDate);
1728    if (bet.encryptionAlgorithm != null) {
1729      b.setEncryptionAlgorithm(bet.encryptionAlgorithm);
1730    }
1731    return b.build();
1732  }
1733
1734  public static FsServerDefaultsProto convert(FsServerDefaults fs) {
1735    if (fs == null) return null;
1736    return FsServerDefaultsProto.newBuilder().
1737        setBlockSize(fs.getBlockSize()).
1738        setBytesPerChecksum(fs.getBytesPerChecksum()).
1739        setWritePacketSize(fs.getWritePacketSize())
1740        .setReplication(fs.getReplication())
1741        .setFileBufferSize(fs.getFileBufferSize())
1742        .setEncryptDataTransfer(fs.getEncryptDataTransfer())
1743        .setTrashInterval(fs.getTrashInterval())
1744        .setChecksumType(convert(fs.getChecksumType()))
1745        .build();
1746  }
1747
1748  public static EnumSetWritable<CreateFlag> convertCreateFlag(int flag) {
1749    EnumSet<CreateFlag> result =
1750        EnumSet.noneOf(CreateFlag.class);
1751    if ((flag & CreateFlagProto.APPEND_VALUE) == CreateFlagProto.APPEND_VALUE) {
1752      result.add(CreateFlag.APPEND);
1753    }
1754    if ((flag & CreateFlagProto.CREATE_VALUE) == CreateFlagProto.CREATE_VALUE) {
1755      result.add(CreateFlag.CREATE);
1756    }
1757    if ((flag & CreateFlagProto.OVERWRITE_VALUE)
1758        == CreateFlagProto.OVERWRITE_VALUE) {
1759      result.add(CreateFlag.OVERWRITE);
1760    }
1761    if ((flag & CreateFlagProto.LAZY_PERSIST_VALUE)
1762        == CreateFlagProto.LAZY_PERSIST_VALUE) {
1763      result.add(CreateFlag.LAZY_PERSIST);
1764    }
1765    if ((flag & CreateFlagProto.NEW_BLOCK_VALUE)
1766        == CreateFlagProto.NEW_BLOCK_VALUE) {
1767      result.add(CreateFlag.NEW_BLOCK);
1768    }
1769    return new EnumSetWritable<>(result, CreateFlag.class);
1770  }
1771
1772  public static EnumSet<CacheFlag> convertCacheFlags(int flags) {
1773    EnumSet<CacheFlag> result = EnumSet.noneOf(CacheFlag.class);
1774    if ((flags & CacheFlagProto.FORCE_VALUE) == CacheFlagProto.FORCE_VALUE) {
1775      result.add(CacheFlag.FORCE);
1776    }
1777    return result;
1778  }
1779
1780  public static HdfsFileStatusProto convert(HdfsFileStatus fs) {
1781    if (fs == null)
1782      return null;
1783    FileType fType = FileType.IS_FILE;
1784    if (fs.isDir()) {
1785      fType = FileType.IS_DIR;
1786    } else if (fs.isSymlink()) {
1787      fType = FileType.IS_SYMLINK;
1788    }
1789
1790    HdfsFileStatusProto.Builder builder =
1791        HdfsFileStatusProto.newBuilder().
1792            setLength(fs.getLen()).
1793            setFileType(fType).
1794            setBlockReplication(fs.getReplication()).
1795            setBlocksize(fs.getBlockSize()).
1796            setModificationTime(fs.getModificationTime()).
1797            setAccessTime(fs.getAccessTime()).
1798            setPermission(convert(fs.getPermission())).
1799            setOwner(fs.getOwner()).
1800            setGroup(fs.getGroup()).
1801            setFileId(fs.getFileId()).
1802            setChildrenNum(fs.getChildrenNum()).
1803            setPath(getByteString(fs.getLocalNameInBytes())).
1804            setStoragePolicy(fs.getStoragePolicy());
1805    if (fs.isSymlink())  {
1806      builder.setSymlink(getByteString(fs.getSymlinkInBytes()));
1807    }
1808    if (fs.getFileEncryptionInfo() != null) {
1809      builder.setFileEncryptionInfo(convert(fs.getFileEncryptionInfo()));
1810    }
1811    if (fs instanceof HdfsLocatedFileStatus) {
1812      final HdfsLocatedFileStatus lfs = (HdfsLocatedFileStatus) fs;
1813      LocatedBlocks locations = lfs.getBlockLocations();
1814      if (locations != null) {
1815        builder.setLocations(convert(locations));
1816      }
1817    }
1818    return builder.build();
1819  }
1820
1821  public static SnapshottableDirectoryStatusProto convert(
1822      SnapshottableDirectoryStatus status) {
1823    if (status == null) {
1824      return null;
1825    }
1826    int snapshotNumber = status.getSnapshotNumber();
1827    int snapshotQuota = status.getSnapshotQuota();
1828    byte[] parentFullPath = status.getParentFullPath();
1829    ByteString parentFullPathBytes = getByteString(
1830        parentFullPath == null ? DFSUtilClient.EMPTY_BYTES : parentFullPath);
1831    HdfsFileStatusProto fs = convert(status.getDirStatus());
1832    SnapshottableDirectoryStatusProto.Builder builder =
1833        SnapshottableDirectoryStatusProto
1834            .newBuilder()
1835            .setSnapshotNumber(snapshotNumber)
1836            .setSnapshotQuota(snapshotQuota)
1837            .setParentFullpath(parentFullPathBytes)
1838            .setDirStatus(fs);
1839    return builder.build();
1840  }
1841
1842  public static HdfsFileStatusProto[] convert(HdfsFileStatus[] fs) {
1843    if (fs == null) return null;
1844    final int len = fs.length;
1845    HdfsFileStatusProto[] result = new HdfsFileStatusProto[len];
1846    for (int i = 0; i < len; ++i) {
1847      result[i] = convert(fs[i]);
1848    }
1849    return result;
1850  }
1851
1852  public static DirectoryListingProto convert(DirectoryListing d) {
1853    if (d == null)
1854      return null;
1855    return DirectoryListingProto.newBuilder().
1856        addAllPartialListing(Arrays.asList(
1857            convert(d.getPartialListing()))).
1858        setRemainingEntries(d.getRemainingEntries()).
1859        build();
1860  }
1861
1862  public static GetFsStatsResponseProto convert(long[] fsStats) {
1863    GetFsStatsResponseProto.Builder result = GetFsStatsResponseProto
1864        .newBuilder();
1865    if (fsStats.length >= ClientProtocol.GET_STATS_CAPACITY_IDX + 1)
1866      result.setCapacity(fsStats[ClientProtocol.GET_STATS_CAPACITY_IDX]);
1867    if (fsStats.length >= ClientProtocol.GET_STATS_USED_IDX + 1)
1868      result.setUsed(fsStats[ClientProtocol.GET_STATS_USED_IDX]);
1869    if (fsStats.length >= ClientProtocol.GET_STATS_REMAINING_IDX + 1)
1870      result.setRemaining(fsStats[ClientProtocol.GET_STATS_REMAINING_IDX]);
1871    if (fsStats.length >= ClientProtocol.GET_STATS_UNDER_REPLICATED_IDX + 1)
1872      result.setUnderReplicated(
1873          fsStats[ClientProtocol.GET_STATS_UNDER_REPLICATED_IDX]);
1874    if (fsStats.length >= ClientProtocol.GET_STATS_CORRUPT_BLOCKS_IDX + 1)
1875      result.setCorruptBlocks(
1876          fsStats[ClientProtocol.GET_STATS_CORRUPT_BLOCKS_IDX]);
1877    if (fsStats.length >= ClientProtocol.GET_STATS_MISSING_BLOCKS_IDX + 1)
1878      result.setMissingBlocks(
1879          fsStats[ClientProtocol.GET_STATS_MISSING_BLOCKS_IDX]);
1880    if (fsStats.length >=
1881        ClientProtocol.GET_STATS_MISSING_REPL_ONE_BLOCKS_IDX + 1)
1882      result.setMissingReplOneBlocks(
1883          fsStats[ClientProtocol.GET_STATS_MISSING_REPL_ONE_BLOCKS_IDX]);
1884
1885    if (fsStats.length >=
1886        ClientProtocol.GET_STATS_BYTES_IN_FUTURE_BLOCKS_IDX + 1) {
1887      result.setBlocksInFuture(
1888          fsStats[ClientProtocol.GET_STATS_BYTES_IN_FUTURE_BLOCKS_IDX]);
1889    }
1890    if (fsStats.length >=
1891        ClientProtocol.GET_STATS_PENDING_DELETION_BLOCKS_IDX + 1) {
1892      result.setPendingDeletionBlocks(
1893          fsStats[ClientProtocol.GET_STATS_PENDING_DELETION_BLOCKS_IDX]);
1894    }
1895    return result.build();
1896  }
1897
1898  public static DatanodeReportType convert(DatanodeReportTypeProto t) {
1899    switch (t) {
1900    case ALL: return DatanodeReportType.ALL;
1901    case LIVE: return DatanodeReportType.LIVE;
1902    case DEAD: return DatanodeReportType.DEAD;
1903    case DECOMMISSIONING: return DatanodeReportType.DECOMMISSIONING;
1904    default:
1905      throw new IllegalArgumentException("Unexpected data type report:" + t);
1906    }
1907  }
1908
1909  public static SafeModeAction convert(
1910      SafeModeActionProto a) {
1911    switch (a) {
1912    case SAFEMODE_LEAVE:
1913      return SafeModeAction.SAFEMODE_LEAVE;
1914    case SAFEMODE_ENTER:
1915      return SafeModeAction.SAFEMODE_ENTER;
1916    case SAFEMODE_GET:
1917      return SafeModeAction.SAFEMODE_GET;
1918    case SAFEMODE_FORCE_EXIT:
1919      return  SafeModeAction.SAFEMODE_FORCE_EXIT;
1920    default:
1921      throw new IllegalArgumentException("Unexpected SafeModeAction :" + a);
1922    }
1923  }
1924
1925  public static RollingUpgradeAction convert(RollingUpgradeActionProto a) {
1926    switch (a) {
1927    case QUERY:
1928      return RollingUpgradeAction.QUERY;
1929    case START:
1930      return RollingUpgradeAction.PREPARE;
1931    case FINALIZE:
1932      return RollingUpgradeAction.FINALIZE;
1933    default:
1934      throw new IllegalArgumentException("Unexpected value: " + a);
1935    }
1936  }
1937
1938  public static RollingUpgradeStatusProto convertRollingUpgradeStatus(
1939      RollingUpgradeStatus status) {
1940    return RollingUpgradeStatusProto.newBuilder()
1941        .setBlockPoolId(status.getBlockPoolId())
1942        .setFinalized(status.isFinalized())
1943        .build();
1944  }
1945
1946  public static RollingUpgradeStatus convert(RollingUpgradeStatusProto proto) {
1947    return new RollingUpgradeStatus(proto.getBlockPoolId(),
1948        proto.getFinalized());
1949  }
1950
1951  public static RollingUpgradeInfoProto convert(RollingUpgradeInfo info) {
1952    return RollingUpgradeInfoProto.newBuilder()
1953        .setStatus(convertRollingUpgradeStatus(info))
1954        .setCreatedRollbackImages(info.createdRollbackImages())
1955        .setStartTime(info.getStartTime())
1956        .setFinalizeTime(info.getFinalizeTime())
1957        .build();
1958  }
1959
1960  public static CorruptFileBlocksProto convert(CorruptFileBlocks c) {
1961    if (c == null)
1962      return null;
1963    return CorruptFileBlocksProto.newBuilder().
1964        addAllFiles(Arrays.asList(c.getFiles())).
1965        setCookie(c.getCookie()).
1966        build();
1967  }
1968
1969  public static ContentSummaryProto convert(ContentSummary cs) {
1970    if (cs == null) return null;
1971    ContentSummaryProto.Builder builder = ContentSummaryProto.newBuilder();
1972    builder.setLength(cs.getLength()).
1973        setFileCount(cs.getFileCount()).
1974        setDirectoryCount(cs.getDirectoryCount()).
1975        setSnapshotLength(cs.getSnapshotLength()).
1976        setSnapshotFileCount(cs.getSnapshotFileCount()).
1977        setSnapshotDirectoryCount(cs.getSnapshotDirectoryCount()).
1978        setSnapshotSpaceConsumed(cs.getSnapshotSpaceConsumed()).
1979        setQuota(cs.getQuota()).
1980        setSpaceConsumed(cs.getSpaceConsumed()).
1981        setSpaceQuota(cs.getSpaceQuota());
1982
1983    if (cs.isTypeQuotaSet() || cs.isTypeConsumedAvailable()) {
1984      builder.setTypeQuotaInfos(getBuilder(cs));
1985    }
1986    return builder.build();
1987  }
1988
1989  private static void addStorageTypes(
1990      HdfsProtos.StorageTypeQuotaInfosProto typeQuotaInfos,
1991      QuotaUsage.Builder builder) {
1992    for (HdfsProtos.StorageTypeQuotaInfoProto info :
1993        typeQuotaInfos.getTypeQuotaInfoList()) {
1994      StorageType type = convertStorageType(info.getType());
1995      builder.typeConsumed(type, info.getConsumed());
1996      builder.typeQuota(type, info.getQuota());
1997    }
1998  }
1999
2000  private static HdfsProtos.StorageTypeQuotaInfosProto.Builder getBuilder(
2001      QuotaUsage qu) {
2002    HdfsProtos.StorageTypeQuotaInfosProto.Builder isb =
2003            HdfsProtos.StorageTypeQuotaInfosProto.newBuilder();
2004    for (StorageType t: StorageType.getTypesSupportingQuota()) {
2005      HdfsProtos.StorageTypeQuotaInfoProto info =
2006          HdfsProtos.StorageTypeQuotaInfoProto.newBuilder().
2007              setType(convertStorageType(t)).
2008              setConsumed(qu.getTypeConsumed(t)).
2009              setQuota(qu.getTypeQuota(t)).
2010              build();
2011      isb.addTypeQuotaInfo(info);
2012    }
2013    return isb;
2014  }
2015
2016  public static DatanodeStorageProto convert(DatanodeStorage s) {
2017    return DatanodeStorageProto.newBuilder()
2018        .setState(convertState(s.getState()))
2019        .setStorageType(convertStorageType(s.getStorageType()))
2020        .setStorageUuid(s.getStorageID()).build();
2021  }
2022
2023  private static StorageState convertState(State state) {
2024    switch(state) {
2025    case READ_ONLY_SHARED:
2026      return StorageState.READ_ONLY_SHARED;
2027    case NORMAL:
2028    default:
2029      return StorageState.NORMAL;
2030    }
2031  }
2032
2033  public static StorageReportProto convert(StorageReport r) {
2034    StorageReportProto.Builder builder = StorageReportProto.newBuilder()
2035        .setBlockPoolUsed(r.getBlockPoolUsed()).setCapacity(r.getCapacity())
2036        .setDfsUsed(r.getDfsUsed()).setRemaining(r.getRemaining())
2037        .setStorageUuid(r.getStorage().getStorageID())
2038        .setStorage(convert(r.getStorage()))
2039        .setNonDfsUsed(r.getNonDfsUsed());
2040    return builder.build();
2041  }
2042
2043  public static List<StorageReportProto> convertStorageReports(
2044      StorageReport[] storages) {
2045    final List<StorageReportProto> protos = new ArrayList<>(storages.length);
2046    for (StorageReport storage : storages) {
2047      protos.add(convert(storage));
2048    }
2049    return protos;
2050  }
2051
2052  public static SnapshottableDirectoryListingProto convert(
2053      SnapshottableDirectoryStatus[] status) {
2054    if (status == null)
2055      return null;
2056    SnapshottableDirectoryStatusProto[] protos =
2057        new SnapshottableDirectoryStatusProto[status.length];
2058    for (int i = 0; i < status.length; i++) {
2059      protos[i] = convert(status[i]);
2060    }
2061    List<SnapshottableDirectoryStatusProto> protoList = Arrays.asList(protos);
2062    return SnapshottableDirectoryListingProto.newBuilder()
2063        .addAllSnapshottableDirListing(protoList).build();
2064  }
2065
2066  public static SnapshotDiffReportEntryProto convert(DiffReportEntry entry) {
2067    if (entry == null) {
2068      return null;
2069    }
2070    ByteString sourcePath = getByteString(entry.getSourcePath() == null ?
2071        DFSUtilClient.EMPTY_BYTES : entry.getSourcePath());
2072    String modification = entry.getType().getLabel();
2073    SnapshotDiffReportEntryProto.Builder builder = SnapshotDiffReportEntryProto
2074        .newBuilder().setFullpath(sourcePath)
2075        .setModificationLabel(modification);
2076    if (entry.getType() == DiffType.RENAME) {
2077      ByteString targetPath =
2078          getByteString(entry.getTargetPath() == null ?
2079              DFSUtilClient.EMPTY_BYTES : entry.getTargetPath());
2080      builder.setTargetPath(targetPath);
2081    }
2082    return builder.build();
2083  }
2084
2085  public static SnapshotDiffReportProto convert(SnapshotDiffReport report) {
2086    if (report == null) {
2087      return null;
2088    }
2089    List<DiffReportEntry> entries = report.getDiffList();
2090    List<SnapshotDiffReportEntryProto> entryProtos = new ArrayList<>();
2091    for (DiffReportEntry entry : entries) {
2092      SnapshotDiffReportEntryProto entryProto = convert(entry);
2093      if (entryProto != null)
2094        entryProtos.add(entryProto);
2095    }
2096
2097    return SnapshotDiffReportProto.newBuilder()
2098        .setSnapshotRoot(report.getSnapshotRoot())
2099        .setFromSnapshot(report.getFromSnapshot())
2100        .setToSnapshot(report.getLaterSnapshotName())
2101        .addAllDiffReportEntries(entryProtos).build();
2102  }
2103
2104  public static CacheDirectiveStatsProto convert(CacheDirectiveStats stats) {
2105    CacheDirectiveStatsProto.Builder builder =
2106        CacheDirectiveStatsProto.newBuilder();
2107    builder.setBytesNeeded(stats.getBytesNeeded());
2108    builder.setBytesCached(stats.getBytesCached());
2109    builder.setFilesNeeded(stats.getFilesNeeded());
2110    builder.setFilesCached(stats.getFilesCached());
2111    builder.setHasExpired(stats.hasExpired());
2112    return builder.build();
2113  }
2114
2115  public static CacheDirectiveEntryProto convert(CacheDirectiveEntry entry) {
2116    CacheDirectiveEntryProto.Builder builder =
2117        CacheDirectiveEntryProto.newBuilder();
2118    builder.setInfo(convert(entry.getInfo()));
2119    builder.setStats(convert(entry.getStats()));
2120    return builder.build();
2121  }
2122
2123  public static boolean[] convertBooleanList(
2124      List<Boolean> targetPinningsList) {
2125    final boolean[] targetPinnings = new boolean[targetPinningsList.size()];
2126    for (int i = 0; i < targetPinningsList.size(); i++) {
2127      targetPinnings[i] = targetPinningsList.get(i);
2128    }
2129    return targetPinnings;
2130  }
2131
2132  public static CachePoolStatsProto convert(CachePoolStats stats) {
2133    CachePoolStatsProto.Builder builder = CachePoolStatsProto.newBuilder();
2134    builder.setBytesNeeded(stats.getBytesNeeded());
2135    builder.setBytesCached(stats.getBytesCached());
2136    builder.setBytesOverlimit(stats.getBytesOverlimit());
2137    builder.setFilesNeeded(stats.getFilesNeeded());
2138    builder.setFilesCached(stats.getFilesCached());
2139    return builder.build();
2140  }
2141
2142  public static CachePoolEntryProto convert(CachePoolEntry entry) {
2143    CachePoolEntryProto.Builder builder = CachePoolEntryProto.newBuilder();
2144    builder.setInfo(convert(entry.getInfo()));
2145    builder.setStats(convert(entry.getStats()));
2146    return builder.build();
2147  }
2148
2149  public static DatanodeLocalInfoProto convert(DatanodeLocalInfo info) {
2150    DatanodeLocalInfoProto.Builder builder =
2151        DatanodeLocalInfoProto.newBuilder();
2152    builder.setSoftwareVersion(info.getSoftwareVersion());
2153    builder.setConfigVersion(info.getConfigVersion());
2154    builder.setUptime(info.getUptime());
2155    return builder.build();
2156  }
2157
2158  public static GetAclStatusResponseProto convert(AclStatus e) {
2159    AclStatusProto.Builder builder = AclStatusProto.newBuilder();
2160    builder.setOwner(e.getOwner())
2161        .setGroup(e.getGroup()).setSticky(e.isStickyBit())
2162        .addAllEntries(convertAclEntryProto(e.getEntries()));
2163    if (e.getPermission() != null) {
2164      builder.setPermission(convert(e.getPermission()));
2165    }
2166    AclStatusProto r = builder.build();
2167    return GetAclStatusResponseProto.newBuilder().setResult(r).build();
2168  }
2169
2170  public static EnumSet<XAttrSetFlag> convert(int flag) {
2171    EnumSet<XAttrSetFlag> result =
2172        EnumSet.noneOf(XAttrSetFlag.class);
2173    if ((flag & XAttrSetFlagProto.XATTR_CREATE_VALUE) ==
2174        XAttrSetFlagProto.XATTR_CREATE_VALUE) {
2175      result.add(XAttrSetFlag.CREATE);
2176    }
2177    if ((flag & XAttrSetFlagProto.XATTR_REPLACE_VALUE) ==
2178        XAttrSetFlagProto.XATTR_REPLACE_VALUE) {
2179      result.add(XAttrSetFlag.REPLACE);
2180    }
2181    return result;
2182  }
2183
2184  public static XAttr convertXAttr(XAttrProto a) {
2185    XAttr.Builder builder = new XAttr.Builder();
2186    builder.setNameSpace(convert(a.getNamespace()));
2187    if (a.hasName()) {
2188      builder.setName(a.getName());
2189    }
2190    if (a.hasValue()) {
2191      builder.setValue(a.getValue().toByteArray());
2192    }
2193    return builder.build();
2194  }
2195
2196  public static GetXAttrsResponseProto convertXAttrsResponse(
2197      List<XAttr> xAttrs) {
2198    GetXAttrsResponseProto.Builder builder = GetXAttrsResponseProto
2199        .newBuilder();
2200    if (xAttrs != null) {
2201      builder.addAllXAttrs(convertXAttrProto(xAttrs));
2202    }
2203    return builder.build();
2204  }
2205
2206  public static ListXAttrsResponseProto convertListXAttrsResponse(
2207      List<XAttr> names) {
2208    ListXAttrsResponseProto.Builder builder =
2209        ListXAttrsResponseProto.newBuilder();
2210    if (names != null) {
2211      builder.addAllXAttrs(convertXAttrProto(names));
2212    }
2213    return builder.build();
2214  }
2215
2216  public static EncryptionZoneProto convert(EncryptionZone zone) {
2217    return EncryptionZoneProto.newBuilder()
2218        .setId(zone.getId())
2219        .setPath(zone.getPath())
2220        .setSuite(convert(zone.getSuite()))
2221        .setCryptoProtocolVersion(convert(zone.getVersion()))
2222        .setKeyName(zone.getKeyName())
2223        .build();
2224  }
2225
2226  public static SlotId convert(ShortCircuitShmSlotProto slotId) {
2227    return new SlotId(convert(slotId.getShmId()),
2228        slotId.getSlotIdx());
2229  }
2230
2231  public static GetEditsFromTxidResponseProto convertEditsResponse(
2232      EventBatchList el) {
2233    InotifyProtos.EventsListProto.Builder builder =
2234        InotifyProtos.EventsListProto.newBuilder();
2235    for (EventBatch b : el.getBatches()) {
2236      List<InotifyProtos.EventProto> events = Lists.newArrayList();
2237      for (Event e : b.getEvents()) {
2238        switch (e.getEventType()) {
2239        case CLOSE:
2240          Event.CloseEvent ce = (Event.CloseEvent) e;
2241          events.add(InotifyProtos.EventProto.newBuilder()
2242              .setType(InotifyProtos.EventType.EVENT_CLOSE)
2243              .setContents(
2244                  InotifyProtos.CloseEventProto.newBuilder()
2245                      .setPath(ce.getPath())
2246                      .setFileSize(ce.getFileSize())
2247                      .setTimestamp(ce.getTimestamp()).build().toByteString()
2248              ).build());
2249          break;
2250        case CREATE:
2251          Event.CreateEvent ce2 = (Event.CreateEvent) e;
2252          events.add(InotifyProtos.EventProto.newBuilder()
2253              .setType(InotifyProtos.EventType.EVENT_CREATE)
2254              .setContents(
2255                  InotifyProtos.CreateEventProto.newBuilder()
2256                      .setType(createTypeConvert(ce2.getiNodeType()))
2257                      .setPath(ce2.getPath())
2258                      .setCtime(ce2.getCtime())
2259                      .setOwnerName(ce2.getOwnerName())
2260                      .setGroupName(ce2.getGroupName())
2261                      .setPerms(convert(ce2.getPerms()))
2262                      .setReplication(ce2.getReplication())
2263                      .setSymlinkTarget(ce2.getSymlinkTarget() == null ?
2264                          "" : ce2.getSymlinkTarget())
2265                      .setDefaultBlockSize(ce2.getDefaultBlockSize())
2266                      .setOverwrite(ce2.getOverwrite()).build().toByteString()
2267              ).build());
2268          break;
2269        case METADATA:
2270          Event.MetadataUpdateEvent me = (Event.MetadataUpdateEvent) e;
2271          InotifyProtos.MetadataUpdateEventProto.Builder metaB =
2272              InotifyProtos.MetadataUpdateEventProto.newBuilder()
2273                  .setPath(me.getPath())
2274                  .setType(metadataUpdateTypeConvert(me.getMetadataType()))
2275                  .setMtime(me.getMtime())
2276                  .setAtime(me.getAtime())
2277                  .setReplication(me.getReplication())
2278                  .setOwnerName(me.getOwnerName() == null ? "" :
2279                      me.getOwnerName())
2280                  .setGroupName(me.getGroupName() == null ? "" :
2281                      me.getGroupName())
2282                  .addAllAcls(me.getAcls() == null ?
2283                      Lists.<AclEntryProto>newArrayList() :
2284                      convertAclEntryProto(me.getAcls()))
2285                  .addAllXAttrs(me.getxAttrs() == null ?
2286                      Lists.<XAttrProto>newArrayList() :
2287                      convertXAttrProto(me.getxAttrs()))
2288                  .setXAttrsRemoved(me.isxAttrsRemoved());
2289          if (me.getPerms() != null) {
2290            metaB.setPerms(convert(me.getPerms()));
2291          }
2292          events.add(InotifyProtos.EventProto.newBuilder()
2293              .setType(InotifyProtos.EventType.EVENT_METADATA)
2294              .setContents(metaB.build().toByteString())
2295              .build());
2296          break;
2297        case RENAME:
2298          Event.RenameEvent re = (Event.RenameEvent) e;
2299          events.add(InotifyProtos.EventProto.newBuilder()
2300              .setType(InotifyProtos.EventType.EVENT_RENAME)
2301              .setContents(
2302                  InotifyProtos.RenameEventProto.newBuilder()
2303                      .setSrcPath(re.getSrcPath())
2304                      .setDestPath(re.getDstPath())
2305                      .setTimestamp(re.getTimestamp()).build().toByteString()
2306              ).build());
2307          break;
2308        case APPEND:
2309          Event.AppendEvent re2 = (Event.AppendEvent) e;
2310          events.add(InotifyProtos.EventProto.newBuilder()
2311              .setType(InotifyProtos.EventType.EVENT_APPEND)
2312              .setContents(InotifyProtos.AppendEventProto.newBuilder()
2313                  .setPath(re2.getPath())
2314                  .setNewBlock(re2.toNewBlock()).build().toByteString())
2315              .build());
2316          break;
2317        case UNLINK:
2318          Event.UnlinkEvent ue = (Event.UnlinkEvent) e;
2319          events.add(InotifyProtos.EventProto.newBuilder()
2320              .setType(InotifyProtos.EventType.EVENT_UNLINK)
2321              .setContents(
2322                  InotifyProtos.UnlinkEventProto.newBuilder()
2323                      .setPath(ue.getPath())
2324                      .setTimestamp(ue.getTimestamp()).build().toByteString()
2325              ).build());
2326          break;
2327        case TRUNCATE:
2328          Event.TruncateEvent te = (Event.TruncateEvent) e;
2329          events.add(InotifyProtos.EventProto.newBuilder()
2330              .setType(InotifyProtos.EventType.EVENT_TRUNCATE)
2331              .setContents(
2332                  InotifyProtos.TruncateEventProto.newBuilder()
2333                      .setPath(te.getPath())
2334                      .setFileSize(te.getFileSize())
2335                      .setTimestamp(te.getTimestamp()).build().toByteString()
2336              ).build());
2337          break;
2338        default:
2339          throw new RuntimeException("Unexpected inotify event: " + e);
2340        }
2341      }
2342      builder.addBatch(InotifyProtos.EventBatchProto.newBuilder().
2343          setTxid(b.getTxid()).
2344          addAllEvents(events));
2345    }
2346    builder.setFirstTxid(el.getFirstTxid());
2347    builder.setLastTxid(el.getLastTxid());
2348    builder.setSyncTxid(el.getSyncTxid());
2349    return GetEditsFromTxidResponseProto.newBuilder().setEventsList(
2350        builder.build()).build();
2351  }
2352
2353  public static CryptoProtocolVersion[] convertCryptoProtocolVersions(
2354      List<CryptoProtocolVersionProto> protos) {
2355    List<CryptoProtocolVersion> versions =
2356        Lists.newArrayListWithCapacity(protos.size());
2357    for (CryptoProtocolVersionProto p: protos) {
2358      versions.add(convert(p));
2359    }
2360    return versions.toArray(new CryptoProtocolVersion[]{});
2361  }
2362
2363  public static HdfsProtos.PerFileEncryptionInfoProto convertPerFileEncInfo(
2364      FileEncryptionInfo info) {
2365    if (info == null) {
2366      return null;
2367    }
2368    return HdfsProtos.PerFileEncryptionInfoProto.newBuilder()
2369        .setKey(getByteString(info.getEncryptedDataEncryptionKey()))
2370        .setIv(getByteString(info.getIV()))
2371        .setEzKeyVersionName(info.getEzKeyVersionName())
2372        .build();
2373  }
2374
2375  public static HdfsProtos.ZoneEncryptionInfoProto convert(
2376      CipherSuite suite, CryptoProtocolVersion version, String keyName) {
2377    if (suite == null || version == null || keyName == null) {
2378      return null;
2379    }
2380    return HdfsProtos.ZoneEncryptionInfoProto.newBuilder()
2381        .setSuite(convert(suite))
2382        .setCryptoProtocolVersion(convert(version))
2383        .setKeyName(keyName)
2384        .build();
2385  }
2386
2387  public static FileEncryptionInfo convert(
2388      HdfsProtos.PerFileEncryptionInfoProto fileProto,
2389      CipherSuite suite, CryptoProtocolVersion version, String keyName) {
2390    if (fileProto == null || suite == null || version == null ||
2391        keyName == null) {
2392      return null;
2393    }
2394    byte[] key = fileProto.getKey().toByteArray();
2395    byte[] iv = fileProto.getIv().toByteArray();
2396    String ezKeyVersionName = fileProto.getEzKeyVersionName();
2397    return new FileEncryptionInfo(suite, version, key, iv, keyName,
2398        ezKeyVersionName);
2399  }
2400
2401  public static DatanodeInfo[] convert(DatanodeInfosProto datanodeInfosProto) {
2402    List<DatanodeInfoProto> proto = datanodeInfosProto.getDatanodesList();
2403    DatanodeInfo[] infos = new DatanodeInfo[proto.size()];
2404    for (int i = 0; i < infos.length; i++) {
2405      infos[i] = convert(proto.get(i));
2406    }
2407    return infos;
2408  }
2409
2410  static List<DatanodeInfosProto> convert(DatanodeInfo[][] targets) {
2411    DatanodeInfosProto[] ret = new DatanodeInfosProto[targets.length];
2412    for (int i = 0; i < targets.length; i++) {
2413      ret[i] = DatanodeInfosProto.newBuilder()
2414          .addAllDatanodes(convert(targets[i])).build();
2415    }
2416    return Arrays.asList(ret);
2417  }
2418
2419  public static EnumSet<AddBlockFlag> convertAddBlockFlags(
2420      List<AddBlockFlagProto> addBlockFlags) {
2421    EnumSet<AddBlockFlag> flags =
2422        EnumSet.noneOf(AddBlockFlag.class);
2423    for (AddBlockFlagProto af : addBlockFlags) {
2424      AddBlockFlag flag = AddBlockFlag.valueOf((short)af.getNumber());
2425      if (flag != null) {
2426        flags.add(flag);
2427      }
2428    }
2429    return flags;
2430  }
2431
2432  public static List<AddBlockFlagProto> convertAddBlockFlags(
2433      EnumSet<AddBlockFlag> flags) {
2434    List<AddBlockFlagProto> ret = new ArrayList<>();
2435    for (AddBlockFlag flag : flags) {
2436      AddBlockFlagProto abfp = AddBlockFlagProto.valueOf(flag.getMode());
2437      if (abfp != null) {
2438        ret.add(abfp);
2439      }
2440    }
2441    return ret;
2442  }
2443}