1 2 3 package net.nutch.ndfs; 4 5 import java.io.*; 6 import java.util.*; 7 8 import net.nutch.fs.*; 9 import net.nutch.util.*; 10 11 17 public class FSDataset implements FSConstants { 18 22 class FSDir { 23 File dir; 24 FSDir children[]; 25 26 28 public FSDir(File dir) { 29 this.dir = dir; 30 this.children = null; 31 } 32 33 35 public File getDirName() { 36 return dir; 37 } 38 39 41 public FSDir[] getChildren() { 42 return children; 43 } 44 45 47 public void addBlock(Block b, File src) { 48 addBlock(b, src, b.getBlockId(), 0); 49 } 50 51 53 void addBlock(Block b, File src, long blkid, int depth) { 54 if (children == null) { 58 src.renameTo(new File(dir, b.getBlockName())); 59 60 65 99 } else { 100 children[getHalfByte(blkid, depth)].addBlock(b, src, blkid, depth+1); 102 } 103 } 104 105 109 public void getBlockInfo(TreeSet blockSet) { 110 if (children != null) { 111 for (int i = 0; i < children.length; i++) { 112 children[i].getBlockInfo(blockSet); 113 } 114 } 115 116 File blockFiles[] = dir.listFiles(); 117 for (int i = 0; i < blockFiles.length; i++) { 118 if (Block.isBlockFilename(blockFiles[i])) { 119 blockSet.add(new Block(blockFiles[i], blockFiles[i].length())); 120 } 121 } 122 } 123 124 127 public File getBlockFilename(Block b) { 128 return getBlockFilename(b, b.getBlockId(), 0); 129 } 130 131 134 public long getTotalUsedBytes() { 135 long total = 0; 136 File blocks[] = dir.listFiles(); 137 for (int i = 0; i < blocks.length; i++) { 138 total += blocks[i].length(); 139 } 140 return total; 141 } 142 143 146 private File getBlockFilename(Block b, long blkid, int depth) { 147 if (children == null) { 148 return new File(dir, b.getBlockName()); 149 } else { 150 return children[getHalfByte(blkid, depth)].getBlockFilename(b, blkid, depth+1); 156 } 157 } 158 159 163 private int getHalfByte(long blkid, int halfByteIndex) { 164 blkid = blkid >> ((15 - halfByteIndex) * 4); 165 return (int) ((0x000000000000000F) & blkid); 166 } 167 } 168 169 175 File data = null, tmp = null; 176 long capacity = 0, used = 0, reserved = 0; 177 FSDir dirTree; 178 TreeSet ongoingCreates = new TreeSet(); 179 180 183 public FSDataset(File dir, long capacity) throws IOException { 184 this.capacity = capacity; 185 this.data = new File(dir, "data"); 186 if (! data.exists()) { 187 data.mkdirs(); 188 } 189 this.tmp = new File(dir, "tmp"); 190 if (tmp.exists()) { 191 FileUtil.fullyDelete(tmp); 192 } 193 this.tmp.mkdirs(); 194 this.dirTree = new FSDir(data); 195 this.used = dirTree.getTotalUsedBytes(); 196 } 197 198 201 public long getCapacity() { 202 return capacity; 203 } 204 205 208 public long getRemaining() { 209 long remaining = capacity - used - reserved; 210 if (remaining < 0) { 211 remaining = 0; 212 } 213 return remaining; 214 } 215 216 219 public long getLength(Block b) throws IOException { 220 if (! isValidBlock(b)) { 221 throw new IOException("Block " + b + " is not valid."); 222 } 223 File f = getFile(b); 224 return f.length(); 225 } 226 227 230 public InputStream getBlockData(Block b) throws IOException { 231 if (! isValidBlock(b)) { 232 throw new IOException("Block " + b + " is not valid."); 233 } 234 return new FileInputStream(getFile(b)); 235 } 236 237 240 public boolean startBlock(Block b) throws IOException { 241 if (isValidBlock(b)) { 245 throw new IOException("Block " + b + " is valid, and cannot be created."); 246 } 247 return true; 248 } 249 250 253 public OutputStream writeToBlock(Block b) throws IOException { 254 if (isValidBlock(b)) { 258 throw new IOException("Block " + b + " is valid, and cannot be written to."); 259 } 260 261 File f = null; 265 synchronized (ongoingCreates) { 266 if (ongoingCreates.contains(b)) { 270 throw new IOException("Block " + b + " has already been started (though not completed), and thus cannot be created."); 271 } 272 273 if (capacity - used - reserved < BLOCK_SIZE) { 277 throw new IOException("Insufficient space for an additional block"); 278 } 279 280 ongoingCreates.add(b); 285 reserved += BLOCK_SIZE; 286 f = getTmpFile(b); 287 288 if (f.exists()) { 289 throw new IOException("Unexpected problem in startBlock() for " + b + ". File " + f + " should not be present, but is."); 290 } 291 } 292 293 if (!f.createNewFile()) { 297 throw new IOException("Unexpected problem in startBlock() for " + b + ". File " + f + " should be creatable, but is already present."); 298 } 299 300 return new FileOutputStream(f); 306 } 307 308 316 319 public void finalizeBlock(Block b) throws IOException { 320 File f = getTmpFile(b); 321 if (! f.exists()) { 322 throw new IOException("No temporary file " + f + " for block " + b); 323 } 324 325 synchronized (ongoingCreates) { 326 if (! ongoingCreates.contains(b)) { 330 throw new IOException("Tried to finalize block " + b + ", but not in ongoingCreates table"); 331 } 332 333 long finalLen = f.length(); 334 b.setNumBytes(finalLen); 335 336 dirTree.addBlock(b, f); 342 343 if (! ongoingCreates.remove(b)) { 347 throw new IOException("Tried to finalize block " + b + ", but could not find it in ongoingCreates after file-move!"); 348 } 349 reserved -= BLOCK_SIZE; 350 used += finalLen; 351 } 352 } 353 354 357 public Block[] getBlockReport() { 358 TreeSet blockSet = new TreeSet(); 359 dirTree.getBlockInfo(blockSet); 360 Block blockTable[] = new Block[blockSet.size()]; 361 int i = 0; 362 for (Iterator it = blockSet.iterator(); it.hasNext(); i++) { 363 blockTable[i] = (Block) it.next(); 364 } 365 return blockTable; 366 } 367 368 371 public boolean isValidBlock(Block b) { 372 File f = getFile(b); 373 if (f.exists()) { 374 return true; 375 } else { 376 return false; 377 } 378 } 379 380 385 public void invalidate(Block invalidBlks[]) throws IOException { 386 for (int i = 0; i < invalidBlks.length; i++) { 387 File f = getFile(invalidBlks[i]); 388 389 long len = f.length(); 390 if (!f.delete()) { 391 throw new IOException("Unexpected error trying to delete block " + invalidBlks[i] + " at file " + f); 392 } 393 used -= len; 394 } 395 } 396 397 400 File getFile(Block b) { 401 return dirTree.getBlockFilename(b); 403 } 404 405 408 File getTmpFile(Block b) { 409 return new File(tmp, b.getBlockName()); 411 } 412 } 413 | Popular Tags |