2 * To change this template, choose Tools | Templates
3 * and open the template in the editor.
5 package TransactionalIO.core;
7 import TransactionalIO.Utilities.Conversions;
8 import TransactionalIO.Utilities.Range;
9 import TransactionalIO.exceptions.AbortedException;
10 import TransactionalIO.exceptions.PanicException;
11 import TransactionalIO.benchmarks.benchmark;
12 import TransactionalIO.core.ExtendedTransaction.Status;
13 import TransactionalIO.interfaces.BlockAccessModesEnum;
14 import TransactionalIO.interfaces.OffsetDependency;
15 import com.sun.org.apache.bcel.internal.generic.IFEQ;
16 import java.io.DataOutputStream;
18 import java.io.FileDescriptor;
19 import java.io.FileNotFoundException;
20 import java.io.IOException;
21 import java.io.RandomAccessFile;
22 import java.io.UTFDataFormatException;
23 import java.nio.ByteBuffer;
24 import java.util.Collections;
25 import java.util.Iterator;
26 import java.util.TreeMap;
27 import java.util.Vector;
28 import java.util.concurrent.atomic.AtomicBoolean;
29 import java.util.concurrent.locks.Lock;
31 import java.util.concurrent.locks.ReentrantLock;
32 import java.util.concurrent.locks.ReentrantReadWriteLock.ReadLock;
33 import java.util.concurrent.locks.ReentrantReadWriteLock.WriteLock;
34 import java.util.logging.Level;
35 import java.util.logging.Logger;
41 public class TransactionalFile implements Comparable {
43 private native int nativepread(byte buff[], long offset, int size, FileDescriptor fd);
45 private native int nativepwrite(byte buff[], long offset, int size, FileDescriptor fd);
49 System.load("/home/navid/libkooni.so");
51 public RandomAccessFile file;
53 private int sequenceNum = 0;
54 public static int currenSeqNumforInode = 0;
55 /* public AtomicLong commitedoffset;
56 public AtomicLong commitedfilesize;*/
57 public boolean to_be_created = false;
58 public boolean writemode = false;
59 public boolean appendmode = false;
60 public ReentrantLock offsetlock;
61 private GlobalOffset committedoffset;
62 AtomicBoolean open = new AtomicBoolean(true);
65 private GlobalINodeState inodestate;
68 public TransactionalFile(File f, String mode) {
70 if ((!(f.exists()))) {
78 offsetlock = new ReentrantLock();
79 file = new RandomAccessFile(f, mode);
80 } catch (FileNotFoundException ex) {
82 Logger.getLogger(TransactionalFile.class.getName()).log(Level.SEVERE, null, ex);
86 inode = TransactionalFileWrapperFactory.getINodefromFileName(f.getAbsolutePath());
87 inodestate = TransactionalFileWrapperFactory.createTransactionalFile(inode, f.getAbsolutePath(), mode);
90 sequenceNum = inodestate.seqNum;
93 if (mode.equals("rw")) {
95 } else if (mode.equals("a")) {
99 if (inodestate != null) {
100 synchronized (inodestate) {
101 committedoffset = new GlobalOffset(0);
108 public boolean isOpen(){
112 public TransactionalFile(String filename, String mode) {
115 File f = new File(filename);
117 if ((!(f.exists()))) {
118 to_be_created = true;
125 offsetlock = new ReentrantLock();
126 file = new RandomAccessFile(f, mode);
127 } catch (FileNotFoundException ex) {
129 Logger.getLogger(TransactionalFile.class.getName()).log(Level.SEVERE, null, ex);
133 /* synchronized(this){
136 offsetlock = new ReentrantLock();
137 file = new RandomAccessFile(filename, mode);
139 System.out.println("ll " + file.length());
140 } catch (IOException ex) {
141 Logger.getLogger(TransactionalFile.class.getName()).log(Level.SEVERE, null, ex);
143 } catch (FileNotFoundException ex) {
144 Logger.getLogger(TransactionalFile.class.getName()).log(Level.SEVERE, null, ex);
148 inode = TransactionalFileWrapperFactory.getINodefromFileName(filename);
149 inodestate = TransactionalFileWrapperFactory.createTransactionalFile(inode, filename, mode);
151 sequenceNum = inodestate.seqNum;
154 if (mode.equals("rw")) {
156 } else if (mode.equals("a")) {
160 if (inodestate != null) {
161 synchronized (inodestate) {
162 committedoffset = new GlobalOffset(0);
170 private int invokeNativepread(byte buff[], long offset, int size) {
174 return nativepread(buff, offset, size, file.getFD());
175 } catch (IOException ex) {
177 Logger.getLogger(TransactionalFile.class.getName()).log(Level.SEVERE, null, ex);
183 public int invokeNativepwrite(byte buff[], long offset, int size, RandomAccessFile file) {
185 return nativepwrite(buff, offset, buff.length, file.getFD());
186 } catch (IOException ex) {
188 Logger.getLogger(TransactionalFile.class.getName()).log(Level.SEVERE, null, ex);
194 public int getSequenceNum() {
198 public GlobalOffset getCommitedoffset() {
199 return committedoffset;
205 public GlobalINodeState getInodestate() {
209 public INode getInode() {
213 public void close() throws IOException {
214 ExtendedTransaction me = Wrapper.getTransaction();
216 throw new IOException();
224 if (!(me.getGlobaltoLocalMappings().containsKey(this))) {
228 TransactionLocalFileAttributes tmp = (TransactionLocalFileAttributes) me.getGlobaltoLocalMappings().get(this);
235 public long length() throws IOException{
237 throw new IOException();
238 ExtendedTransaction me = Wrapper.getTransaction();
242 inodestate.commitedfilesize.lengthlock.lock();
243 length = inodestate.commitedfilesize.getLength();
244 inodestate.commitedfilesize.lengthlock.unlock();
249 if (!(me.getGlobaltoLocalMappings().containsKey(this))) {
253 TransactionLocalFileAttributes tmp = (TransactionLocalFileAttributes) me.getGlobaltoLocalMappings().get(this);
257 if (!(this.inodestate.commitedfilesize.getLengthReaders().contains(me))) {
258 this.inodestate.commitedfilesize.getLengthReaders().add(me);
261 tmp.setLocalsize(this.inodestate.commitedfilesize.getLength());
262 tmp.lenght_read = true;
264 this.inodestate.commitedfilesize.lengthlock.unlock();
266 return tmp.getLocalsize();
268 public long getFilePointer() throws IOException {
270 throw new IOException();
271 ExtendedTransaction me = Wrapper.getTransaction();
274 return non_Transactional_getFilePointer();
277 if (!(me.getGlobaltoLocalMappings().containsKey(this))) {
281 TransactionLocalFileAttributes tmp = (TransactionLocalFileAttributes) me.getGlobaltoLocalMappings().get(this);
282 if ((tmp.getOffsetdependency() == OffsetDependency.WRITE_DEPENDENCY_1) || (tmp.getOffsetdependency() == OffsetDependency.NO_ACCESS)) {
283 tmp.setOffsetdependency(OffsetDependency.READ_DEPENDENCY);
288 if (!(this.committedoffset.getOffsetReaders().contains(me))) {
289 this.committedoffset.getOffsetReaders().add(me);
292 tmp.setLocaloffset(tmp.getLocaloffset() + this.committedoffset.getOffsetnumber() - tmp.getCopylocaloffset());
293 target = this.committedoffset.getOffsetnumber() - tmp.getCopylocaloffset();
299 if ((me.getWriteBuffer().get(inode)) != null) {
301 it = ((Vector) (me.getWriteBuffer().get(inode))).iterator();
302 while (it.hasNext()) {
303 WriteOperations wrp = (WriteOperations) it.next();
304 if (wrp.getBelongingto() == tmp && wrp.isUnknownoffset()) {
305 wrp.setUnknownoffset(false);
307 wrp.getRange().setStart(target + wrp.getRange().getStart());
308 wrp.getRange().setEnd(target + wrp.getRange().getEnd());
315 tmp.setUnknown_inital_offset_for_write(false);
316 return tmp.getLocaloffset();
323 public void seek(long offset) throws IOException {
326 throw new IOException();
327 ExtendedTransaction me = Wrapper.getTransaction();
330 non_Transactional_Seek(offset);
334 if (!(me.getGlobaltoLocalMappings().containsKey(this))) {
335 me.addFile(this, offset);
338 TransactionLocalFileAttributes tmp = (TransactionLocalFileAttributes) me.getGlobaltoLocalMappings().get(this);
340 if (tmp.getOffsetdependency() == OffsetDependency.NO_ACCESS) {
341 tmp.setOffsetdependency(OffsetDependency.NO_DEPENDENCY);
342 } else if (tmp.getOffsetdependency() == OffsetDependency.WRITE_DEPENDENCY_1) {
343 tmp.setOffsetdependency(OffsetDependency.WRITE_DEPENDENCY_2);
345 tmp.setUnknown_inital_offset_for_write(false);
346 tmp.setLocaloffset(offset);
351 public int skipBytes(int n) throws IOException {
359 pos = getFilePointer();
362 // if (newpos > len) {
367 /* return the actual number of bytes skipped */
368 return (int) (newpos - pos);
371 public final byte readByte() throws IOException{
372 byte[] data = new byte[1];
374 byte result = (byte)(data[0]);
378 public final boolean readBoolean() throws IOException{
379 byte[] data = new byte[1];
384 //return ((boolean)data[0]);// != 0);
387 public final char readChar() throws IOException{
388 byte[] data = new byte[2];
390 char result = (char)((data[0] << 8) | data[0]);
394 public final short readShort() throws IOException{
395 byte[] data = new byte[2];
397 short result = (short)((data[0] << 8) | data[1]);
398 // System.out.println("res " + result);
402 public final int readUnsignedShort() throws IOException {
403 byte[] data = new byte[2];
405 return (data[0] << 8) + (data[1] << 0);
408 public final String readUTF() throws UTFDataFormatException, IOException{
410 byte[] bytearr = null;
411 char[] chararr = null;
413 utflen = readUnsignedShort();
414 } catch (IOException ex) {
415 Logger.getLogger(TransactionalFile.class.getName()).log(Level.SEVERE, null, ex);
417 bytearr = new byte[utflen];
418 chararr = new char[utflen];
423 int chararr_count = 0;
427 while (count < utflen) {
428 c = (int) bytearr[count] & 0xff;
432 chararr[chararr_count++] = (char) c;
435 while (count < utflen) {
436 c = (int) bytearr[count] & 0xff;
448 chararr[chararr_count++] = (char) c;
452 /* 110x xxxx 10xx xxxx*/
455 throw new UTFDataFormatException(
456 "malformed input: partial character at end");
457 char2 = (int) bytearr[count - 1];
458 if ((char2 & 0xC0) != 0x80)
459 throw new UTFDataFormatException(
460 "malformed input around byte " + count);
461 chararr[chararr_count++] = (char) (((c & 0x1F) << 6) | (char2 & 0x3F));
464 /* 1110 xxxx 10xx xxxx 10xx xxxx */
467 throw new UTFDataFormatException(
468 "malformed input: partial character at end");
469 char2 = (int) bytearr[count - 2];
470 char3 = (int) bytearr[count - 1];
471 if (((char2 & 0xC0) != 0x80)
472 || ((char3 & 0xC0) != 0x80))
473 throw new UTFDataFormatException(
474 "malformed input around byte "
476 chararr[chararr_count++] = (char) (((c & 0x0F) << 12)
477 | ((char2 & 0x3F) << 6) | ((char3 & 0x3F) << 0));
480 /* 10xx xxxx, 1111 xxxx */
481 throw new UTFDataFormatException(
482 "malformed input around byte " + count);
485 // The number of chars produced may be less than utflen
486 return new String(chararr, 0, chararr_count);
490 public final float readFloat() throws IOException{
491 // byte[] data = new byte[4];
492 // int k = read(data);
493 return Float.intBitsToFloat(readInt());
494 // float result = Conversions.bytes2float(data);
495 //int result = (data[0] << 24) | (data[1] << 16) + (data[2] << 8) + (data[3]<<0);
496 // System.out.println("int res " + result);
500 public final double readDouble() throws IOException{
501 return Double.longBitsToDouble(readLong());
505 public final int readInt() throws IOException{
506 byte[] data = new byte[4];
509 int result = Conversions.bytes2int(data);
510 //int result = (data[0] << 24) | (data[1] << 16) + (data[2] << 8) + (data[3]<<0);
511 // System.out.println("int res " + result);
515 public final long readLong() throws IOException{
516 //long result = ((long)(readInt()) << 32) + (readInt() & 0xFFFFFFFFL);
517 byte[] data = new byte[8];
519 //long result = ((long)data[0] << 56) + ((long)data[1] << 48) + ((long)data[2] << 40) + ((long)data[3] << 32) + ((long)data[4] << 24) + ((long)data[5] << 16)+ ((long)data[6] << 8) + data[7];
520 long result = Conversions.bytes2long(data);
521 // System.out.println("long res " + result);
526 public final void writeByte(int b){
528 byte[] result = new byte[1];
531 }catch(IOException ex){
532 Logger.getLogger(TransactionalFile.class.getName()).log(Level.SEVERE, null, ex);
537 public final void writeChar(int value){
539 byte[] result = new byte[2];
540 result[0] = (byte)(value >> 8);
541 result[1] = (byte)(value);
543 }catch(IOException ex){
544 Logger.getLogger(TransactionalFile.class.getName()).log(Level.SEVERE, null, ex);
550 public final void writeShort(int value){
552 byte[] result = new byte[2];
553 result[0] = (byte)(value >> 8);
554 result[1] = (byte)(value);
556 }catch(IOException ex){
557 Logger.getLogger(TransactionalFile.class.getName()).log(Level.SEVERE, null, ex);
562 public final void writeInt(int value){
564 byte[] result = new byte[4];
565 result[0] = (byte) (value >>> 24 & 0xFF);
566 result[1] = (byte) (value >>> 16 & 0xFF);
567 result[2] = (byte) (value >>> 8 & 0xFF);
568 result[3] = (byte) (value);
570 } catch (IOException ex) {
571 Logger.getLogger(TransactionalFile.class.getName()).log(Level.SEVERE, null, ex);
576 public final void writeFloat(Float v){
577 writeInt(Float.floatToIntBits(v));
580 public final void writeLong(long value){
582 byte[] result = new byte[8];
583 result[0] = (byte)(value >>> 56);
584 result[1] = (byte)(value >>> 48);
585 result[2] = (byte)(value >>> 40);
586 result[3] = (byte)(value >>> 32);
587 result[4] = (byte)(value >>> 24);
588 result[5] = (byte)(value >>> 16);
589 result[6] = (byte)(value >>> 8);
590 result[7] = (byte)(value);
592 } catch (IOException ex) {
593 Logger.getLogger(TransactionalFile.class.getName()).log(Level.SEVERE, null, ex);
598 public final void writeDouble(Double v) {
599 writeLong(Double.doubleToLongBits(v));
602 public final void writeBoolean(boolean v){
603 writeByte(v ? 1 : 0);
606 public final void writeChars(String s) throws IOException {
607 int clen = s.length();
609 byte[] b = new byte[blen];
610 char[] c = new char[clen];
611 s.getChars(0, clen, c, 0);
612 for (int i = 0, j = 0; i < clen; i++) {
613 b[j++] = (byte)(c[i] >>> 8);
614 b[j++] = (byte)(c[i] >>> 0);
619 public final int writeUTF(String str) throws UTFDataFormatException{
620 int strlen = str.length();
623 /* use charAt instead of copying String to char array */
624 for (int i = 0; i < strlen; i++) {
626 if ((c >= 0x0001) && (c <= 0x007F)) {
628 } else if (c > 0x07FF) {
636 throw new UTFDataFormatException(
637 "encoded string too long: " + utflen + " bytes");
639 byte[] bytearr = null;
641 bytearr = new byte[utflen + 2];
644 bytearr[count++] = (byte) ((utflen >>> 8) & 0xFF);
645 bytearr[count++] = (byte) ((utflen >>> 0) & 0xFF);
648 for (i = 0; i < strlen; i++) {
650 if (!((c >= 0x0001) && (c <= 0x007F)))
652 bytearr[count++] = (byte) c;
655 for (; i < strlen; i++) {
657 if ((c >= 0x0001) && (c <= 0x007F)) {
658 bytearr[count++] = (byte) c;
660 } else if (c > 0x07FF) {
661 bytearr[count++] = (byte) (0xE0 | ((c >> 12) & 0x0F));
662 bytearr[count++] = (byte) (0x80 | ((c >> 6) & 0x3F));
663 bytearr[count++] = (byte) (0x80 | ((c >> 0) & 0x3F));
665 bytearr[count++] = (byte) (0xC0 | ((c >> 6) & 0x1F));
666 bytearr[count++] = (byte) (0x80 | ((c >> 0) & 0x3F));
671 } catch (IOException ex) {
672 Logger.getLogger(TransactionalFile.class.getName()).log(Level.SEVERE, null, ex);
674 //write(bytearr, 0, utflen + 2);
678 public int read(byte[] b) throws IOException {
681 throw new IOException();
683 ExtendedTransaction me = Wrapper.getTransaction();
686 if (me == null) { // not a transaction, but any I/O operation even though within a non-transaction is considered a single opertion transactiion
687 return non_Transactional_Read(b);
690 if (!(me.getGlobaltoLocalMappings().containsKey(this))) { // if this is the first time the file is accessed by the transcation
695 TransactionLocalFileAttributes tmp = (TransactionLocalFileAttributes) me.getGlobaltoLocalMappings().get(this);
696 tmp.setUnknown_inital_offset_for_write(false);
698 OffsetDependency dep = tmp.getOffsetdependency();
699 if ((dep == OffsetDependency.WRITE_DEPENDENCY_1) ||
700 (dep == OffsetDependency.NO_ACCESS) ||
701 (dep == OffsetDependency.WRITE_DEPENDENCY_2)) {
702 tmp.setOffsetdependency(OffsetDependency.READ_DEPENDENCY);
705 if (dep != OffsetDependency.WRITE_DEPENDENCY_2) {
706 tmp.setLocaloffset(tmp.getLocaloffset() + this.committedoffset.getOffsetnumber() - tmp.getCopylocaloffset());
709 if (!(this.committedoffset.getOffsetReaders().contains(me))) {
710 this.committedoffset.getOffsetReaders().add(me);
717 if (me.getWriteBuffer().get(inode) != null) {
718 makeWritestDependent(me);
720 if ((Boolean) me.merge_for_writes_done.get(inode) == Boolean.FALSE) {
721 mergeWrittenData(me);
724 long loffset = tmp.getLocaloffset();
725 markAccessedBlocks(me, loffset, size, BlockAccessModesEnum.READ);
728 Vector writebuffer = null;
729 if ((me.getWriteBuffer().get(this.inode)) != null) {
730 writebuffer = (Vector) (me.getWriteBuffer().get(this.inode));
733 result = readFromFile(me, b, tmp);
735 //writebuffer = new Vector();
736 //me.getWriteBuffer().put(this.inode, writebuffer);
739 Range readrange = new Range(loffset, loffset + size);
740 Range writerange = null;
741 Range[] intersectedrange = new Range[writebuffer.size()];
742 WriteOperations[] markedwriteop = new WriteOperations[writebuffer.size()];
745 boolean in_local_buffer = false;
748 Iterator it = writebuffer.iterator();
749 while (it.hasNext()) {
751 WriteOperations wrp = (WriteOperations) it.next();
752 writerange = wrp.getRange();
753 if (writerange.includes(readrange)) {
754 markedwriteop[counter] = wrp;
755 in_local_buffer = true;
759 if (writerange.hasIntersection(readrange)) {
760 intersectedrange[counter] = readrange.intersection(writerange);
761 markedwriteop[counter] = wrp;
767 if (in_local_buffer) { // the read one from local buffer
769 result = readFromBuffer(b, tmp, markedwriteop[counter], writerange);
774 if (counter == 0) { // all the read straight from file
776 result = readFromFile(me, b, tmp);
777 } else { // some parts from file others from buffer
779 for (int i = 0; i < counter; i++) {
780 Byte[] data = markedwriteop[i].getData();
781 byte[] copydata = new byte[data.length];
782 for (int j = 0; j < data.length; j++) {
783 copydata[j] = data[j].byteValue();
785 System.arraycopy(copydata, (int) (intersectedrange[i].getStart() - markedwriteop[i].getRange().getStart()), b, (int) (intersectedrange[i].getStart() - readrange.getStart()), (int) (Math.min(intersectedrange[i].getEnd(), readrange.getEnd()) - intersectedrange[i].getStart()));
786 result += Math.min(intersectedrange[i].getEnd(), readrange.getEnd()) - intersectedrange[i].getStart();
789 Range[] non_intersected_ranges = readrange.minus(intersectedrange, counter);
790 Vector occupiedblocks = new Vector();
791 for (int i = 0; i < non_intersected_ranges.length; i++) {
792 int st = FileBlockManager.getCurrentFragmentIndexofTheFile(non_intersected_ranges[i].getStart());
793 int en = FileBlockManager.getCurrentFragmentIndexofTheFile(non_intersected_ranges[i].getEnd());
794 for (int j = st; j <= en; j++) {
795 if (!(occupiedblocks.contains(Integer.valueOf(j)))) {
796 occupiedblocks.add(Integer.valueOf(j));
803 me.getHeldoffsetlocks().add(offsetlock);
804 BlockDataStructure block;
806 for (k = 0; k < occupiedblocks.size() && me.getStatus() == Status.ACTIVE; k++) { // locking the block locks
807 block = this.inodestate.getBlockDataStructure((Integer) (occupiedblocks.get(k)));//(BlockDataStructure) tmp.adapter.lockmap.get(Integer.valueOf(k)));
809 block.getLock().readLock().lock();
810 if (!(block.getReaders().contains(me))) {
811 block.getReaders().add(me);
815 if (k<occupiedblocks.size()){
816 for (int i = 0; i <k; i++) {
817 block = this.inodestate.getBlockDataStructure((Integer) (occupiedblocks.get(k)));
818 me.getHeldblocklocks().add(block.getLock().readLock());
820 throw new AbortedException();
824 for (int i = 0; i < non_intersected_ranges.length; i++) {
826 int sizetoread = (int) (non_intersected_ranges[i].getEnd() - non_intersected_ranges[i].getStart());
827 byte[] tmpdt = new byte[(int) (non_intersected_ranges[i].getEnd() - non_intersected_ranges[i].getStart())];
828 int tmpsize = invokeNativepread(tmpdt, non_intersected_ranges[i].getStart(), sizetoread);
829 System.arraycopy(tmpdt, 0, b, (int) (non_intersected_ranges[i].getStart() - readrange.getStart()), sizetoread);
830 //file.seek(non_intersected_ranges[i].getStart());
831 //int tmpsize = file.read(b, (int) (non_intersected_ranges[i].getStart() - readrange.getStart()), (int) (non_intersected_ranges[i].getEnd() - non_intersected_ranges[i].getStart()));
836 if (me.getStatus() == Status.ABORTED) {
837 for (k = 0; k < occupiedblocks.size(); k++) {
838 block = this.inodestate.getBlockDataStructure((Integer) (occupiedblocks.get(k)));
839 me.getHeldblocklocks().add(block.getLock().readLock());
841 throw new AbortedException();
843 for (k = 0; k < occupiedblocks.size(); k++) {
844 block = this.inodestate.getBlockDataStructure((Integer) (occupiedblocks.get(k)));
845 block.getLock().readLock().unlock();
847 // offsetlock.unlock();
848 tmp.setLocaloffset(tmp.getLocaloffset() + result);
856 public void write(byte[] data) throws IOException {
858 throw new IOException();
860 throw new IOException();
864 ExtendedTransaction me = Wrapper.getTransaction();
865 int size = data.length;
868 if (me == null) // not a transaction
871 non_Transactional_Write(data);
875 if (!(me.getGlobaltoLocalMappings().containsKey(this))) {
879 // if (me.getGlobaltoLocalMappings().containsKey(this)) //
883 Byte[] by = new Byte[size];
884 for (int i = 0; i < size; i++) {
885 by[i] = Byte.valueOf(data[i]);
887 TransactionLocalFileAttributes tmp = ((TransactionLocalFileAttributes) (me.getGlobaltoLocalMappings().get(this)));
890 if (((Vector) (me.getWriteBuffer().get(this.inode))) != null) {
891 dummy = new Vector((Vector) (me.getWriteBuffer().get(this.inode)));
893 dummy = new Vector();
895 dummy.add(new WriteOperations(by, new Range(tmp.getLocaloffset(), tmp.getLocaloffset() + by.length), tmp.isUnknown_inital_offset_for_write(), this, tmp));
896 me.getWriteBuffer().put(this.inode, dummy);
898 long loffset = tmp.getLocaloffset();
901 tmp.setLocaloffset(tmp.getLocaloffset() + by.length);
903 if (tmp.getLocaloffset() > tmp.getLocalsize())
904 tmp.setLocalsize(tmp.getLocaloffset());
906 me.merge_for_writes_done.put(inode, Boolean.FALSE);
908 if (!(tmp.isUnknown_inital_offset_for_write())) {
909 markAccessedBlocks(me, loffset, size, BlockAccessModesEnum.WRITE);
912 if (tmp.getOffsetdependency() == OffsetDependency.NO_ACCESS) {
913 tmp.offsetdependency = OffsetDependency.WRITE_DEPENDENCY_1;
917 private void markAccessedBlocks(ExtendedTransaction me, long loffset, int size, BlockAccessModesEnum mode) {
922 if (me.getAccessedBlocks().get(this.getInode()) != null) {
923 map = (TreeMap) me.getAccessedBlocks().get(this.getInode());
926 me.getAccessedBlocks().put(this.inode, map);
928 int startblock = (int) ((loffset / Defaults.FILEFRAGMENTSIZE));//FileBlockManager.getCurrentFragmentIndexofTheFile(loffset);
929 int targetblock = (int) (((size + loffset) / Defaults.FILEFRAGMENTSIZE));//FileBlockManager.getTargetFragmentIndexofTheFile(loffset, size);
930 for (int i = startblock; i <= targetblock; i++) {
931 if (map.get(Integer.valueOf(i)) == null) {
932 map.put(Integer.valueOf(i), mode);
933 } else if (map.get(Integer.valueOf(i)) != mode) {
934 map.put(Integer.valueOf(i), BlockAccessModesEnum.READ_WRITE);
939 private int readFromFile(ExtendedTransaction me, byte[] readdata, TransactionLocalFileAttributes tmp) {
940 //Inline these method calls for performance...
941 //int st = FileBlockManager.getCurrentFragmentIndexofTheFile(tmp.getLocaloffset());//(int) ((tmp.getLocaloffset() / Defaults.FILEFRAGMENTSIZE));//
942 //int end = FileBlockManager.getTargetFragmentIndexofTheFile(tmp.getLocaloffset(), readdata.length);//(int) (((tmp.getLocaloffset() + readdata.length) / Defaults.FILEFRAGMENTSIZE));
943 int st = (int) ((tmp.getLocaloffset() / Defaults.FILEFRAGMENTSIZE));
944 int end =(int) (((tmp.getLocaloffset() + readdata.length) / Defaults.FILEFRAGMENTSIZE));
946 BlockDataStructure block = null;
948 Lock[] locks = new Lock[end -st +1];
953 for (k = st; k <= end /*&& me.getStatus() == Status.ACTIVE*/; k++) {
954 block = this.inodestate.getBlockDataStructure(Integer.valueOf(k));
955 block.getLock().readLock().lock();
957 // locks[k-st] = block.getLock().readLock();
958 if (!(block.getReaders().contains(me))) {
959 block.getReaders().add(me);
963 //Optimization here...not actually needed...may be worth checking
964 //whether this improves performance
966 //We aborted here if k is less than or equal to end
967 me.blockcount = k - st;
968 for (int i = st; i < k; i++) {
969 // block = this.inodestate.getBlockDataStructure(Integer.valueOf(i));
970 me.getHeldblocklocks().add(block.getLock().readLock());
971 //me.toholdblocklocks[i-st] = this.inodestate.getBlockDataStructure(Integer.valueOf(i)).getLock().readLock();
972 // me.getHeldblocklocks().add(locks[i-st]);
974 throw new AbortedException();
979 size = invokeNativepread(readdata, tmp.getLocaloffset(), readdata.length);
980 tmp.setLocaloffset(tmp.getLocaloffset() + size);
987 //Needed to make sure that transaction only sees consistent data
988 if (me.getStatus() == Status.ABORTED) {
989 me.blockcount = end - st + 1;
990 for (int i = st; i <= end; i++) {
991 block = this.inodestate.getBlockDataStructure(Integer.valueOf(i));
992 // me.toholdblocklocks[i-st] = this.inodestate.getBlockDataStructure(Integer.valueOf(i)).getLock().readLock();
993 me.getHeldblocklocks().add(block.getLock().readLock());
994 // me.getHeldblocklocks().add(locks[i-st]);
996 throw new AbortedException();
1000 for (k = st; k <= end; k++) {
1001 block = this.inodestate.getBlockDataStructure(Integer.valueOf(k));
1002 block.getLock().readLock().unlock();
1003 //locks[k-st].unlock();
1008 private int readFromBuffer(byte[] readdata, TransactionLocalFileAttributes tmp, WriteOperations wrp, Range writerange) {
1009 long loffset = tmp.getLocaloffset();
1011 Byte[] data = (Byte[]) wrp.getData();
1012 byte[] copydata = new byte[data.length];
1014 for (int i = 0; i < data.length; i++) {
1015 copydata[i] = data[i].byteValue();
1017 System.arraycopy(copydata, (int) (loffset - writerange.getStart()), readdata, 0, readdata.length);
1018 tmp.setLocaloffset(tmp.getLocaloffset() + readdata.length);
1019 return readdata.length;
1023 public void simpleWritetoBuffer(Byte[] data, Range newwriterange, TreeMap tm) {
1024 tm.put(newwriterange, data);
1027 public void unlockLocks(Vector heldlocks) {
1028 for (int i = 0; i < heldlocks.size(); i++) {
1029 ((Lock) heldlocks.get(i)).unlock();
1033 public void setInode(INode inode) {
1037 public void lockOffset(ExtendedTransaction me) {
1038 boolean locked = false;
1039 if (me.getStatus() == Status.ACTIVE) { //locking the offset
1044 if (me.getStatus() != Status.ACTIVE) {
1046 me.getHeldoffsetlocks().add(offsetlock);
1048 throw new AbortedException();
1053 public void lockLength(ExtendedTransaction me) {
1054 boolean locked = false;
1055 if (me.getStatus() == Status.ACTIVE) { //locking the offset
1057 this.inodestate.commitedfilesize.lengthlock.lock();
1061 if (me.getStatus() != Status.ACTIVE) {
1063 me.getHeldlengthlocks().add(this.inodestate.commitedfilesize.lengthlock);
1065 throw new AbortedException();
1070 public void mergeWrittenData(ExtendedTransaction me/*TreeMap target, byte[] data, Range to_be_merged_data_range*/) {
1072 boolean flag = false;
1073 Vector vec = (Vector) me.getWriteBuffer().get(this.inode);
1074 Range intersectedrange = new Range(0, 0);
1075 Iterator it1 = vec.iterator();
1076 WriteOperations wrp;
1077 WriteOperations wrp2;
1078 Vector toberemoved = new Vector();
1079 while (it1.hasNext()) {
1080 wrp = (WriteOperations) (it1.next());
1082 if (toberemoved.contains(wrp)) {
1086 Iterator it2 = vec.listIterator();
1087 while (it2.hasNext()) {
1089 wrp2 = (WriteOperations) (it2.next());
1091 if ((wrp2 == wrp) || toberemoved.contains(wrp2)) {
1095 if (wrp.getRange().hasIntersection(wrp2.getRange())) {
1097 intersectedrange = wrp2.getRange().intersection(wrp.getRange());
1098 toberemoved.add(wrp2);
1102 long startprefix = 0;
1104 long startsuffix = 0;
1107 int intermediatesize = 0;
1108 Byte[] prefixdata = null;
1109 Byte[] suffixdata = null;
1110 boolean prefix = false;
1111 boolean suffix = false;
1115 if (wrp.getRange().getStart() < wrp2.getRange().getStart()) {
1116 prefixdata = new Byte[(int) (wrp2.getRange().getStart() - wrp.getRange().getStart())];
1117 prefixdata = (Byte[]) (wrp.getData());
1118 startprefix = wrp.getRange().getStart();
1119 prefixsize = (int) (intersectedrange.getStart() - startprefix);
1120 intermediatesize = (int) (intersectedrange.getEnd() - intersectedrange.getStart());
1122 } else if (wrp2.getRange().getStart() <= wrp.getRange().getStart()) {
1123 prefixdata = new Byte[(int) (wrp.getRange().getStart() - wrp2.getRange().getStart())];
1124 prefixdata = (Byte[]) (wrp2.getData());
1125 startprefix = wrp2.getRange().getStart();
1126 prefixsize = (int) (intersectedrange.getStart() - startprefix);
1127 intermediatesize = (int) (intersectedrange.getEnd() - intersectedrange.getStart());
1131 if (wrp2.getRange().getEnd() >= wrp.getRange().getEnd()) {
1133 suffixdata = new Byte[(int) (wrp2.getRange().getEnd() - intersectedrange.getEnd())];
1134 suffixdata = (Byte[]) (wrp2.getData());
1135 startsuffix = intersectedrange.getEnd() - wrp2.getRange().getStart();
1136 suffixsize = (int) (wrp2.getRange().getEnd() - intersectedrange.getEnd());
1138 endsuffix = wrp2.getRange().getEnd();
1139 } else if (wrp.getRange().getEnd() > wrp2.getRange().getEnd()) {
1140 suffixdata = new Byte[(int) (wrp.getRange().getEnd() - intersectedrange.getEnd())];
1141 suffixdata = (Byte[]) (wrp.getData());
1142 startsuffix = intersectedrange.getEnd() - wrp.getRange().getStart();
1143 suffixsize = (int) (wrp.getRange().getEnd() - intersectedrange.getEnd());
1144 endsuffix = wrp.getRange().getEnd();
1149 Byte[] data_to_insert;
1151 if ((prefix) && (suffix)) {
1152 data_to_insert = new Byte[(int) (endsuffix - startprefix)];
1153 System.arraycopy(prefixdata, 0, data_to_insert, 0, prefixsize);
1154 System.arraycopy(wrp2.getData(), (int) (intersectedrange.getStart() - wrp2.getRange().getStart()), data_to_insert, prefixsize, intermediatesize);
1155 System.arraycopy(suffixdata, (int) startsuffix, data_to_insert, (prefixsize + intermediatesize), suffixsize);
1156 wrp.setData(data_to_insert);
1157 wrp.setRange(new Range(startprefix, endsuffix));
1163 Iterator it = toberemoved.iterator();
1164 while (it.hasNext()) {
1165 vec.remove(it.next());
1167 toberemoved.clear();
1168 Collections.sort(vec);
1169 me.merge_for_writes_done.put(inode, Boolean.TRUE);
1173 public void non_Transactional_Write(byte[] data) {
1175 Vector heldlocks = new Vector();
1177 int startblock = FileBlockManager.getCurrentFragmentIndexofTheFile(committedoffset.getOffsetnumber());
1178 int targetblock = FileBlockManager.getTargetFragmentIndexofTheFile(committedoffset.getOffsetnumber(), data.length);
1181 WriteLock[] blocksar;
1182 blocksar = new WriteLock[targetblock-startblock+1];
1183 for (int i = startblock; i <= targetblock; i++) {
1184 BlockDataStructure block = this.inodestate.getBlockDataStructure(i);
1185 block.getLock().writeLock().lock();
1186 blocksar[i-startblock] = block.getLock().writeLock();
1187 //heldlocks.add(block.getLock().writeLock());
1191 ExtendedTransaction.invokeNativepwrite(data, committedoffset.getOffsetnumber(), data.length, file);
1192 //file.seek(committedoffset.getOffsetnumber());
1194 committedoffset.setOffsetnumber(committedoffset.getOffsetnumber() + data.length);
1197 // unlockLocks(heldlocks);
1198 for (int i = startblock; i <= targetblock; i++) {
1199 blocksar[i-startblock].unlock();
1201 offsetlock.unlock();
1205 public int non_Transactional_Read(byte[] b) {
1213 startblock = FileBlockManager.getCurrentFragmentIndexofTheFile(committedoffset.getOffsetnumber());
1214 targetblock = FileBlockManager.getTargetFragmentIndexofTheFile(committedoffset.getOffsetnumber(), size);
1216 ReadLock[] blocksar;
1217 blocksar = new ReadLock[targetblock-startblock+1];
1219 for (int i = startblock; i <= targetblock; i++) {
1220 BlockDataStructure block = this.inodestate.getBlockDataStructure(i);
1221 block.getLock().readLock().lock();
1222 blocksar[i-startblock] = block.getLock().readLock();
1225 size = invokeNativepread(b, committedoffset.getOffsetnumber(), b.length);
1226 committedoffset.setOffsetnumber(committedoffset.getOffsetnumber() + size);
1227 if (!(committedoffset.getOffsetReaders().isEmpty())) {
1228 Iterator it2 = committedoffset.getOffsetReaders().iterator(); // for visible readers strategy
1230 while (it2.hasNext()) {
1231 ExtendedTransaction tr = (ExtendedTransaction) it2.next();
1234 committedoffset.getOffsetReaders().clear();
1237 for (int i = startblock; i <= targetblock; i++) {
1238 blocksar[i-startblock].unlock();
1241 //unlockLocks(heldlocks);
1242 offsetlock.unlock();
1250 public void non_Transactional_Seek(long offset) {
1252 committedoffset.setOffsetnumber(offset);
1253 offsetlock.unlock();
1256 public long non_Transactional_getFilePointer() {
1260 offset = committedoffset.getOffsetnumber();
1261 offsetlock.unlock();
1266 public int compareTo(Object arg0) {
1267 TransactionalFile tf = (TransactionalFile) arg0;
1268 if (this.inode.getNumber() < tf.inode.getNumber()) {
1270 } else if (this.inode.getNumber() > tf.inode.getNumber()) {
1273 if (this.sequenceNum < tf.sequenceNum) {
1281 public void makeWritestDependent(ExtendedTransaction me) {// make the writes absolute and dependent on ofset value
1286 it = ((Vector) (me.getWriteBuffer().get(inode))).iterator();
1287 while (it.hasNext()) {
1289 WriteOperations wrp = (WriteOperations) it.next();
1290 if (wrp.isUnknownoffset()) {
1291 wrp.setUnknownoffset(false);
1292 wrp.getOwnertransactionalFile().lockOffset(me);
1294 wrp.getRange().setStart(wrp.getOwnertransactionalFile().committedoffset.getOffsetnumber() - wrp.getBelongingto().getCopylocaloffset() + wrp.getRange().getStart());
1295 wrp.getRange().setEnd(wrp.getOwnertransactionalFile().committedoffset.getOffsetnumber() - wrp.getBelongingto().getCopylocaloffset() + wrp.getRange().getEnd());
1296 if ((wrp.getBelongingto().getOffsetdependency() == OffsetDependency.WRITE_DEPENDENCY_1) ||
1297 (wrp.getBelongingto().offsetdependency == OffsetDependency.NO_ACCESS) ||
1298 (wrp.getBelongingto().getOffsetdependency() == OffsetDependency.WRITE_DEPENDENCY_2)) {
1299 wrp.getBelongingto().setOffsetdependency(OffsetDependency.READ_DEPENDENCY);
1300 wrp.getBelongingto().setUnknown_inital_offset_for_write(false);
1301 if (!(wrp.getOwnertransactionalFile().committedoffset.getOffsetReaders().contains(me))) {
1302 wrp.getOwnertransactionalFile().committedoffset.getOffsetReaders().add(me);
1304 wrp.getBelongingto().setLocaloffset(wrp.getBelongingto().getLocaloffset() + wrp.getOwnertransactionalFile().committedoffset.getOffsetnumber() - wrp.getBelongingto().getCopylocaloffset());
1306 wrp.getOwnertransactionalFile().offsetlock.unlock();
1307 markAccessedBlocks(me, (int) wrp.getRange().getStart(), (int) (wrp.getRange().getEnd() - wrp.getRange().getStart()), BlockAccessModesEnum.WRITE);
1315 // for block versioning mechanism
1316 /*if (!(validateBlocksVersions(startblock, targetblock))) { ////check to see if version are still valid
1318 throw new AbortedException();
1322 int expvalue = ((Integer) tmp.getBlockversions().get(Integer.valueOf(k))).intValue();
1323 while (me.getStatus() == Status.ACTIVE) {
1324 BlockDataStructure block = ((BlockDataStructure) tmp.adapter.lockmap.get(Integer.valueOf(k)));
1325 if (block.getLock().tryLock()) {
1326 heldlocks.add(block.getLock());
1327 if (!(block.getVersion().get() == expvalue)) { // for block versioning mechanism
1335 me.getContentionManager().resolveConflict(me, block.getOwner());
1338 if (me.getStatus() == Status.ABORTED) {
1339 unlockLocks(heldlocks);
1340 offsetlock.unlock();
1341 throw new AbortedException();
1345 /* public boolean validateBlocksVersions(int startblock, int targetblock) { // For Block Versioning Mechanism
1346 boolean valid = true;
1347 ExtendedTransaction me = ExtendedTransaction.getTransaction();
1348 TransactionLocalFileAttributes tmp = ((TransactionLocalFileAttributes) (me.getFilesAccesses().get(this.getInode())));
1349 for (int i = startblock; i <= targetblock; i++) {
1350 int expvalue = ((Integer) tmp.getBlockversions().get(Integer.valueOf(i))).intValue();
1351 BlockDataStructure block = ((BlockDataStructure) tmp.adapter.lockmap.get(Integer.valueOf(i)));
1352 if (expvalue != block.getVersion().get()) {