*** empty log message ***
[IRC.git] / Robust / Transactions / TransactionalIO / src / TransactionalIO / core / TransactionalFile.java
1 /*
2  * To change this template, choose Tools | Templates
3  * and open the template in the editor.
4  */
5 package TransactionalIO.core;
6
7
8
9 import TransactionalIO.Utilities.Range;
10 import TransactionalIO.exceptions.AbortedException;
11 import TransactionalIO.exceptions.PanicException;
12 import TransactionalIO.benchmarks.benchmark;
13 import TransactionalIO.core.ExtendedTransaction.Status;
14 import TransactionalIO.interfaces.BlockAccessModesEnum;
15 import TransactionalIO.interfaces.OffsetDependency;
16 import java.io.File;
17 import java.io.FileDescriptor;
18 import java.io.FileNotFoundException;
19 import java.io.IOException;
20 import java.io.RandomAccessFile;
21 import java.nio.ByteBuffer;
22 import java.util.Collections;
23 import java.util.Iterator;
24 import java.util.SortedSet;
25 import java.util.TreeMap;
26 import java.util.TreeSet;
27 import java.util.Vector;
28 import java.util.concurrent.locks.Lock;
29 import java.util.concurrent.locks.ReentrantLock;
30 import java.util.logging.Level;
31 import java.util.logging.Logger;
32 import sun.misc.ConditionLock;
33
34 /**
35  *
36  * @author navid
37  */
38
39
40 public class TransactionalFile implements Comparable{
41
42     private native int nativepwrite(byte buff[], long offset, int size, FileDescriptor fd);
43     private native int nativepread(byte buff[], long offset, int size, FileDescriptor fd);
44     
45     {
46         
47         System.load("/home/navid/libkooni.so");
48     }
49     
50     
51     public RandomAccessFile file;
52     private INode inode;
53     private int sequenceNum = 0;
54     public static int currenSeqNumforInode = 0;
55  
56     public boolean to_be_created = false;
57     public boolean writemode = false;
58     public boolean appendmode = false;
59     public ReentrantLock offsetlock;
60     private GlobalOffset committedoffset;
61     private GlobalINodeState inodestate ;
62     
63     
64     public TransactionalFile(String filename, String mode) {
65         
66        
67         File f = new File(filename);
68   
69         if ((!(f.exists()))) {
70             to_be_created = true;
71             file = null;
72
73         } else {
74
75             try {
76
77                 offsetlock = new ReentrantLock();
78                 file = new RandomAccessFile(f, mode);
79             } catch (FileNotFoundException ex) {
80  
81                 Logger.getLogger(TransactionalFile.class.getName()).log(Level.SEVERE, null, ex);
82             }
83       
84         }
85         inode = TransactionalFileWrapperFactory.getINodefromFileName(filename);
86         inodestate = TransactionalFileWrapperFactory.createTransactionalFile(inode, filename, mode);
87         
88         
89         sequenceNum = inodestate.seqNum;
90         inodestate.seqNum++;
91
92         if (mode.equals("rw")) {
93             writemode = true;
94         } else if (mode.equals("a")) {
95             appendmode = true;
96         }
97
98         if (inodestate != null) {
99             synchronized (inodestate) {
100                 try {
101                     if (!appendmode) {
102                         committedoffset = new GlobalOffset(0);
103                     } else {
104                         committedoffset = new GlobalOffset(file.length());
105                     }
106
107                 } catch (IOException ex) {
108                     Logger.getLogger(TransactionalFile.class.getName()).log(Level.SEVERE, null, ex);
109                 }
110             }
111         }
112         
113                 
114     }
115
116     private int invokeNativepread(byte buff[], long offset, int size) {
117         try {
118             return nativepread(buff, offset, size, file.getFD());
119         } catch (IOException ex) {
120             
121             Logger.getLogger(TransactionalFile.class.getName()).log(Level.SEVERE, null, ex);
122             return -1;
123         }
124         
125     }
126     
127     public int invokeNativepwrite(byte buff[], long offset, int size, RandomAccessFile file) {
128         try {
129             return nativepwrite(buff, offset, buff.length, file.getFD());
130         } catch (IOException ex) {
131             
132             Logger.getLogger(TransactionalFile.class.getName()).log(Level.SEVERE, null, ex);
133             return -1;
134         }
135         
136     }
137     
138     
139
140     
141     public int getSequenceNum() {
142         return sequenceNum;
143     }
144
145     
146     public GlobalOffset getCommitedoffset() {
147         return committedoffset;
148     }
149
150     public GlobalINodeState getInodestate() {
151         return inodestate;
152     }
153
154
155     public INode getInode() {
156         return inode;
157     }
158   
159     
160     public void close() {
161         try {
162             file.close();
163         } catch (IOException ex) {
164             Logger.getLogger(TransactionalFile.class.getName()).log(Level.SEVERE, null, ex);
165         }
166     }
167
168     public long getFilePointer(){ 
169         
170         ExtendedTransaction me = Wrapper.getTransaction();
171         TransactionLocalFileAttributes tmp = null;
172         
173         if (me == null) {
174             return non_Transactional_getFilePointer();
175         }
176         
177         if (!(me.getGlobaltoLocalMappings().containsKey(this))){
178                me.addFile(this, 0);
179         }
180         
181         tmp = (TransactionLocalFileAttributes) me.getGlobaltoLocalMappings().get(this);
182         if ((tmp.getOffsetdependency() == OffsetDependency.WRITE_DEPENDENCY_1) || (tmp.getOffsetdependency() == OffsetDependency.NO_ACCESS)){   
183              tmp.setOffsetdependency(OffsetDependency.READ_DEPENDENCY);
184
185              long target;
186              
187              lockOffset(me);
188                     if (!(this.committedoffset.getOffsetReaders().contains(me))){
189                         this.committedoffset.getOffsetReaders().add(me);
190                     }
191                     tmp.setLocaloffset(tmp.getLocaloffset() + this.committedoffset.getOffsetnumber() - tmp.getCopylocaloffset());
192                     target = this.committedoffset.getOffsetnumber() - tmp.getCopylocaloffset();
193              offsetlock.unlock();         
194              
195              
196              Iterator it;
197
198              if ((me.getWriteBuffer().get(inode)) != null)
199              {   
200                 it = ((Vector) (me.getWriteBuffer().get(inode))).iterator();
201                 while (it.hasNext()){
202                     WriteOperations wrp = (WriteOperations) it.next();
203                     if (wrp.getTFA() == tmp && wrp.isUnknownoffset())
204                         wrp.setUnknownoffset(false);
205                         wrp.getRange().setStart(target + wrp.getRange().getStart());
206                         wrp.getRange().setEnd(target + wrp.getRange().getEnd());
207                 }   
208              }             
209         }
210         
211        
212         tmp.setUnknown_inital_offset_for_write(false);
213         return tmp.getLocaloffset();
214     }
215     
216     public void seek(long offset) {
217
218         if (appendmode) {
219             throw new PanicException("Cannot seek into a file opened in append mode");
220         }
221         ExtendedTransaction me = Wrapper.getTransaction();
222         
223         if (me == null) {
224             non_Transactional_Seek(offset);
225             return;
226         }
227         
228         else {
229            TransactionLocalFileAttributes tmp = null;
230             if (!(me.getGlobaltoLocalMappings().containsKey(this))){
231                 me.addFile(this, offset);
232             }
233             tmp = (TransactionLocalFileAttributes) me.getGlobaltoLocalMappings().get(this);
234             
235             if (tmp.getOffsetdependency() == OffsetDependency.NO_ACCESS)
236                 tmp.setOffsetdependency(OffsetDependency.NO_DEPENDENCY);
237             
238             else if (tmp.getOffsetdependency() == OffsetDependency.WRITE_DEPENDENCY_1)
239                 tmp.setOffsetdependency(OffsetDependency.WRITE_DEPENDENCY_2);
240             
241             tmp.setUnknown_inital_offset_for_write(false);
242             tmp.setLocaloffset(offset);
243           
244         }
245     }
246
247     public int read(byte[] b) {
248        
249         ExtendedTransaction me = Wrapper.getTransaction();
250         int size = b.length;
251         int result = 0;
252         
253         if (me == null) {  // not a transaction, but any I/O operation even though within a non-transaction is considered a single opertion transactiion 
254             return non_Transactional_Read(b);
255         }
256    
257   
258         if (me.getGlobaltoLocalMappings().containsKey(this)){
259     
260             TransactionLocalFileAttributes tmp = (TransactionLocalFileAttributes) me.getGlobaltoLocalMappings().get(this);
261             tmp.setUnknown_inital_offset_for_write(false);
262             
263             //make this transaction read dependent on this descriptor if it is not so already
264             if ((tmp.getOffsetdependency() == OffsetDependency.WRITE_DEPENDENCY_1) || (tmp.offsetdependency == OffsetDependency.NO_ACCESS) || (tmp.getOffsetdependency() == OffsetDependency.WRITE_DEPENDENCY_2)){
265                 
266                lockOffset(me);
267                     makeDependentonOffet(me, tmp);
268                offsetlock.unlock();
269             }
270
271             // make all write operations by any transaction to this offset absolute and those transaction read 
272             //dependent on the offset
273             Iterator it;
274             if (me.getWriteBuffer().get(inode) != null)
275             {
276                 it = ((Vector) (me.getWriteBuffer().get(inode))).iterator();
277                 while (it.hasNext()){
278                  
279                       WriteOperations wrp = (WriteOperations) it.next();
280                       if (wrp.isUnknownoffset()){
281                         wrp.setUnknownoffset(false);
282                         
283                         wrp.getOwnerTF().lockOffset(me);
284                             makeWriteAbsolute(me, wrp);
285                         wrp.getOwnerTF().offsetlock.unlock();     
286                         
287                         markAccessedBlocks(me, (int)wrp.getRange().getStart(), (int)(wrp.getRange().getEnd() - wrp.getRange().getStart()), BlockAccessModesEnum.WRITE);
288
289                       }
290                 }
291             }
292             
293         /*    if (!(me.isWritesmerged())){
294                 mergeWrittenData();
295             }*/
296
297             
298             // merge the write by this transation to this descriptor before start reading from it 
299             if ((Boolean)me.merge_for_writes_done.get(inode) == Boolean.FALSE){
300                  mergeWrittenData(me);
301             }
302                
303             
304             
305             // find the intersections of the data o be read with the
306             // transactions local buffer if any at all
307             long loffset = tmp.getLocaloffset();
308             markAccessedBlocks(me, loffset, size, BlockAccessModesEnum.READ);
309    
310             Vector writebuffer;
311             if ((me.getWriteBuffer().get(this.inode)) != null)
312                 writebuffer = (Vector) (me.getWriteBuffer().get(this.inode));
313             else {
314                 writebuffer = new Vector();
315                 me.getWriteBuffer().put(this.inode, writebuffer);
316             }
317             Range readrange = new Range(loffset, loffset + size);
318             Range writerange = null;
319             Range[] intersectedrange = new Range[writebuffer.size()];
320             WriteOperations[] markedwriteop = new WriteOperations[writebuffer.size()];
321             
322             int number_of_intersections = 0;
323             boolean data_in_local_buffer = false;
324             
325                     
326             it = writebuffer.iterator();
327             while (it.hasNext()) {
328                 
329                 WriteOperations wrp = (WriteOperations) it.next();
330                 writerange = wrp.getRange();
331                 if (writerange.includes(readrange)) {
332                     markedwriteop[number_of_intersections] = wrp;
333                     data_in_local_buffer = true;
334                     break;
335                 }
336
337                 if (writerange.hasIntersection(readrange)) {
338                     intersectedrange[number_of_intersections] = readrange.intersection(writerange);
339                     markedwriteop[number_of_intersections] = wrp;
340                    
341                     number_of_intersections++;
342                 }
343             }
344
345
346         
347             if (data_in_local_buffer) {
348                 // the to be read offset is written previously by the transaction itself
349                 // so the read is done from localbuffer
350                 result = readFromBuffer(b, tmp, markedwriteop[number_of_intersections],writerange);    
351                 return result;
352             }
353             
354             else{
355                 
356                 if (number_of_intersections == 0) {
357                     // the whole range to be read should be donefrom the file itself, 
358                     result = readFromFile(me, b, tmp);
359                 }
360                 
361                 
362                 else {
363                       //some of the parts to read are in local buffer some should be done
364                      //from the file 
365                     for (int i = 0; i < number_of_intersections; i++) {
366
367                         
368                         Byte[] data = markedwriteop[i].getData();
369                         byte[] copydata = new byte[data.length];
370
371                         for (int j = 0; j < data.length; j++) {
372                             copydata[j] = data[j].byteValue();
373                         }
374                         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()));
375                         result += Math.min(intersectedrange[i].getEnd(), readrange.getEnd()) - intersectedrange[i].getStart();
376                     }
377
378                     Range[] non_intersected_ranges = readrange.minus(intersectedrange, number_of_intersections);
379                     Vector occupiedblocks = new Vector();
380                     for (int i = 0; i < non_intersected_ranges.length; i++) {
381                         int st = FileBlockManager.getCurrentFragmentIndexofTheFile(non_intersected_ranges[i].getStart());
382                         int en = FileBlockManager.getCurrentFragmentIndexofTheFile(non_intersected_ranges[i].getEnd());
383                         for (int j = st; j <= en; j++) {
384                             if (!(occupiedblocks.contains(Integer.valueOf(j)))) {
385                                 occupiedblocks.add(Integer.valueOf(j));
386                             }
387                         }
388                     }
389
390
391                 
392                     lockOffset(me);
393                     me.getHeldoffsetlocks().add(offsetlock);
394                     
395                     
396                     for (int k = 0; k < occupiedblocks.size(); k++) {   // locking the block locks
397
398                         while (me.getStatus() == Status.ACTIVE) {
399                           
400                             BlockDataStructure block = this.inodestate.getBlockDataStructure((Integer)(occupiedblocks.get(k)));//(BlockDataStructure) tmp.adapter.lockmap.get(Integer.valueOf(k)));
401                             block.getLock().readLock().lock();
402                                     if (!(block.getReaders().contains(me))){
403                                         block.getReaders().add(me);
404                                      }
405                                      me.getHeldblocklocks().add(block.getLock().readLock());
406                                     break;
407                         }
408                        if (me.getStatus() == Status.ABORTED) {
409                             throw new AbortedException();
410                         }
411                     }
412
413
414
415                     for (int i = 0; i < non_intersected_ranges.length; i++) {
416                         try {
417                             //invokeNativepread(b, non_intersected_ranges[i].getStart(), size);
418                             file.seek(non_intersected_ranges[i].getStart());
419                             int tmpsize = file.read(b, (int) (non_intersected_ranges[i].getStart() - readrange.getStart()), (int) (non_intersected_ranges[i].getEnd() - non_intersected_ranges[i].getStart()));
420                             result += tmpsize;
421                         } catch (IOException ex) {
422
423                             Logger.getLogger(TransactionalFile.class.getName()).log(Level.SEVERE, null, ex);
424                         }
425                     }
426                     me.unlockAllLocks();
427                     tmp.setLocaloffset(tmp.getLocaloffset() + result);
428                 }
429               
430                 return result;
431             }
432
433         } else {           // add to the readers list  
434             me.addFile(this, 0);
435             return read(b);
436         }
437
438     }
439
440     public void write(byte[] data) throws IOException {
441
442         if (!(writemode)) {
443             throw new IOException();
444
445         }
446
447         ExtendedTransaction me = Wrapper.getTransaction();
448         int size = data.length;
449
450
451         if (me == null) // not a transaction 
452         {   
453             non_Transactional_Write(data);
454             return;
455         }
456         
457         if (me.getGlobaltoLocalMappings().containsKey(this)) 
458         {
459  
460             Byte[] by = new Byte[size];
461             for (int i = 0; i < size; i++) {
462                 by[i] = Byte.valueOf(data[i]);
463             }
464             TransactionLocalFileAttributes tmp = ((TransactionLocalFileAttributes) (me.getGlobaltoLocalMappings().get(this)));
465
466             Vector dummy;
467             if (((Vector)(me.getWriteBuffer().get(this.inode))) != null){
468                 dummy = new Vector((Vector)(me.getWriteBuffer().get(this.inode)));
469             }
470             else 
471                 dummy = new Vector();
472       
473             dummy.add(new WriteOperations(by, new Range(tmp.getLocaloffset(), tmp.getLocaloffset() + by.length), tmp.isUnknown_inital_offset_for_write(), this, tmp));
474             me.getWriteBuffer().put(this.inode, dummy);
475             
476             long loffset = tmp.getLocaloffset();
477              
478              
479             tmp.setLocaloffset(tmp.getLocaloffset() + by.length);
480             
481             me.merge_for_writes_done.put(inode, Boolean.FALSE);
482             if (!(tmp.isUnknown_inital_offset_for_write())){
483                 markAccessedBlocks(me, loffset, size, BlockAccessModesEnum.WRITE);
484             }
485                      
486             if (tmp.getOffsetdependency() == OffsetDependency.NO_ACCESS)
487                 tmp.offsetdependency = OffsetDependency.WRITE_DEPENDENCY_1;
488
489         } else {
490             me.addFile(this, 0);      
491             write(data);
492         }
493     }
494
495     
496     private void markAccessedBlocks(ExtendedTransaction me,long loffset, int size, BlockAccessModesEnum mode){
497         
498         TreeMap map;
499         
500         if (me.getAccessedBlocks().get(this.getInode()) != null)
501             map = (TreeMap) me.getAccessedBlocks().get(this.getInode());
502         else{ 
503             map = new TreeMap();
504             me.getAccessedBlocks().put(this.inode, map);
505         }
506         int startblock = FileBlockManager.getCurrentFragmentIndexofTheFile(loffset);
507         int targetblock = FileBlockManager.getTargetFragmentIndexofTheFile(loffset, size);
508         for (int i = startblock; i <= targetblock; i++) {
509             if (map.containsKey(Integer.valueOf(i))){
510                  if (map.get(Integer.valueOf(i)) != mode){ 
511                     map.put(Integer.valueOf(i), BlockAccessModesEnum.READ_WRITE);
512                  }
513             }
514             else{
515                   map.put(Integer.valueOf(i), mode);
516             }
517         }
518
519     }
520     
521
522     // reads the data directly from file, 
523     private int readFromFile(ExtendedTransaction me, byte[] readdata, TransactionLocalFileAttributes tmp) {
524         int st = FileBlockManager.getCurrentFragmentIndexofTheFile(tmp.getLocaloffset());
525         int end = FileBlockManager.getTargetFragmentIndexofTheFile(tmp.getLocaloffset(), readdata.length);
526         
527         BlockDataStructure block = null;
528         boolean locked = false;
529         for (int k = st; k <= end; k++) {
530             lockBlock(me, st, k);
531         }
532         if (me.getStatus() == Status.ABORTED) {
533              for (int i=st; i<=end; i++){
534                     block = this.inodestate.getBlockDataStructure(Integer.valueOf(i));
535                     me.getHeldblocklocks().add(block.getLock().readLock());
536              }
537                 throw new AbortedException();
538         }
539         int size = -1;
540         size = invokeNativepread(readdata, tmp.getLocaloffset(), readdata.length);
541         tmp.setLocaloffset(tmp.getLocaloffset() + size);
542         if (size == 0)
543             size = -1;
544         if (me.getStatus() == Status.ABORTED) {
545                 for (int i=st; i<=end; i++){
546                     block = this.inodestate.getBlockDataStructure(Integer.valueOf(i));
547                     me.getHeldblocklocks().add(block.getLock().readLock());
548                 }
549                 throw new AbortedException();
550         }
551         for (int p = st; p <= end; p++) {
552                     block = this.inodestate.getBlockDataStructure(Integer.valueOf(p));
553                     block.getLock().readLock().unlock();
554         }
555         return size;
556     }
557
558     private int readFromBuffer(byte[] readdata, TransactionLocalFileAttributes tmp, WriteOperations wrp, Range writerange) {
559         long loffset = tmp.getLocaloffset();
560
561         Byte[] data = (Byte[]) wrp.getData();
562         byte[] copydata = new byte[data.length];
563
564         for (int i = 0; i < data.length; i++) {
565             copydata[i] = data[i].byteValue();
566         }
567         System.arraycopy(copydata, (int) (loffset - writerange.getStart()), readdata, 0, readdata.length);
568         tmp.setLocaloffset(tmp.getLocaloffset() + readdata.length);
569         return readdata.length;
570
571     }
572
573     public void simpleWritetoBuffer(Byte[] data, Range newwriterange, TreeMap tm) {
574         tm.put(newwriterange, data);
575     }
576
577     public void unlockLocks(Vector heldlocks) {
578         for (int i = 0; i < heldlocks.size(); i++) {
579             ((Lock) heldlocks.get(i)).unlock();
580         }
581     }
582     
583
584     public void setInode(INode inode) {
585         this.inode = inode;
586     }
587     
588     public void lockOffset(ExtendedTransaction me){
589             boolean locked = false;
590             while (me.getStatus() == Status.ACTIVE) {                        //locking the offset
591                     offsetlock.lock();
592                locked = true;
593                break;
594           
595             }
596
597             if (me.getStatus() != Status.ACTIVE){
598                if (locked)
599                     me.getHeldoffsetlocks().add(offsetlock);
600                 throw new AbortedException();
601             }
602     }
603     
604     public void mergeWrittenData(ExtendedTransaction me){
605             
606             //ExtendedTransaction me = Wrapper.getTransaction();
607             boolean flag = false;
608             Vector vec = (Vector) me.getWriteBuffer().get(this.inode);     
609             Range intersectedrange = new Range(0, 0);
610             Iterator it1 = vec.iterator();
611             WriteOperations wrp;
612             WriteOperations wrp2;
613             Vector toberemoved = new Vector();
614             while (it1.hasNext()) {
615                 wrp = (WriteOperations) (it1.next());
616                 
617                 if (toberemoved.contains(wrp)){
618                     continue;
619                 }
620                     
621                 Iterator it2 = vec.listIterator();
622                 while (it2.hasNext()) {
623                     flag = false;
624                     wrp2 = (WriteOperations) (it2.next());
625                     /*if (wrp2.getRange().includes(wrp.getRange())) {
626                         flag = true;
627                         intersect = wrp2.getRange().intersection(wrp.getRange());
628                         break;
629                     }
630                     */
631                     if ((wrp2 == wrp) || toberemoved.contains(wrp2)){
632                         continue;
633                     }
634                         
635                     if (wrp.getRange().hasIntersection(wrp2.getRange())) {
636                         flag = true;
637                         intersectedrange = wrp2.getRange().intersection(wrp.getRange());
638                         toberemoved.add(wrp2);
639                     }
640                     
641                     
642                     long startprefix = 0;
643                     long endsuffix = 0;
644                     long startsuffix = 0;
645                     int prefixsize = 0;
646                     int suffixsize = 0;
647                     int intermediatesize = 0;
648                     Byte[] prefixdata = null;
649                     Byte[] suffixdata = null;
650                     boolean prefix = false;
651                     boolean suffix = false;
652                     if (flag){
653                         
654                         
655                         if (wrp.getRange().getStart() < wrp2.getRange().getStart()) {
656                              prefixdata = new Byte[(int) (wrp2.getRange().getStart() - wrp.getRange().getStart())];
657                              prefixdata = (Byte[]) (wrp.getData());
658                              startprefix = wrp.getRange().getStart();
659                              prefixsize = (int)(intersectedrange.getStart() - startprefix);
660                              intermediatesize = (int)(intersectedrange.getEnd() -intersectedrange.getStart());
661                              prefix = true;   
662                         }
663
664                         else if (wrp2.getRange().getStart() <= wrp.getRange().getStart()) {
665                              prefixdata = new Byte[(int) (wrp.getRange().getStart() - wrp2.getRange().getStart())];
666                              prefixdata = (Byte[]) (wrp2.getData());
667                              startprefix = wrp2.getRange().getStart();
668                              prefixsize = (int)(intersectedrange.getStart() - startprefix);
669                              intermediatesize = (int)(intersectedrange.getEnd() -intersectedrange.getStart());
670                              prefix = true;
671                         }
672
673                         if (wrp2.getRange().getEnd() >= wrp.getRange().getEnd()) {
674
675                              suffixdata = new Byte[(int) (wrp2.getRange().getEnd() - intersectedrange.getEnd())];
676                              suffixdata = (Byte[]) (wrp2.getData());
677                              startsuffix = intersectedrange.getEnd() - wrp2.getRange().getStart();
678                              suffixsize = (int)(wrp2.getRange().getEnd() - intersectedrange.getEnd());
679                              suffix = true;
680                              endsuffix = wrp2.getRange().getEnd();
681                         }
682
683                         else if (wrp.getRange().getEnd() > wrp2.getRange().getEnd()) {
684                              suffixdata = new Byte[(int) (wrp.getRange().getEnd() - intersectedrange.getEnd())];
685                              suffixdata = (Byte[]) (wrp.getData());
686                              startsuffix = intersectedrange.getEnd() - wrp.getRange().getStart();
687                              suffixsize = (int)(wrp.getRange().getEnd() - intersectedrange.getEnd());
688                              endsuffix = wrp.getRange().getEnd();
689                              suffix = true;
690
691                         }
692                         
693
694                         Byte[] data_to_insert;
695
696                         if ((prefix) && (suffix)) {
697                             data_to_insert = new Byte[(int) (endsuffix - startprefix)];
698                             System.arraycopy(prefixdata, 0, data_to_insert, 0, prefixsize);
699                             System.arraycopy(wrp2.getData(), (int)(intersectedrange.getStart() - wrp2.getRange().getStart()), data_to_insert, prefixsize, intermediatesize);
700                             System.arraycopy(suffixdata, (int)startsuffix, data_to_insert, (prefixsize + intermediatesize), suffixsize);
701                             wrp.setData(data_to_insert);
702                             wrp.setRange(new Range(startprefix, endsuffix));
703                         }
704                        
705                     }
706                 }
707             }
708             Iterator it = toberemoved.iterator();
709             while (it.hasNext())
710                 vec.remove(it.next());
711             
712             toberemoved.clear();
713             Collections.sort(vec);
714             me.merge_for_writes_done.put(inode, Boolean.TRUE);
715       
716     }
717     
718     public void non_Transactional_Write(byte[] data){
719         
720             Vector heldlocks = new Vector();
721             boolean flag = true;
722             offsetlock.lock();
723             int startblock = FileBlockManager.getCurrentFragmentIndexofTheFile(committedoffset.getOffsetnumber());
724             int targetblock = FileBlockManager.getTargetFragmentIndexofTheFile(committedoffset.getOffsetnumber(), data.length);
725             for (int i = startblock; i <= targetblock; i++) {
726                 BlockDataStructure block =this.inodestate.getBlockDataStructure(i);
727                 block.getLock().writeLock().lock(); 
728                     heldlocks.add(block.getLock().writeLock());
729             }
730
731             try {
732
733                 file.seek(committedoffset.getOffsetnumber());
734                 file.write(data);                    
735
736                 committedoffset.setOffsetnumber(committedoffset.getOffsetnumber() +data.length);
737
738             } catch (IOException ex) {
739                 Logger.getLogger(TransactionalFile.class.getName()).log(Level.SEVERE, null, ex);
740             } finally {
741                 unlockLocks(heldlocks);
742                 offsetlock.unlock();
743             }
744     }
745     
746     public int non_Transactional_Read(byte[] b){
747         
748             int size = -1;
749             Vector heldlocks = new Vector();
750             boolean flag = true;
751             offsetlock.lock();
752             int startblock;    
753             int targetblock; 
754             startblock = FileBlockManager.getCurrentFragmentIndexofTheFile(committedoffset.getOffsetnumber());
755             targetblock = FileBlockManager.getTargetFragmentIndexofTheFile(committedoffset.getOffsetnumber(), size);
756        
757             for (int i = startblock; i <= targetblock; i++) {
758                 BlockDataStructure block = this.inodestate.getBlockDataStructure(i);
759                 block.getLock().readLock().lock();    
760                     heldlocks.add(block.getLock().readLock());
761                
762             }
763             
764             size = invokeNativepread(b, committedoffset.getOffsetnumber(), b.length);
765
766             committedoffset.setOffsetnumber(committedoffset.getOffsetnumber() +size);
767             if (!(committedoffset.getOffsetReaders().isEmpty())){
768                 Iterator it2 =  committedoffset.getOffsetReaders().iterator(); // for visible readers strategy
769                 while ( it2.hasNext())
770                 {
771                     ExtendedTransaction tr = (ExtendedTransaction) it2.next();
772                     tr.abort();
773             }   
774             committedoffset.getOffsetReaders().clear();
775             }
776
777         
778             unlockLocks(heldlocks);
779             offsetlock.unlock();
780             if (size == 0)
781                 size = -1;
782             return size;
783     }
784     
785     public void non_Transactional_Seek(long offset){
786             offsetlock.lock();
787                 committedoffset.setOffsetnumber(offset);
788             offsetlock.unlock();
789     }
790
791     public long non_Transactional_getFilePointer(){
792             long offset = -1;;
793             offsetlock.lock();
794                 offset = committedoffset.getOffsetnumber();
795             offsetlock.unlock();
796             return offset;
797     }
798     
799     public int compareTo(Object arg0) {
800         TransactionalFile tf = (TransactionalFile) arg0;
801         if (this.inode.getNumber() < tf.inode.getNumber())
802             return -1;
803         else if (this.inode.getNumber() > tf.inode.getNumber())
804             return 1;
805         else {
806             if (this.sequenceNum < tf.sequenceNum)
807                 return -1;
808             else 
809                 return 1;
810         }
811     }
812     
813     public void makeDependentonOffet(ExtendedTransaction me, TransactionLocalFileAttributes tmp){
814         
815             if (tmp.getOffsetdependency() != OffsetDependency.WRITE_DEPENDENCY_2){     
816                         tmp.setLocaloffset(tmp.getLocaloffset() + this.committedoffset.getOffsetnumber() - tmp.getCopylocaloffset()); 
817             }
818                     
819             tmp.setOffsetdependency(OffsetDependency.READ_DEPENDENCY);  
820             if (!(this.committedoffset.getOffsetReaders().contains(me))){
821                 this.committedoffset.getOffsetReaders().add(me);
822
823             }
824     }
825     
826     public void makeWriteAbsolute(ExtendedTransaction me, WriteOperations wrp){
827             wrp.getRange().setStart(wrp.getOwnerTF().committedoffset.getOffsetnumber() - wrp.getTFA().getCopylocaloffset() + wrp.getRange().getStart());
828             wrp.getRange().setEnd(wrp.getOwnerTF().committedoffset.getOffsetnumber() - wrp.getTFA().getCopylocaloffset() + wrp.getRange().getEnd());
829             if ((wrp.getTFA().getOffsetdependency() == OffsetDependency.WRITE_DEPENDENCY_1)  || (wrp.getTFA().offsetdependency == OffsetDependency.NO_ACCESS) || (wrp.getTFA().getOffsetdependency() == OffsetDependency.WRITE_DEPENDENCY_2)){
830                 wrp.getTFA().setOffsetdependency(OffsetDependency.READ_DEPENDENCY);
831                 wrp.getTFA().setUnknown_inital_offset_for_write(false);
832                 if (!(wrp.getOwnerTF().committedoffset.getOffsetReaders().contains(me)))
833                     wrp.getOwnerTF().committedoffset.getOffsetReaders().add(me);
834                 wrp.getTFA().setLocaloffset(wrp.getTFA().getLocaloffset() + wrp.getOwnerTF().committedoffset.getOffsetnumber() - wrp.getTFA().getCopylocaloffset());
835             }
836         
837     }
838     
839     
840     private void lockBlock(ExtendedTransaction me, int st, int k){
841         BlockDataStructure block;
842         boolean locked = false;
843             while (me.getStatus() == Status.ACTIVE) {
844                 block = this.inodestate.getBlockDataStructure(Integer.valueOf(k));
845       
846                 block.getLock().readLock().lock();
847                         if (!(block.getReaders().contains(me))){
848                             block.getReaders().add(me);
849                         }
850                         locked = true;
851                      break;
852             }
853             
854             if (me.getStatus() == Status.ABORTED) {
855                 int m;
856                 if (locked){
857                     m = k+1;
858                 }
859                 else 
860                     m = k;
861                 for (int i=st; i<m; i++){
862                     block = this.inodestate.getBlockDataStructure(Integer.valueOf(k));
863                     me.getHeldblocklocks().add(block.getLock().readLock());
864                 }
865              
866                 locked = false;
867                 
868                 throw new AbortedException();
869             }
870     }
871
872         // for block versioning mechanism
873             /*if (!(validateBlocksVersions(startblock, targetblock))) { ////check to see if version are still valid 
874             
875                     throw new AbortedException();
876             
877             }*/
878                        /*  
879                         int expvalue = ((Integer) tmp.getBlockversions().get(Integer.valueOf(k))).intValue();
880                         while (me.getStatus() == Status.ACTIVE) {
881                             BlockDataStructure block = ((BlockDataStructure) tmp.adapter.lockmap.get(Integer.valueOf(k)));
882                             if (block.getLock().tryLock()) {
883                                 heldlocks.add(block.getLock());
884                                 if (!(block.getVersion().get() == expvalue)) {  // for block versioning mechanism
885                                         me.abort();
886                                 } 
887                                 else {
888                                         break;
889                                 }
890                             } 
891                             else {
892                                     me.getContentionManager().resolveConflict(me, block.getOwner());
893                             }
894                         }
895                       if (me.getStatus() == Status.ABORTED) {
896                             unlockLocks(heldlocks);
897                             offsetlock.unlock();
898                             throw new AbortedException();
899                         }
900                     }
901                    }*/
902     
903     
904 /*    public boolean validateBlocksVersions(int startblock, int targetblock) { // For Block Versioning Mechanism
905         boolean valid = true;
906         ExtendedTransaction me = ExtendedTransaction.getTransaction();
907         TransactionLocalFileAttributes tmp = ((TransactionLocalFileAttributes) (me.getFilesAccesses().get(this.getInode())));
908         for (int i = startblock; i <= targetblock; i++) {
909             int expvalue = ((Integer) tmp.getBlockversions().get(Integer.valueOf(i))).intValue();
910             BlockDataStructure block = ((BlockDataStructure) tmp.adapter.lockmap.get(Integer.valueOf(i)));
911             if (expvalue != block.getVersion().get()) {
912                 valid = false;
913                 break;
914             }
915         }
916
917         return valid;
918     }*/
919
920