public void merge(String parity, String source, String codecId, int[] checksums) 
    throws IOException {
    if(FSNamesystem.LOG.isDebugEnabled()) {
      FSNamesystem.LOG.debug("merge " + parity + " to " + source);
    }
    if (isInSafeMode()) {
      throw new SafeModeException("merge: cannot merge " + parity + " to " 
                                  + source, safeMode);
    }
    // Verify parity and source 
    if (source == null || source.isEmpty() || parity == null || parity.isEmpty()) {
      throw new IOException(
          "merge: source file name or parity file name is empty");
    }
    // Verify checksums
    if (checksums == null || checksums.length == 0) {
      throw new IOException("merge: checksum array is empty or null");
    }
    // Verify codec
    RaidCodec codec = RaidCodec.getCodec(codecId);
    if (codec == null) {
      throw new IOException("merge: codec " + codecId + " doesn't exist");
    }
    
    INode[] sourceINodes = dir.getExistingPathINodes(source);
    INode[] parityINodes = dir.getExistingPathINodes(parity);
    writeLock();
    try {
      // write permissions for the source
      if (isPermissionEnabled) {
        if (isPermissionCheckingEnabled(sourceINodes)) {
          checkPathAccess(source, sourceINodes, FsAction.WRITE); 
        }
        if (isPermissionCheckingEnabled(parityINodes)) {
          checkPathAccess(parity, parityINodes, FsAction.READ); // read the file
          checkParentAccess(parity, parityINodes, FsAction.WRITE); // for delete
        }
      }
      INode sinode = sourceINodes[sourceINodes.length - 1];
      INode pinode = parityINodes[parityINodes.length - 1];
      
      if (sinode == null || pinode == null) {
        throw new IOException(
            "merge: source file or parity file doesn't exist");
      }
      
      if (sinode.isUnderConstruction() || pinode.isUnderConstruction()) {
        throw new IOException(
            "merge: source file or parity file is under construction");
      }
      
      if (sinode.isDirectory() || pinode.isDirectory()) {
        throw new IOException(
            "merge: source file or parity file is a directory");
      }
      
      if (sinode instanceof INodeHardLinkFile ||
          pinode instanceof INodeHardLinkFile) { 
        throw new IOException("merge: source file or parity file is hardlinked");  
      }

      INodeFile sourceINode = (INodeFile) sinode;
      INodeFile parityINode = (INodeFile) pinode;

      if (sourceINode.getStorageType() != StorageType.REGULAR_STORAGE
          || parityINode.getStorageType() != StorageType.REGULAR_STORAGE) {
        throw new IOException(
            "merge: source file or parity file doesn't support merge");
      }
      if (sourceINode.getModificationTime() != parityINode.getModificationTime()) {
        throw new IOException(
            "merge: source file and parity file doesn't have the same modification time");
      }
      if (parityINode.getReplication() != codec.parityReplication) {
        throw new IOException(
            "merge: parity file's replication doesn't match codec's parity replication");
      }
      
      BlockInfo[] sourceBlks = sourceINode.getBlocks();
      BlockInfo[] parityBlks = parityINode.getBlocks();
      
      if (sourceBlks == null || sourceBlks.length == 0) {
        throw new IOException("merge: " + source + " is empty");
      }
      if (parityBlks == null || parityBlks.length == 0) {
        throw new IOException("merge: " + parity + " is empty");
      }
      if (checksums.length != sourceBlks.length) {
        throw new IOException("merge: checksum length " + checksums.length +
            " doesn't match number of source blocks " + sourceBlks.length);
      }
      int expectedParityBlocks = codec.getNumStripes(sourceBlks.length) 
          * codec.numParityBlocks;
      if (expectedParityBlocks != parityBlks.length) {
        throw new IOException("merge: expect parity blocks " + 
            expectedParityBlocks + " doesn't match number of parity blocks " + 
            parityBlks.length);
      }

      if(NameNode.stateChangeLog.isDebugEnabled()) {
        NameNode.stateChangeLog.debug("DIR* NameSystem.merge: " +
            parity + " to " + source);
      }
      
      dir.mergeInternal(parityINodes, sourceINodes, parity, source, codec,
                        checksums);
    } finally {
      writeUnlock();
    }
    getEditLog().logSync();

    if (auditLog.isInfoEnabled()) {
      logAuditEvent(getCurrentUGI(),
                    Server.getRemoteIp(),
                    "merge", parity, source, 
                    getLastINode(sourceINodes));
    }
  }
public void merge ( String parity , String source , String codecId , int [ ] checksums ) throws IOException { if ( FSNamesystem . LOG . isDebugEnabled ( ) ) { FSNamesystem . LOG . debug ( "merge " + parity + " to " + source ) ; } if ( isInSafeMode ( ) ) { throw new SafeModeException ( "merge: cannot merge " + parity + " to " + source , safeMode ) ; } if ( source == null || source . isEmpty ( ) || parity == null || parity . isEmpty ( ) ) { throw new IOException ( "merge: source file name or parity file name is empty" ) ; } if ( checksums == null || checksums . length == 0 ) { throw new IOException ( "merge: checksum array is empty or null" ) ; } RaidCodec codec = RaidCodec . getCodec ( codecId ) ; if ( codec == null ) { throw new IOException ( "merge: codec " + codecId + " doesn't exist" ) ; } INode [ ] sourceINodes = dir . getExistingPathINodes ( source ) ; INode [ ] parityINodes = dir . getExistingPathINodes ( parity ) ; writeLock ( ) ; try { if ( isPermissionEnabled ) { if ( isPermissionCheckingEnabled ( sourceINodes ) ) { checkPathAccess ( source , sourceINodes , FsAction . WRITE ) ; } if ( isPermissionCheckingEnabled ( parityINodes ) ) { checkPathAccess ( parity , parityINodes , FsAction . READ ) ; checkParentAccess ( parity , parityINodes , FsAction . WRITE ) ; } } INode sinode = sourceINodes [ sourceINodes . length - 1 ] ; INode pinode = parityINodes [ parityINodes . length - 1 ] ; if ( sinode == null || pinode == null ) { throw new IOException ( "merge: source file or parity file doesn't exist" ) ; } if ( sinode . isUnderConstruction ( ) || pinode . isUnderConstruction ( ) ) { throw new IOException ( "merge: source file or parity file is under construction" ) ; } if ( sinode . isDirectory ( ) || pinode . isDirectory ( ) ) { throw new IOException ( "merge: source file or parity file is a directory" ) ; } if ( sinode instanceof INodeHardLinkFile || pinode instanceof INodeHardLinkFile ) { throw new IOException ( "merge: source file or parity file is hardlinked" ) ; } INodeFile sourceINode = ( INodeFile ) sinode ; INodeFile parityINode = ( INodeFile ) pinode ; if ( sourceINode . getStorageType ( ) != StorageType . REGULAR_STORAGE || parityINode . getStorageType ( ) != StorageType . REGULAR_STORAGE ) { throw new IOException ( "merge: source file or parity file doesn't support merge" ) ; } if ( sourceINode . getModificationTime ( ) != parityINode . getModificationTime ( ) ) { throw new IOException ( "merge: source file and parity file doesn't have the same modification time" ) ; } if ( parityINode . getReplication ( ) != codec . parityReplication ) { throw new IOException ( "merge: parity file's replication doesn't match codec's parity replication" ) ; } BlockInfo [ ] sourceBlks = sourceINode . getBlocks ( ) ; BlockInfo [ ] parityBlks = parityINode . getBlocks ( ) ; if ( sourceBlks == null || sourceBlks . length == 0 ) { throw new IOException ( "merge: " + source + " is empty" ) ; } if ( parityBlks == null || parityBlks . length == 0 ) { throw new IOException ( "merge: " + parity + " is empty" ) ; } if ( checksums . length != sourceBlks . length ) { throw new IOException ( "merge: checksum length " + checksums . length + " doesn't match number of source blocks " + sourceBlks . length ) ; } int expectedParityBlocks = codec . getNumStripes ( sourceBlks . length ) * codec . numParityBlocks ; if ( expectedParityBlocks != parityBlks . length ) { throw new IOException ( "merge: expect parity blocks " + expectedParityBlocks + " doesn't match number of parity blocks " + parityBlks . length ) ; } if ( NameNode . stateChangeLog . isDebugEnabled ( ) ) { NameNode . stateChangeLog . debug ( "DIR* NameSystem.merge: " + parity + " to " + source ) ; } dir . mergeInternal ( parityINodes , sourceINodes , parity , source , codec , checksums ) ; } finally { writeUnlock ( ) ; } getEditLog ( ) . logSync ( ) ; if ( auditLog . isInfoEnabled ( ) ) { logAuditEvent ( getCurrentUGI ( ) , Server . getRemoteIp ( ) , "merge" , parity , source , getLastINode ( sourceINodes ) ) ; } }
Merge parity file into source file to convert source file's storage format
from INodeRegularStorage into INodeRaidStorage.
checksums will be added to each block of the source file
return true if merge succeeds