KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > mr > core > persistent > file > MantaFatFile


1 /*
2  * Copyright 2002 by
3  * <a HREF="http://www.coridan.com">Coridan</a>
4  * <a HREF="mailto: support@coridan.com ">support@coridan.com</a>
5  *
6  * The contents of this file are subject to the Mozilla Public License Version
7  * 1.1 (the "License"); you may not use this file except in compliance with the
8  * License. You may obtain a copy of the License at
9  * http://www.mozilla.org/MPL/
10  *
11  * Software distributed under the License is distributed on an "AS IS" basis,
12  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
13  * for the specific language governing rights and limitations under the
14  * License.
15  *
16  * The Original Code is "MantaRay" (TM).
17  *
18  * The Initial Developer of the Original Code is Amir Shevat.
19  * Portions created by the Initial Developer are Copyright (C) 2006
20  * Coridan Inc. All Rights Reserved.
21  *
22  * Contributor(s): all the names of the contributors are added in the source
23  * code where applicable.
24  *
25  * Alternatively, the contents of this file may be used under the terms of the
26  * LGPL license (the "GNU LESSER GENERAL PUBLIC LICENSE"), in which case the
27  * provisions of LGPL are applicable instead of those above. If you wish to
28  * allow use of your version of this file only under the terms of the LGPL
29  * License and not to allow others to use your version of this file under
30  * the MPL, indicate your decision by deleting the provisions above and
31  * replace them with the notice and other provisions required by the LGPL.
32  * If you do not delete the provisions above, a recipient may use your version
33  * of this file under either the MPL or the GNU LESSER GENERAL PUBLIC LICENSE.
34  
35  *
36  * This library is free software; you can redistribute it and/or modify it
37  * under the terms of the MPL as stated above or under the terms of the GNU
38  * Lesser General Public License as published by the Free Software Foundation;
39  * either version 2.1 of the License, or any later version.
40  *
41  * This library is distributed in the hope that it will be useful, but WITHOUT
42  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
43  * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
44  * License for more details.
45  */

46 /*
47  * Created on Feb 18, 2004
48  * Manta LTD
49  */

50 package org.mr.core.persistent.file;
51
52 import java.io.File JavaDoc;
53
54 import java.io.IOException JavaDoc;
55 import java.io.RandomAccessFile JavaDoc;
56 import java.nio.ByteBuffer JavaDoc;
57 import java.nio.MappedByteBuffer JavaDoc;
58 import java.nio.channels.FileChannel JavaDoc;
59 import java.nio.channels.FileLock JavaDoc;
60
61 import org.apache.commons.logging.Log;
62 import org.apache.commons.logging.LogFactory;
63 import org.mr.core.persistent.PersistentConst;
64 import org.mr.core.util.byteable.ByteBufferFactory;
65
66
67 /**
68  *
69  * MantaFatFile - very cool class ,do not change unless you talk to me.
70  * This class give you the ability to write "files" in to our FAT,
71  * the FAT is a memory mapped file that is "known" to be faster the regular files.
72  * another cool thing is that the delete and save are very fast O(1), this is because the file name
73  * are well formed (int no bigger the a configurable number) so no lookups are needed
74  *
75  * @since Feb 18, 2004
76  * @version 1.0
77  * @author Amir Shevat
78  
79  */

80 public class MantaFatFile {
81     
82     // the fat file can be no bigger then this number in bytes
83
public static final int MAX_FAT_FILE_SIZE = Integer.MAX_VALUE;
84     // any file if bigger then this size (- 10 bites for cluster metadata)
85
// will be broken in to CLUSTER_SIZE size chunks
86
public static final int CLUSTER_SIZE =1024;
87     // the fat will not hold more then this amount of files
88
public static final int MAX_FILES_IN_FAT = 10000;
89     // every cluster is numbered with this amount of bytes (int = 4 bytes)
90
public static final int BYTES_TO_INDEX_CLUSTER = 4;
91     // we will write 2 bytes (short) as length of bytes(data) written in the cluster
92
public static final int BYTES_DATA_LENGTH_IN_CLUSTER =2;
93     // this file will hold a file table that will take this size
94
public static final int FILE_TABLE_SIZE = MAX_FILES_IN_FAT*BYTES_TO_INDEX_CLUSTER;
95     // 1 k for fat metadata info
96
public static final int FAT_METADATA_SIZE = 1024;
97     
98     // the location of the root cluster
99
private static final int ROOT_CULSTER_INDEX =FAT_METADATA_SIZE +FILE_TABLE_SIZE;
100     // this is the null Terminator indicating that the next cluster is free/not allocated
101
private static final int NULL_CLUSTER_INDEX = -1;
102     
103     // the fat will hold no more the this number of clusters
104
public static final int MAX_NUMBER_OF_CLUSTERS = (MAX_FAT_FILE_SIZE-ROOT_CULSTER_INDEX)/CLUSTER_SIZE;
105     // fat file will be init with this amount of free clusters
106
public static final int INITIAL_CULSTER_CAPACITY = 500;
107     // when more space is needed we will increment the size of clusters by this value
108
public static final int INCREMENT_CULSTER_VALUE =5000;
109     /**
110      * clusters stract
111      */

112     // the offset of the next cluster index MetaData in the cluster
113
private static final int CLUSTER_NEXT_MD_OFFSET =0;
114     // the offset of the previous cluster index MetaData in the cluster
115
private static final int CLUSTER_PREVIOUS_MD_OFFSET =CLUSTER_NEXT_MD_OFFSET+BYTES_TO_INDEX_CLUSTER;
116     // after the metadata of the next and previous we write a
117
// short meta data for the length of data written in the cluster
118
private static final int CLUSTER_DATA_LENGTH_MD_OFFSET = CLUSTER_PREVIOUS_MD_OFFSET+BYTES_TO_INDEX_CLUSTER;
119     // after the metadata comes the data
120
private static final int CLUSTER_DATA_OFFSET =CLUSTER_DATA_LENGTH_MD_OFFSET+BYTES_DATA_LENGTH_IN_CLUSTER;
121     // size for raw data
122
private static final int MAX_DATA_SIZE_IN_CLUSTER =CLUSTER_SIZE -((BYTES_TO_INDEX_CLUSTER*2)+BYTES_DATA_LENGTH_IN_CLUSTER);
123     
124     /**
125      * fat stract
126      */

127     private static final int FAT_TABLE_OFFSET = 0;
128     private static final int FAT_METADATA_OFFSET = FAT_TABLE_OFFSET+FILE_TABLE_SIZE;
129     
130     /**
131      * fat metadata stract
132      */

133     private static final int METADATA_FILE_COUNT_OFFSET = 0;
134     private static final int METADATA_FREE_CLUSTER_COUNT_OFFSET = METADATA_FILE_COUNT_OFFSET+4;
135     private static final int METADATA_ASSIGNED_CLUSTER_COUNT_OFFSET = METADATA_FREE_CLUSTER_COUNT_OFFSET+4;
136     private static final int METADATA_FAT_FILE_SIZE_OFFSET = METADATA_ASSIGNED_CLUSTER_COUNT_OFFSET+4;
137     
138     
139     // all these member are saved in the metadata
140
private int fileInFatCount = 0;
141     // free Clusters for file allocation
142
private int freeClustersCount = 0;
143      // root is always assigned
144
private int assignedClusterCount = 1;
145     // the file size in bytes
146
private int currentFileSize =0;
147     
148     private File JavaDoc physicalFile;
149     private RandomAccessFile JavaDoc randomAccessFile;
150
151     private FileLock JavaDoc lock;
152     private MappedByteBuffer JavaDoc fatBuff;
153     private String JavaDoc fatFilePath;
154     private static Log log;
155     
156     
157     /**
158      * loads or creates the fat
159      */

160      MantaFatFile(String JavaDoc fatFilePath) {
161          log=LogFactory.getLog("MantaFatFile");
162          try {
163                 if(!recoverFromFile(fatFilePath))
164                     createNewFatFile(fatFilePath);
165             } catch (IOException JavaDoc e) {
166                 log.error("problem creating new fat file",e );
167             }
168             this.fatFilePath = fatFilePath;
169             
170     }
171     
172     /**
173      * @return the list of files that are currently saved in the FAT
174      */

175     public synchronized int[] getFileList(){
176         int[] list = new int[fileInFatCount];
177         int j = 0;
178         for(int i= 1 ; i < MAX_FILES_IN_FAT && j<list.length ; i++){
179             if(fileExit(i))
180                 list[j++] =i ;
181         }
182         int[] temp;
183         if( j < fileInFatCount){
184             // we have less files mapped then what fileInFatCount say
185
temp = new int[j];
186             for (int i = 0; i < j; i++) {
187                 temp[i] = list[i];
188             }
189             list = temp;
190             saveFilesInFatCount(j);
191         }
192         return list;
193     }
194     
195     /**
196      * saves a file with a given name and content existing file with the same
197      * file name will be deleted
198      * @param fileName the name of the file must be valid see checkValidFileName
199      * @param fileContent a byteBuffer with the data after flip/rewind
200      * @throws IOException
201      */

202     public synchronized void save(int fileName , ByteBuffer JavaDoc fileContent) throws IOException JavaDoc{
203         
204         //System.out.println("start save"+fileName);
205

206         checkValidFileName(fileName);
207         if(fileExit(fileName)){
208             delete(fileName);
209         }
210         
211         int fileSize = fileContent.limit();
212         int numOfClustersNeeded = (int)Math.ceil((double)fileSize/MAX_DATA_SIZE_IN_CLUSTER);
213         int clusterIndex = assignCluster();
214         saveFileLength(clusterIndex ,fileSize );
215         writeDataToCluster(clusterIndex , fileContent);
216         saveEntryInFileTable(fileName ,clusterIndex );
217         int nextClusterIndex = NULL_CLUSTER_INDEX;
218         for (int i = 1; i < numOfClustersNeeded; i++) {
219             nextClusterIndex =assignCluster();
220             writeDataToCluster(nextClusterIndex , fileContent);
221             linkClusters(clusterIndex ,nextClusterIndex );
222             clusterIndex = nextClusterIndex;
223         }
224         fileInFatCount++;
225         saveFilesInFatCount(fileInFatCount);
226         if(MantaFileManager.forceEveryEntry){
227             fatBuff.force();
228         }
229             
230         
231     }// save
232

233     
234     /**
235      * returns true if file exits works in O(1)
236      * @param fileName see checkValidFileName for valid names
237      * @return true id found else false
238      */

239     public synchronized boolean fileExit(int fileName){
240         checkValidFileName(fileName);
241         int rootCluster = getRootClusterFromFileTable(fileName);
242         return rootCluster != NULL_CLUSTER_INDEX;
243     }
244     
245     /**
246      * deletes a file from the FAT done in very close to O(1)
247      * @param fileName see checkValidFileName for valid names
248      * @return true if found and deleted
249      */

250     public synchronized boolean delete(int fileName){
251         checkValidFileName(fileName);
252         // fond the first cluster of the link cluster list
253
int fileRootCluster = deleteEntryInFileTable(fileName);
254         if(fileRootCluster == NULL_CLUSTER_INDEX)
255             return false;
256         int fileSize = getFileLength(fileRootCluster);
257         int numOfClustersNeeded = (int)Math.ceil((double)fileSize/MAX_DATA_SIZE_IN_CLUSTER);
258         // free the used cluster
259
// we add to the end of the free clusters list the list that we want to free
260
// and set the end of the free clusters list to the new location
261
int lastFreeCluster = getLastFreeClusterIndex();
262         linkClusters(lastFreeCluster ,fileRootCluster );
263         // find and set the new last cluster
264
int newLastFreeCluster = fileRootCluster;
265         for (int i = 1; i < numOfClustersNeeded; i++) {
266             newLastFreeCluster = getNextClusterIndex(newLastFreeCluster);
267         }
268         setLastFreeClusterIndex(newLastFreeCluster);
269         
270         freeClustersCount += numOfClustersNeeded;
271         saveFreeClustersCount(freeClustersCount);
272         assignedClusterCount -= numOfClustersNeeded;
273         saveAssignedClusterCount(assignedClusterCount);
274         fileInFatCount--;
275         saveFilesInFatCount(fileInFatCount);
276         return true;
277     }
278     
279     /**
280      * reads and returns the file content of a given file name
281      * @param fileName see checkValidFileName for valid file names
282      * @return the NIO ByteBuffer with the file content after flip
283      */

284     public synchronized ByteBuffer JavaDoc load(int fileName){
285         checkValidFileName(fileName);
286         ByteBuffer JavaDoc result = null;
287         int clusterIndex = getRootClusterFromFileTable(fileName);
288         // file does not exist
289
if(clusterIndex == NULL_CLUSTER_INDEX)
290             return null;
291         int fileSize = getFileLength(clusterIndex);
292         
293         ByteBufferFactory pool =PersistentConst.getPersistentByteBufferPool();
294         if(pool != null){
295             result = pool.getBuffer(fileSize );
296         }else{
297             result = ByteBuffer.allocate(fileSize);
298         }
299     
300         fileSize -= readDataFromCluster( clusterIndex , result );
301         while(fileSize>0){
302             clusterIndex =getNextClusterIndex(clusterIndex);
303             fileSize -= readDataFromCluster( clusterIndex , result );
304         }
305         result.flip();
306         return result;
307     }
308     
309     /**
310      * file name must be an int and can not be less the 1 or more then member MAX_FILES_IN_FAT
311      * @param fileName the file to check
312      */

313     private void checkValidFileName(int fileName){
314         if(fileName > MAX_FILES_IN_FAT || fileName<1){
315             throw new IllegalArgumentException JavaDoc("Invalid file name "+fileName+" fileName must be between 1 and "+MAX_FILES_IN_FAT);
316         }
317     }
318     
319     
320     /**
321      * reads all the data written in the cluster in to a given buffer
322      */

323     private int readDataFromCluster(int clusterIndex, ByteBuffer JavaDoc result) {
324         int clusterDataLength = getClusterDataLength(clusterIndex);
325         setPosition(clusterIndex+CLUSTER_DATA_OFFSET);
326         for(int i = 0 ; i<clusterDataLength ; i++ ){
327             result.put(fatBuff.get());
328         }
329         return clusterDataLength;
330         
331     }
332     
333     /**
334      * the file length is kept in the previous of the first cluster of the file
335      */

336     private int getFileLength(int fileRootCluster){
337         return getPreviousClusterIndex(fileRootCluster);
338     }
339     
340     /**
341      * the file length is kept in the previous of the first cluster of the file
342      */

343     private void saveFileLength(int fileRootCluster, int fileSize){
344         setPreviousClusterIndex(fileSize , fileRootCluster);
345     }
346     
347     /**
348      * writes and saves all that data that is in the buffer that can be fit
349      * in to the cluster
350      */

351     private void writeDataToCluster(int clusterIndex , ByteBuffer JavaDoc fileContent ){
352         setPosition(clusterIndex+CLUSTER_DATA_OFFSET);
353         int dataInCluster = 0;
354         while(fileContent.hasRemaining() && dataInCluster<MAX_DATA_SIZE_IN_CLUSTER){
355             fatBuff.put(fileContent.get());
356             dataInCluster++;
357         }
358         setClusterDataLength(clusterIndex ,(short)dataInCluster );
359     }
360     
361     /**
362      * saves the index of the first cluster in the proper place in the fat
363      * @param fileName the file saved
364      * @param firstClusterIndex the address of the first cluster of this file
365      */

366     private void saveEntryInFileTable(int fileName ,int firstClusterIndex ){
367         setPosition(FAT_TABLE_OFFSET+(fileName*BYTES_TO_INDEX_CLUSTER));
368         fatBuff.putInt(firstClusterIndex);
369     }
370     
371     /**
372      * returns the first cluster in the linked list that is the file
373      * @param fileName
374      * @return the first cluster index or NULL_CLUSTER_INDEX if not in FAT
375      */

376     private int getRootClusterFromFileTable(int fileName){
377         setPosition(FAT_TABLE_OFFSET+(fileName*BYTES_TO_INDEX_CLUSTER));
378         return fatBuff.getInt();
379         
380     }
381     /**
382      * deletes the entry of the first cluster of this file name and returns is
383      * @param fileName the name of the file to be deleted
384      * @return the root cluster of the file
385      */

386     private int deleteEntryInFileTable(int fileName){
387         
388         setPosition(FAT_TABLE_OFFSET+(fileName*BYTES_TO_INDEX_CLUSTER));
389         int fileRootCluster = fatBuff.getInt();
390         setPosition(FAT_TABLE_OFFSET+(fileName*BYTES_TO_INDEX_CLUSTER));
391         fatBuff.putInt(NULL_CLUSTER_INDEX);
392         return fileRootCluster;
393     }
394     
395     /**
396      * when no more Clusters are free this method creates new free Clusters
397      * @return
398      * @throws IOException
399      */

400     private int assignCluster() throws IOException JavaDoc{
401         
402         int nextFreeCluster = getNextClusterIndex(ROOT_CULSTER_INDEX);
403         if( nextFreeCluster == NULL_CLUSTER_INDEX){
404             if(freeClustersCount != 0 && log.isWarnEnabled()){
405                 log.warn("FAT netFreeCluster=null : freeClustersCount = "+freeClustersCount);
406                 
407             }
408             allocateFreeClusters();
409             nextFreeCluster = getNextClusterIndex(ROOT_CULSTER_INDEX);
410         }
411         freeClustersCount--;
412         saveFreeClustersCount(freeClustersCount);
413         assignedClusterCount++;
414         saveAssignedClusterCount(assignedClusterCount);
415         // remove the cluster from the free link
416
int newNextFree = getNextClusterIndex(nextFreeCluster);
417         if(newNextFree != NULL_CLUSTER_INDEX){
418             // link the next of the free list to the root
419
linkClusters(ROOT_CULSTER_INDEX ,newNextFree );
420         }else{
421             // set the next of root to null (next assignCluster() method call should allocateFreeClusters or next delete() free clusters)
422
setNextClusterIndex(ROOT_CULSTER_INDEX , NULL_CLUSTER_INDEX);
423             setLastFreeClusterIndex(ROOT_CULSTER_INDEX);
424         }
425         
426         // terminate this cluster next and privious
427
setNextClusterIndex(nextFreeCluster , NULL_CLUSTER_INDEX);
428         setPreviousClusterIndex(NULL_CLUSTER_INDEX , nextFreeCluster);
429         return nextFreeCluster;
430         
431     }
432     
433     private boolean recoverFromFile(String JavaDoc fatFilePath){
434         physicalFile = new File JavaDoc(fatFilePath);
435         if(physicalFile.exists() == false)
436             return false;
437         int needFileSize = ROOT_CULSTER_INDEX;
438         try {
439             randomAccessFile = new RandomAccessFile JavaDoc(physicalFile , "rw");
440             
441             lock = randomAccessFile.getChannel().tryLock();
442             if(lock == null){
443                 log.fatal("Two applications are trying to read the same FAT, this is very bad (FAT not integrity safe), name="+this.physicalFile.getName());
444             }
445             fatBuff = randomAccessFile.getChannel().map(FileChannel.MapMode.READ_WRITE ,0, needFileSize );
446             
447             // read the metadata of the file
448
// all these member are loaded form the metadata
449
fileInFatCount = loadFilesInFatCount();
450             // free Clusters for file allocation
451
freeClustersCount = loadFreeClustersCount();
452             // root is always assigned
453
assignedClusterCount = loadAssignedClusterCount();
454             // the file size in bytes
455
currentFileSize = loadCurrentFileSize();
456             fatBuff = randomAccessFile.getChannel().map(FileChannel.MapMode.READ_WRITE ,0, currentFileSize );
457         } catch (Exception JavaDoc e) {
458             
459             if(log.isFatalEnabled()){
460                 log.fatal("could not load fat file "+fatFilePath,e);
461                 return false;
462             }//if
463

464         }
465         
466         return true;
467     }
468     
469     private void createNewFatFile(String JavaDoc fatFilePath) throws IOException JavaDoc{
470         // create the file and the file mapping
471
physicalFile = new File JavaDoc(fatFilePath);
472         randomAccessFile = new RandomAccessFile JavaDoc(physicalFile , "rw");
473         int needFileSize = ROOT_CULSTER_INDEX+CLUSTER_SIZE;
474         lock = randomAccessFile.getChannel().tryLock();
475         if(lock == null){
476             log.fatal("Two applications are trying to read the same FAT, this is very bad (FAT not integrity safe), name="+this.physicalFile.getName());
477         }
478         fatBuff = randomAccessFile.getChannel().map(FileChannel.MapMode.READ_WRITE ,0, needFileSize );
479         currentFileSize = needFileSize;
480         saveCurrentFileSize(currentFileSize);
481         
482         //create the fat empty table
483
setPosition(FAT_TABLE_OFFSET);
484         for (int i = 0; i < MAX_FILES_IN_FAT; i++) {
485             fatBuff.putInt(NULL_CLUSTER_INDEX);
486         }
487         // create root cluster
488
setClusterDataLength(ROOT_CULSTER_INDEX,(short)0);
489         setNextClusterIndex(ROOT_CULSTER_INDEX,NULL_CLUSTER_INDEX);
490         setPreviousClusterIndex( NULL_CLUSTER_INDEX, ROOT_CULSTER_INDEX);
491         //and the INITIAL_CULSTER_CAPACITY clusters
492
allocateFreeClusters(INITIAL_CULSTER_CAPACITY);
493
494         
495     }
496     
497     /**
498      * when no more Clusters are free this method creates new free Clusters
499      * @throws IOException if NIO throws one
500      */

501     private void allocateFreeClusters() throws IOException JavaDoc{
502         allocateFreeClusters(INCREMENT_CULSTER_VALUE);
503         
504     }
505     /**
506      * when no more Clusters are free this method creates new free Clusters
507      * @param numberOfCluster the number of free clusters to create
508      * @throws IOException
509      */

510     private void allocateFreeClusters(int numberOfCluster) throws IOException JavaDoc{
511         int needFileSize = numberOfCluster*CLUSTER_SIZE;
512         fatBuff = randomAccessFile.getChannel().map(FileChannel.MapMode.READ_WRITE ,0, needFileSize+currentFileSize );
513         int previous =ROOT_CULSTER_INDEX;
514         int clusterIndex = NULL_CLUSTER_INDEX;
515         for (int i = 0; i < numberOfCluster; i++) {
516             clusterIndex =getClusterIndex(assignedClusterCount+i);
517             linkClusters(previous,clusterIndex);
518             setClusterDataLength(clusterIndex , (short)0);
519             previous =clusterIndex;
520         }
521         setNextClusterIndex(clusterIndex,NULL_CLUSTER_INDEX);
522         setLastFreeClusterIndex(clusterIndex);
523         freeClustersCount = numberOfCluster;
524         saveFreeClustersCount(freeClustersCount);
525         currentFileSize =currentFileSize+needFileSize;
526         saveCurrentFileSize(currentFileSize);
527     }
528     
529     /**
530      * returns the start position of the cluster in the file
531      * @param clusterCount the cluster number
532      * @return the address of the cluster
533      */

534     private int getClusterIndex(int clusterCount){
535         return ROOT_CULSTER_INDEX+(clusterCount*CLUSTER_SIZE);
536     }
537     
538     private void setLastFreeClusterIndex(int lastClusterIndex){
539         // the last free cluster index is kept in the root-> previous
540
setPreviousClusterIndex(lastClusterIndex ,ROOT_CULSTER_INDEX);
541     }
542     
543     private int getLastFreeClusterIndex(){
544         // the last free cluster index is kept in the root-> previous
545
return getPreviousClusterIndex(ROOT_CULSTER_INDEX);
546     }
547     
548     /**
549      * sets the cluster metadata regarding the amount of data written
550      * to this cluster
551      * @param clusterIndex the cluster address
552      * @param dataLength the amount of data written
553      */

554     private void setClusterDataLength(int clusterIndex ,short dataLength){
555         setPosition(clusterIndex+CLUSTER_DATA_LENGTH_MD_OFFSET);
556         fatBuff.putShort(dataLength);
557     }
558     
559     /**
560      * returns the amount of data written to this cluster can be 0 to cluster free space
561      * @param clusterIndex the cluster address
562      * @return the amount of data wirtten to this
563      */

564     private short getClusterDataLength(int clusterIndex){
565         setPosition(clusterIndex+CLUSTER_DATA_LENGTH_MD_OFFSET);
566         return fatBuff.getShort();
567     }
568     
569     /**
570      * links to clusters together
571      */

572     private void linkClusters(int previousClusterIndex ,int nextClusterIndex){
573         setNextClusterIndex( previousClusterIndex , nextClusterIndex);
574         setPreviousClusterIndex( previousClusterIndex , nextClusterIndex);
575     }
576     
577     private void setNextClusterIndex(int previousClusterIndex ,int nextClusterIndex){
578         setPosition(previousClusterIndex+CLUSTER_NEXT_MD_OFFSET);
579         fatBuff.putInt(nextClusterIndex);
580     }
581     
582     private void setPreviousClusterIndex(int previousClusterIndex ,int nextClusterIndex){
583         setPosition(nextClusterIndex+CLUSTER_PREVIOUS_MD_OFFSET);
584         fatBuff.putInt(previousClusterIndex);
585     }
586     
587     private int getNextClusterIndex(int previousClusterIndex){
588         setPosition(previousClusterIndex+CLUSTER_NEXT_MD_OFFSET);
589         return fatBuff.getInt();
590         
591     }
592     
593     private int getPreviousClusterIndex(int nextClusterIndex){
594         setPosition(nextClusterIndex+CLUSTER_PREVIOUS_MD_OFFSET);
595         return fatBuff.getInt();
596     }
597     
598     /**
599      * FAT metadata methods
600      *
601      */

602     
603     /**
604      * @param fileCount the number of files in the fat
605      */

606     private void saveFilesInFatCount(int fileCount){
607         setPosition(FAT_METADATA_OFFSET+METADATA_FILE_COUNT_OFFSET);
608         fatBuff.putInt(fileCount);
609     }
610
611     private int loadFilesInFatCount(){
612         setPosition(FAT_METADATA_OFFSET+METADATA_FILE_COUNT_OFFSET);
613         return fatBuff.getInt();
614     }
615     
616     private void saveFreeClustersCount(int freeClustersCount){
617         setPosition(FAT_METADATA_OFFSET+METADATA_FREE_CLUSTER_COUNT_OFFSET);
618         fatBuff.putInt(freeClustersCount);
619     }
620
621     private int loadFreeClustersCount(){
622         setPosition(FAT_METADATA_OFFSET+METADATA_FREE_CLUSTER_COUNT_OFFSET);
623         return fatBuff.getInt();
624     }
625     
626     private void saveAssignedClusterCount(int assignedClusterCount){
627         setPosition(FAT_METADATA_OFFSET+METADATA_ASSIGNED_CLUSTER_COUNT_OFFSET);
628         fatBuff.putInt(assignedClusterCount);
629     }
630
631     private int loadAssignedClusterCount(){
632         setPosition(FAT_METADATA_OFFSET+METADATA_ASSIGNED_CLUSTER_COUNT_OFFSET);
633         return fatBuff.getInt();
634     }
635     
636     private void saveCurrentFileSize(int currentFileSize){
637         setPosition(FAT_METADATA_OFFSET+METADATA_FAT_FILE_SIZE_OFFSET);
638         fatBuff.putInt(currentFileSize);
639         
640     }
641
642     private int loadCurrentFileSize(){
643         setPosition(FAT_METADATA_OFFSET+METADATA_FAT_FILE_SIZE_OFFSET);
644         return fatBuff.getInt();
645     }
646     
647     
648     private final void setPosition(int pos){
649         if(pos < 10 && pos % 4 != 0){
650             LogFactory.getLog("MantaFatFile").debug("got to eror position"+pos);
651         }
652         if(fatBuff== null){
653             throw new IllegalStateException JavaDoc("FAT not created");
654         }
655         fatBuff.position(pos);
656     }
657     
658     
659     /**
660      * @return a string representation of the fat data
661      */

662     public String JavaDoc toString(){
663         StringBuffer JavaDoc str = new StringBuffer JavaDoc();
664         str.append("\nMAX_FAT_FILE_SIZE ="+ MAX_FAT_FILE_SIZE );
665         str.append("\nCLUSTER_SIZE ="+ CLUSTER_SIZE );
666         str.append("\nMAX_FILES_IN_FAT ="+ MAX_FILES_IN_FAT);
667         str.append("\nBYTES_TO_INDEX_CLUSTER ="+ BYTES_TO_INDEX_CLUSTER);
668         str.append("\nFILE_TABLE_SIZE ="+ FILE_TABLE_SIZE );
669         str.append("\nFAT_METADATA_SIZE ="+ FAT_METADATA_SIZE);
670         str.append("\nMAX_NUMBER_OF_CLUSTERS ="+ MAX_NUMBER_OF_CLUSTERS );
671         str.append("\n fileInFatCount ="+fileInFatCount);
672         str.append("\n freeClustersCount ="+freeClustersCount);
673         str.append("\n assignedClusterCount ="+assignedClusterCount);
674         str.append("\n currentFileSize ="+currentFileSize);
675         
676         return str.toString();
677     }
678     
679     
680     
681     /**
682      * @return Returns the fatFilePath.
683      */

684     public String JavaDoc getFatFilePath() {
685         return fatFilePath;
686     }
687
688     /**
689      * @throws IOException
690      *
691      */

692     public synchronized void close() throws IOException JavaDoc {
693         lock.release();
694         randomAccessFile.getChannel().force(true);
695         randomAccessFile.getChannel().close();
696         fatBuff = null;
697         randomAccessFile.close();
698         
699     }
700
701     protected int getAssignedClusterCount() {
702         return assignedClusterCount;
703     }
704     protected int getCurrentFileSize() {
705         return currentFileSize;
706     }
707     protected int getFileInFatCount() {
708         return fileInFatCount;
709     }
710     protected int getFreeClustersCount() {
711         return freeClustersCount;
712     }
713 }
714
Popular Tags