LargeByteBuffer.java

Go to the documentation of this file.
00001 package edu.rice.cs.hpc.data.util;
00002 
00003 import java.io.IOException;
00004 import java.nio.MappedByteBuffer;
00005 import java.nio.channels.FileChannel;
00006 
00014 public class LargeByteBuffer
00015 {
00016     
00018     private MappedByteBuffer[] masterBuffer;
00019     
00020     private long length;
00021     
00022     final private FileChannel fcInput;
00023     
00024     // The page size has to be the multiple of record size (24) and header size (can be 24 or 32)
00025     // originally: Integer.MAX_VALUE;
00026     private long pageSize; 
00027     
00028     /***
00029      * Construct direct/indirect mapped byte buffer
00030      * 
00031      * @param in : file channel
00032      * @param headerSz : the size of the header file
00033      * 
00034      * @throws IOException
00035      */
00036     public LargeByteBuffer(FileChannel in, int headerSz, int recordSz)
00037         throws IOException
00038     {
00039         fcInput = in;
00040         length = in.size();
00041         
00042         // --------------------------------------------------------------------
00043         // compute the page size:
00044         // the page size has to be multiple of the least common multiple of 
00045         //  the header size and the record size
00046         // --------------------------------------------------------------------
00047         pageSize = lcm (headerSz, recordSz) * (1 << 20);
00048         
00049         int numPages = 1+(int) (in.size() / pageSize);
00050         masterBuffer = new MappedByteBuffer[numPages];      
00051     }
00052     
00053     private long getCurrentSize(long index) throws IOException 
00054     {
00055         long currentSize = pageSize;
00056         if (length/pageSize == index) {
00057             currentSize = length - (index * pageSize);
00058         }
00059         return currentSize;
00060     }
00061     
00062     /****
00063      * Set a buffer map to a specified page
00064      *  
00065      * @param page
00066      * @return
00067      * @throws IOException
00068      */
00069     private MappedByteBuffer setBuffer(int page) throws IOException
00070     {
00071         long start = page * pageSize;
00072         MappedByteBuffer buffer = fcInput.map(FileChannel.MapMode.READ_ONLY, start, 
00073                 getCurrentSize(page));
00074         masterBuffer[page] = buffer;
00075         
00076         return buffer;
00077     }
00078     
00079     private MappedByteBuffer getBuffer(int page) throws IOException
00080     {
00081         MappedByteBuffer buffer = masterBuffer[page];
00082         if (buffer == null) {
00083             buffer = setBuffer(page);
00084         }
00085         return buffer;
00086     }
00087     
00088     public byte get(long position) throws IOException
00089     {
00090         int page = (int) (position / pageSize);
00091         int loc = (int) (position % pageSize);
00092         
00093         return getBuffer(page).get(loc);
00094     }
00095     
00096     public int getInt(long position) throws IOException
00097     {
00098         int page = (int) (position / pageSize);
00099         int loc = (int) (position % pageSize);
00100         return getBuffer(page).getInt(loc);
00101     }
00102     
00103     public long getLong(long position) throws IOException
00104     {
00105         int page = (int) (position / pageSize);
00106         int loc = (int) (position % pageSize);
00107         if (loc < pageSize - 4) {
00108             return getBuffer(page).getLong(loc);
00109         } else {
00110             return (((long) getBuffer(page).getInt(loc)) << 32) + getBuffer(page+1).getInt(0);
00111         }
00112     }
00113     
00114     public double getDouble(long position) throws IOException
00115     {
00116         int page = (int) (position / pageSize);
00117         int loc = (int) (position % pageSize);
00118         if (loc < pageSize - 4) {
00119             return getBuffer(page).getDouble(loc);
00120         } else {
00121             return (double)(((long) getBuffer(page).getInt(loc)) << 32) + (long) getBuffer(page+1).getInt(0);
00122         }
00123     }
00124     
00125     public char getChar(long position) throws IOException
00126     {
00127         int page = (int) (position / pageSize);
00128         int loc = (int) (position % pageSize);
00129         return getBuffer(page).getChar(loc);
00130     }
00131 
00132     public String getString(long position, long length) throws IOException
00133     {
00134         String str = "";
00135         for (long i = 0; i < length; ++i) {
00136             char c = (char)get(position + i);
00137             str += c;
00138         }
00139         return str;
00140     }
00141 
00142     public float getFloat(long position) throws IOException
00143     {
00144         int page = (int) (position / pageSize);
00145         int loc = (int) (position % pageSize);
00146         return getBuffer(page).getFloat(loc);
00147     }
00148     
00149     public short getShort(long position) throws IOException
00150     {
00151         int page = (int) (position / pageSize);
00152         int loc = (int) (position % pageSize);
00153         return getBuffer(page).getShort(loc);
00154     }
00155     
00156     public long size()
00157     {
00158         return length;
00159     }
00160     
00161     /***
00162      * Disposing resources manually to avoid memory leak
00163      */
00164     public void dispose() 
00165     {
00166         masterBuffer = null;
00167         try {
00168             fcInput.close();
00169         } catch (IOException e) {
00170             // TODO Auto-generated catch block
00171             e.printStackTrace();
00172         }
00173     }
00174     
00175     /***
00176      * compute the gcd of two numbers
00177      * 
00178      * @param a
00179      * @param b
00180      * @return
00181      */
00182     private static long gcd(long a, long b)
00183     {
00184         while (b > 0)
00185         {
00186             long temp = b;
00187             b = a % b; 
00188             a = temp;
00189         }
00190         return a;
00191     }
00192     
00193     /****
00194      * compute the lcm of two numbers
00195      * 
00196      * @param a
00197      * @param b
00198      * @return
00199      */
00200     private static long lcm(long a, long b)
00201     {
00202         return a * (b / gcd(a, b));
00203     }
00204 }

Generated on 5 May 2015 for HPCVIEWER by  doxygen 1.6.1