001    /**
002     * Licensed to the Apache Software Foundation (ASF) under one
003     * or more contributor license agreements.  See the NOTICE file
004     * distributed with this work for additional information
005     * regarding copyright ownership.  The ASF licenses this file
006     * to you under the Apache License, Version 2.0 (the
007     * "License"); you may not use this file except in compliance
008     * with the License.  You may obtain a copy of the License at
009     *
010     *     http://www.apache.org/licenses/LICENSE-2.0
011     *
012     * Unless required by applicable law or agreed to in writing, software
013     * distributed under the License is distributed on an "AS IS" BASIS,
014     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
015     * See the License for the specific language governing permissions and
016     * limitations under the License.
017     */
018    package org.apache.hadoop.hdfs.server.namenode;
019    
020    import java.io.IOException;
021    
022    import org.apache.hadoop.fs.permission.PermissionStatus;
023    import org.apache.hadoop.hdfs.protocol.Block;
024    import org.apache.hadoop.hdfs.server.blockmanagement.BlockInfo;
025    import org.apache.hadoop.hdfs.server.blockmanagement.BlockInfoUnderConstruction;
026    import org.apache.hadoop.hdfs.server.blockmanagement.DatanodeDescriptor;
027    import org.apache.hadoop.hdfs.server.common.HdfsServerConstants.BlockUCState;
028    
029    /**
030     * I-node for file being written.
031     */
032    public class INodeFileUnderConstruction extends INodeFile {
033      private  String clientName;         // lease holder
034      private final String clientMachine;
035      private final DatanodeDescriptor clientNode; // if client is a cluster node too.
036      
037      INodeFileUnderConstruction(PermissionStatus permissions,
038                                 short replication,
039                                 long preferredBlockSize,
040                                 long modTime,
041                                 String clientName,
042                                 String clientMachine,
043                                 DatanodeDescriptor clientNode) {
044        this(permissions, 0, replication, preferredBlockSize, modTime,
045            clientName, clientMachine, clientNode);
046      }
047    
048      INodeFileUnderConstruction(PermissionStatus permissions,
049                                 int nrBlocks,
050                                 short replication,
051                                 long preferredBlockSize,
052                                 long modTime,
053                                 String clientName,
054                                 String clientMachine,
055                                 DatanodeDescriptor clientNode) {
056        super(permissions.applyUMask(UMASK), nrBlocks, replication,
057            modTime, modTime, preferredBlockSize);
058        this.clientName = clientName;
059        this.clientMachine = clientMachine;
060        this.clientNode = clientNode;
061      }
062    
063      INodeFileUnderConstruction(byte[] name,
064                                 short blockReplication,
065                                 long modificationTime,
066                                 long preferredBlockSize,
067                                 BlockInfo[] blocks,
068                                 PermissionStatus perm,
069                                 String clientName,
070                                 String clientMachine,
071                                 DatanodeDescriptor clientNode) {
072        super(perm, blocks, blockReplication, modificationTime, modificationTime,
073              preferredBlockSize);
074        setLocalName(name);
075        this.clientName = clientName;
076        this.clientMachine = clientMachine;
077        this.clientNode = clientNode;
078      }
079    
080      String getClientName() {
081        return clientName;
082      }
083    
084      void setClientName(String clientName) {
085        this.clientName = clientName;
086      }
087    
088      String getClientMachine() {
089        return clientMachine;
090      }
091    
092      DatanodeDescriptor getClientNode() {
093        return clientNode;
094      }
095    
096      /**
097       * Is this inode being constructed?
098       */
099      @Override
100      public boolean isUnderConstruction() {
101        return true;
102      }
103    
104      //
105      // converts a INodeFileUnderConstruction into a INodeFile
106      // use the modification time as the access time
107      //
108      INodeFile convertToInodeFile() {
109        INodeFile obj = new INodeFile(getPermissionStatus(),
110                                      getBlocks(),
111                                      getReplication(),
112                                      getModificationTime(),
113                                      getModificationTime(),
114                                      getPreferredBlockSize());
115        return obj;
116        
117      }
118    
119      /**
120       * Remove a block from the block list. This block should be
121       * the last one on the list.
122       */
123      void removeLastBlock(Block oldblock) throws IOException {
124        if (blocks == null) {
125          throw new IOException("Trying to delete non-existant block " + oldblock);
126        }
127        int size_1 = blocks.length - 1;
128        if (!blocks[size_1].equals(oldblock)) {
129          throw new IOException("Trying to delete non-last block " + oldblock);
130        }
131    
132        //copy to a new list
133        BlockInfo[] newlist = new BlockInfo[size_1];
134        System.arraycopy(blocks, 0, newlist, 0, size_1);
135        blocks = newlist;
136      }
137    
138      /**
139       * Convert the last block of the file to an under-construction block.
140       * Set its locations.
141       */
142      public BlockInfoUnderConstruction setLastBlock(BlockInfo lastBlock,
143                                              DatanodeDescriptor[] targets)
144      throws IOException {
145        if (blocks == null || blocks.length == 0) {
146          throw new IOException("Trying to update non-existant block. " +
147              "File is empty.");
148        }
149        BlockInfoUnderConstruction ucBlock =
150          lastBlock.convertToBlockUnderConstruction(
151              BlockUCState.UNDER_CONSTRUCTION, targets);
152        ucBlock.setINode(this);
153        setBlock(numBlocks()-1, ucBlock);
154        return ucBlock;
155      }
156    }