1 29 package net.metanotion.io.block; 30 31 import java.io.File ; 32 import java.io.IOException ; 33 import java.io.RandomAccessFile ; 34 import java.util.HashMap ; 35 import java.util.Iterator ; 36 import java.util.Set ; 37 38 import net.metanotion.io.RAIFile; 39 import net.metanotion.io.RandomAccessInterface; 40 import net.metanotion.io.Serializer; 41 import net.metanotion.io.data.IntBytes; 42 import net.metanotion.io.data.LongBytes; 43 import net.metanotion.io.data.NullBytes; 44 import net.metanotion.io.data.StringBytes; 45 46 import net.metanotion.io.block.index.BSkipList; 47 48 class CorruptFileException extends IOException { } 49 class BadFileFormatException extends IOException { } 50 class BadVersionException extends IOException { } 51 52 public class BlockFile { 53 public static final long PAGESIZE = 1024; 54 public static final long OFFSET_MOUNTED = 20; 55 56 public RandomAccessInterface file; 57 58 private long magicBytes = 0x3141deadbeef0100L; 59 private long fileLen = PAGESIZE * 2; 60 private int freeListStart = 0; 61 private short mounted = 0; 62 public short spanSize = 127; 63 64 private BSkipList metaIndex = null; 65 private HashMap openIndices = new HashMap (); 66 67 private void mount() throws IOException { 68 file.seek(BlockFile.OFFSET_MOUNTED); 69 mounted = 1; 70 file.writeShort(mounted); 71 } 72 73 private void writeSuperBlock() throws IOException { 74 file.seek(0); 75 file.writeLong( magicBytes); 76 file.writeLong( fileLen); 77 file.writeInt( freeListStart); 78 file.writeShort(mounted); 79 file.writeShort(spanSize); 80 } 81 82 private void readSuperBlock() throws IOException { 83 file.seek(0); 84 magicBytes = file.readLong(); 85 fileLen = file.readLong(); 86 freeListStart = file.readInt(); 87 mounted = file.readShort(); 88 spanSize = file.readShort(); 89 } 90 91 public static void main(String args[]) { 92 try { 93 RAIFile raif = new RAIFile(new File (args[0]), true, true); 94 BlockFile bf = new BlockFile(raif, true); 95 96 bf.makeIndex("foo", new NullBytes(), new NullBytes()); 98 99 100 BSkipList b = bf.getIndex("foo", new NullBytes(), new NullBytes()); 101 System.out.println(bf.allocPage()); 102 103 bf.close(); 104 raif.close(); 105 } catch (Exception e) { 106 e.printStackTrace(); 107 } 108 } 109 110 public int writeMultiPageData(byte[] data, int page, int[] curPageOff, int[] nextPage) throws IOException { 111 int pageCounter = curPageOff[0]; 112 int curNextPage = nextPage[0]; 113 int curPage = page; 114 int dct = 0; 115 while(dct < data.length) { 116 int len = ((int) BlockFile.PAGESIZE) - pageCounter; 117 if(len <= 0) { 118 if(curNextPage==0) { 119 curNextPage = this.allocPage(); 120 BlockFile.pageSeek(this.file, curNextPage); 121 this.file.writeInt(0); 122 BlockFile.pageSeek(this.file, curPage); 123 this.file.writeInt(curNextPage); 124 } 125 BlockFile.pageSeek(this.file, curNextPage); 126 curPage = curNextPage; 127 curNextPage = this.file.readInt(); 128 pageCounter = 4; 129 len = ((int) BlockFile.PAGESIZE) - pageCounter; 130 } 131 this.file.write(data, dct, Math.min(len, data.length - dct)); 132 pageCounter += Math.min(len, data.length - dct); 133 dct += Math.min(len, data.length - dct); 134 } 135 nextPage[0] = curNextPage; 136 curPageOff[0] = pageCounter; 137 return curPage; 138 } 139 140 public int readMultiPageData(byte[] arr, int page, int[] curPageOff, int[] nextPage) throws IOException { 141 int pageCounter = curPageOff[0]; 142 int curNextPage = nextPage[0]; 143 int curPage = page; 144 int dct = 0; 145 int res; 146 while(dct < arr.length) { 147 int len = ((int) BlockFile.PAGESIZE) - pageCounter; 148 if(len <= 0) { 149 BlockFile.pageSeek(this.file, curNextPage); 150 curPage = curNextPage; 151 curNextPage = this.file.readInt(); 152 pageCounter = 4; 153 len = ((int) BlockFile.PAGESIZE) - pageCounter; 154 } 155 res = this.file.read(arr, dct, Math.min(len, arr.length - dct)); 156 if(res == -1) { throw new IOException (); } 157 pageCounter += Math.min(len, arr.length - dct); 158 dct += res; 159 } 160 nextPage[0] = curNextPage; 161 curPageOff[0] = pageCounter; 162 return curPage; 163 } 164 165 public BlockFile(RandomAccessInterface rai) throws IOException { this(rai, false); } 166 public BlockFile(RandomAccessFile raf) throws IOException { this(new RAIFile(raf), false); } 167 public BlockFile(RandomAccessFile raf, boolean init) throws IOException { this(new RAIFile(raf), init); } 168 public BlockFile(File f, boolean init) throws IOException { this(new RAIFile(f, true, true), init); } 169 170 public BlockFile(RandomAccessInterface rai, boolean init) throws IOException { 171 if(rai==null) { throw new NullPointerException (); } 172 173 file = rai; 174 175 if(init) { 176 file.setLength(fileLen); 177 writeSuperBlock(); 178 BSkipList.init(this, 2, spanSize); 179 } 180 181 readSuperBlock(); 182 if(magicBytes != 0x3141deadbeef0100L) { 183 if((magicBytes & 0x3141deadbeef0000L) == 0x3141deadbeef0000L) { 184 throw new BadVersionException(); 185 } else { 186 throw new BadFileFormatException(); 187 } 188 } 189 if(fileLen != file.length()) { throw new CorruptFileException(); } 191 mount(); 192 193 metaIndex = new BSkipList(spanSize, this, 2, new StringBytes(), new IntBytes()); 194 } 195 196 197 public static void pageSeek(RandomAccessInterface file, int page) throws IOException { file.seek((((long)page) - 1L) * BlockFile.PAGESIZE ); } 198 199 public int allocPage() throws IOException { 200 if(freeListStart != 0) { 201 FreeListBlock flb = new FreeListBlock(file, freeListStart); 202 if(flb.len > 0) { 203 flb.len = flb.len - 1; 204 int page = flb.branches[flb.len]; 205 flb.writeBlock(); 206 return page; 207 } else { 208 freeListStart = flb.nextPage; 209 writeSuperBlock(); 210 return flb.page; 211 } 212 } 213 long offset = file.length(); 214 fileLen = offset + BlockFile.PAGESIZE; 215 file.setLength(fileLen); 216 writeSuperBlock(); 217 return ((int) ((long) (offset / BlockFile.PAGESIZE))) + 1; 218 } 219 220 public void freePage(int page) throws IOException { 221 System.out.println("Free Page " + page); 222 if(freeListStart == 0) { 223 freeListStart = page; 224 FreeListBlock.initPage(file, page); 225 writeSuperBlock(); 226 return; 227 } 228 FreeListBlock flb = new FreeListBlock(file, freeListStart); 229 if(flb.isFull()) { 230 FreeListBlock.initPage(file, page); 231 if(flb.nextPage == 0) { 232 flb.nextPage = page; 233 flb.writeBlock(); 234 return; 235 } else { 236 flb = new FreeListBlock(file, page); 237 flb.nextPage = freeListStart; 238 flb.writeBlock(); 239 freeListStart = page; 240 writeSuperBlock(); 241 return; 242 } 243 } 244 flb.addPage(page); 245 flb.writeBlock(); 246 } 247 248 public BSkipList getIndex(String name, Serializer key, Serializer val) throws IOException { 249 Integer page = (Integer ) metaIndex.get(name); 250 if (page == null) { return null; } 251 BSkipList bsl = new BSkipList(spanSize, this, page.intValue(), key, val); 252 openIndices.put(name, bsl); 253 return bsl; 254 } 255 256 public BSkipList makeIndex(String name, Serializer key, Serializer val) throws IOException { 257 if(metaIndex.get(name) != null) { throw new IOException ("Index already exists"); } 258 int page = allocPage(); 259 metaIndex.put(name, new Integer (page)); 260 BSkipList.init(this, page, spanSize); 261 BSkipList bsl = new BSkipList(spanSize, this, page, key, val); 262 openIndices.put(name, bsl); 263 return bsl; 264 } 265 266 public void delIndex(String name) throws IOException { 267 Integer page = (Integer ) metaIndex.remove(name); 268 if (page == null) { return; } 269 NullBytes nb = new NullBytes(); 270 BSkipList bsl = new BSkipList(spanSize, this, page.intValue(), nb, nb); 271 bsl.delete(); 272 } 273 274 public void close() throws IOException { 275 metaIndex.close(); 276 metaIndex = null; 277 278 Set oi = openIndices.keySet(); 279 Iterator i = oi.iterator(); 280 Object k; 281 while(i.hasNext()) { 282 k = i.next(); 283 BSkipList bsl = (BSkipList) openIndices.get(k); 284 bsl.close(); 285 } 286 287 file.seek(BlockFile.OFFSET_MOUNTED); 289 file.writeShort(0); 290 } 291 } 292 | Popular Tags |