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.server.namenode;
019
020import java.io.IOException;
021
022import org.apache.hadoop.fs.permission.PermissionStatus;
023import org.apache.hadoop.hdfs.protocol.Block;
024import org.apache.hadoop.hdfs.server.blockmanagement.BlockInfo;
025import org.apache.hadoop.hdfs.server.blockmanagement.BlockInfoUnderConstruction;
026import org.apache.hadoop.hdfs.server.blockmanagement.DatanodeDescriptor;
027import org.apache.hadoop.hdfs.server.common.HdfsServerConstants.BlockUCState;
028
029/**
030 * I-node for file being written.
031 */
032public 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}