SET EC調試版

斷點調試

[hadoop@hadoop1 hadoop]$ hdfs ec -setPolicy -path /ec1 -policy RS-3-2-1024k

源碼如下:

//FSDirErasureCodingOp#setErasureCodingPolicy
static FileStatus setErasureCodingPolicy(final FSNamesystem fsn,
      final String srcArg, final String ecPolicyName,
      final FSPermissionChecker pc, final boolean logRetryCache)
      throws IOException, AccessControlException {
    assert fsn.hasWriteLock();

    String src = srcArg;
    FSDirectory fsd = fsn.getFSDirectory();
    final INodesInPath iip;
    List<XAttr> xAttrs;
    fsd.writeLock();
    try {
      ErasureCodingPolicy ecPolicy = getErasureCodingPolicyByName(fsn,
          ecPolicyName);
      iip = fsd.resolvePath(pc, src, DirOp.WRITE_LINK);
      // Write access is required to set erasure coding policy
      if (fsd.isPermissionEnabled()) {
        fsd.checkPathAccess(pc, iip, FsAction.WRITE);
      }
      src = iip.getPath();
      xAttrs = setErasureCodingPolicyXAttr(fsn, iip, ecPolicy);
    } finally {
      fsd.writeUnlock();
    }
    fsn.getEditLog().logSetXAttrs(src, xAttrs, logRetryCache);
    return fsd.getAuditFileInfo(iip);
  }

可以看到,主要流程:
根據名稱解析到ec策略 --> 獲得iip --> 在iip上設置特性 --> 記錄到editlog
調試如下:
在這裏插入圖片描述
通過ec名稱解析到的ECPolicy:
在這裏插入圖片描述
通過path獲得INodeInPath:iip

INodesInPath: path = /ec1
  inodes = [, ec1], length=2
  isSnapshot        = false
  snapshotId        = 2147483646

srcPath 和 iip 之間可以相互轉化。
在這裏插入圖片描述


進入setErasureCodingPolicyXAttr代碼:

private static List<XAttr> setErasureCodingPolicyXAttr(final FSNamesystem fsn,
      final INodesInPath srcIIP, ErasureCodingPolicy ecPolicy) throws IOException {
    FSDirectory fsd = fsn.getFSDirectory();
    assert fsd.hasWriteLock();
    Preconditions.checkNotNull(srcIIP, "INodes cannot be null");
    Preconditions.checkNotNull(ecPolicy, "EC policy cannot be null");
    String src = srcIIP.getPath();
    //從iip中得到最後一個node節點,設置屬性實則設置在最後一個節點上
    final INode inode = srcIIP.getLastINode();
    if (inode == null) {
      throw new FileNotFoundException("Path not found: " + srcIIP.getPath());
    }
    if (!inode.isDirectory()) {
      throw new IOException("Attempt to set an erasure coding policy " +
          "for a file " + src);
    }

    final XAttr ecXAttr;
    DataOutputStream dOut = null;
    try {
      //這裏關鍵 通過名稱轉化爲XATTR
      ByteArrayOutputStream bOut = new ByteArrayOutputStream();
      dOut = new DataOutputStream(bOut);
      WritableUtils.writeString(dOut, ecPolicy.getName());
      ecXAttr = XAttrHelper.buildXAttr(XATTR_ERASURECODING_POLICY,
          bOut.toByteArray());
    } finally {
      IOUtils.closeStream(dOut);
    }
    // check whether the directory already has an erasure coding policy
    // directly on itself.
    final Boolean hasEcXAttr =
        getErasureCodingPolicyXAttrForINode(fsn, inode) == null ? false : true;
    final List<XAttr> xattrs = Lists.newArrayListWithCapacity(1);
    xattrs.add(ecXAttr);
    final EnumSet<XAttrSetFlag> flag = hasEcXAttr ?
        EnumSet.of(XAttrSetFlag.REPLACE) : EnumSet.of(XAttrSetFlag.CREATE);
    FSDirXAttrOp.unprotectedSetXAttrs(fsd, srcIIP, xattrs, flag);
    return xattrs;
  }

INode的屬性是INodeDirectory:
在這裏插入圖片描述
在這裏插入圖片描述

新加入的XAttr內容爲:

XAttr [ns=SYSTEM, name=hdfs.erasurecoding.policy, value=[0, 0, 0, 12, 82, 83, 45, 51, 45, 50, 45, 49, 48, 50, 52, 107]]

在這裏插入圖片描述


檢查inode是否已經設置了其他EC屬性。如果沒有,這給創建標識;如果有,則給替換標識。

    final Boolean hasEcXAttr =
        getErasureCodingPolicyXAttrForINode(fsn, inode) == null ? false : true;
    final List<XAttr> xattrs = Lists.newArrayListWithCapacity(1);
    xattrs.add(ecXAttr);
    final EnumSet<XAttrSetFlag> flag = hasEcXAttr ?
        EnumSet.of(XAttrSetFlag.REPLACE) : EnumSet.of(XAttrSetFlag.CREATE);
    FSDirXAttrOp.unprotectedSetXAttrs(fsd, srcIIP, xattrs, flag);
    return xattrs;

設置屬性 FSDirXAttrOp.unprotectedSetXAttrs(fsd, srcIIP, xattrs, flag); 代碼如下:

  static INode unprotectedSetXAttrs(
      FSDirectory fsd, final INodesInPath iip, final List<XAttr> xAttrs,
      final EnumSet<XAttrSetFlag> flag)
      throws IOException {
    assert fsd.hasWriteLock();
    INode inode = FSDirectory.resolveLastINode(iip);
    //查詢這個節點已經存在的擴展特性
    List<XAttr> existingXAttrs = XAttrStorage.readINodeXAttrs(inode);
    List<XAttr> newXAttrs = setINodeXAttrs(fsd, existingXAttrs, xAttrs, flag);
    final boolean isFile = inode.isFile();

    //遍歷每個屬性
    for (XAttr xattr : newXAttrs) {
      final String xaName = XAttrHelper.getPrefixedName(xattr);

      /*
       * If we're adding the encryption zone xattr, then add src to the list
       * of encryption zones.
       */
      //如果是ozone相關額外做些工作 
      if (CRYPTO_XATTR_ENCRYPTION_ZONE.equals(xaName)) {
        final HdfsProtos.ZoneEncryptionInfoProto ezProto =
            HdfsProtos.ZoneEncryptionInfoProto.parseFrom(xattr.getValue());
        fsd.ezManager.addEncryptionZone(inode.getId(),
            PBHelperClient.convert(ezProto.getSuite()),
            PBHelperClient.convert(ezProto.getCryptoProtocolVersion()),
            ezProto.getKeyName());

        if (ezProto.hasReencryptionProto()) {
          ReencryptionInfoProto reProto = ezProto.getReencryptionProto();
          fsd.ezManager.getReencryptionStatus()
              .updateZoneStatus(inode.getId(), iip.getPath(), reProto);
        }
      }

      // Add inode id to movement queue if xattrs contain satisfy xattr.
      if (XATTR_SATISFY_STORAGE_POLICY.equals(xaName)) {
        FSDirSatisfyStoragePolicyOp.unprotectedSatisfyStoragePolicy(inode, fsd);
        continue;
      }

      if (!isFile && SECURITY_XATTR_UNREADABLE_BY_SUPERUSER.equals(xaName)) {
        throw new IOException("Can only set '" +
            SECURITY_XATTR_UNREADABLE_BY_SUPERUSER + "' on a file.");
      }
    }

    XAttrStorage.updateINodeXAttrs(inode, newXAttrs, iip.getLatestSnapshotId());
    return inode;
  }

需要設置的屬性是xAttrs,如下:
在這裏插入圖片描述
現存的屬性existingXAttrs爲空。

通過調用XAttrStorage.updateINodeXAttrs,將新的屬性集合設置到inode上。

public static void updateINodeXAttrs(INode inode, 
      List<XAttr> xAttrs, int snapshotId) throws QuotaExceededException {
    if (inode.getXAttrFeature() != null) {
      inode.removeXAttrFeature(snapshotId);
    }
    if (xAttrs == null || xAttrs.isEmpty()) {
      return;
    }
    inode.addXAttrFeature(new XAttrFeature(xAttrs), snapshotId);
  }

在這裏插入圖片描述
通過XAttr來構建 XAttrFeature, 然後INode來添加屬性。
XAttr被格式化成Bytes類型。

// INodeWithAdditionalFields
  protected void addFeature(Feature f) {
    int size = features.length;
    Feature[] arr = new Feature[size + 1];
    if (size != 0) {
      System.arraycopy(features, 0, arr, 0, size);
    }
    arr[size] = f;
    features = arr;
  }

在這裏插入圖片描述

原來的feature爲0,現在有了1個,所以一共是1個。
爲什麼XAttr裏面還有兩個屬性,一個是attrs,一個是xAttrs呢?並且爲什麼xAttrs=null,不是應該有值纔對嗎???
在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章