KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > db4o > util > io > NIOFileAdapter


1 /* Copyright (C) 2004 - 2006 db4objects Inc. http://www.db4o.com
2
3 This file is part of the db4o open source object database.
4
5 db4o is free software; you can redistribute it and/or modify it under
6 the terms of version 2 of the GNU General Public License as published
7 by the Free Software Foundation and as clarified by db4objects' GPL
8 interpretation policy, available at
9 http://www.db4o.com/about/company/legalpolicies/gplinterpretation/
10 Alternatively you can write to db4objects, Inc., 1900 S Norfolk Street,
11 Suite 350, San Mateo, CA 94403, USA.
12
13 db4o is distributed in the hope that it will be useful, but WITHOUT ANY
14 WARRANTY; without even the implied warranty of MERCHANTABILITY or
15 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
16 for more details.
17
18 You should have received a copy of the GNU General Public License along
19 with this program; if not, write to the Free Software Foundation, Inc.,
20 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */

21 package com.db4o.util.io;
22
23 import java.io.*;
24 import java.lang.reflect.*;
25 import java.nio.*;
26 import java.nio.channels.*;
27 import java.util.*;
28
29 import com.db4o.io.*;
30
31 import sun.nio.ch.*;
32
33 public class NIOFileAdapter extends IoAdapter {
34     private int hits=0;
35     private int misses=0;
36     
37     private int _pageSize;
38     private FileChannel _channel;
39     private MappedByteBuffer _page;
40     private int _pageId;
41     private long _position;
42     private long _size;
43     private boolean _dirty;
44     private Map _id2Page;
45     private LinkedList _lruPages;
46     private int _lruLimit;
47     private RandomAccessFile _file;
48     
49     public NIOFileAdapter(int pageSize,int lruLimit) {
50         _pageSize=pageSize;
51         _lruLimit=lruLimit;
52     }
53
54     private NIOFileAdapter(String JavaDoc filename,boolean lockFile,long initialLength,int pageSize,int lruLimit) throws IOException {
55         _pageSize=pageSize;
56         _file=new RandomAccessFile(filename, "rw");
57         _channel=_file.getChannel();
58         _size=_channel.size();
59         _page=null;
60         _pageId=0;
61         _position=0;
62         _dirty=false;
63         _id2Page=new HashMap();
64         _lruPages=new LinkedList();
65         _lruLimit=lruLimit;
66     }
67
68     public void seek(long position) throws IOException {
69         _position=position;
70     }
71
72     public void close() throws IOException {
73         for (Iterator pageiter = _id2Page.values().iterator(); pageiter.hasNext();) {
74             MappedByteBuffer curpage = (MappedByteBuffer) pageiter.next();
75             closePage(curpage);
76         }
77         _id2Page.clear();
78         _lruPages.clear();
79         _page=null;
80         _channel.close();
81         _file.close();
82         //System.err.println("Hits: "+hits+", Misses: "+misses);
83
}
84
85     public void delete(String JavaDoc path) {
86         new File(path).delete();
87     }
88     
89     public boolean exists(String JavaDoc path){
90         File existingFile = new File(path);
91         return existingFile.exists() && existingFile.length() > 0;
92     }
93
94     public long getLength() throws IOException {
95         return _size;
96     }
97
98     public int read(byte[] bytes, int length) throws IOException {
99         if(length<=0) {
100             return 0;
101         }
102         int alreadyRead=0;
103         int stillToRead=length;
104         while(stillToRead>0) {
105             forcePage();
106             try {
107                 _page.position(pageOffset(_position));
108             }
109             catch(IllegalArgumentException JavaDoc exc) {
110                 return -1;
111             }
112             int hereToRead=(int)min(_page.limit()-_page.position(),stillToRead);
113             if(hereToRead==0) {
114                 break;
115             }
116             _page.get(bytes,alreadyRead,hereToRead);
117             stillToRead-=hereToRead;
118             alreadyRead+=hereToRead;
119             _position+=hereToRead;
120         }
121         return (alreadyRead>0 ? alreadyRead : -1);
122     }
123
124     public void write(byte[] bytes, int length) throws IOException {
125         if(length<=0) {
126             return;
127         }
128         if(_position+length>_size) {
129             _size=_position+length;
130         }
131         int alreadyWritten=0;
132         int stillToWrite=length;
133         while(stillToWrite>0) {
134             forcePage();
135             int pageOffset=pageOffset(_position);
136             _page.limit((int)min(_pageSize,pageOffset+length));
137             _page.position(pageOffset);
138             int hereToWrite=(int)min(_page.capacity()-_page.position(),stillToWrite);
139             _page.put(bytes,alreadyWritten,hereToWrite);
140             stillToWrite-=hereToWrite;
141             alreadyWritten+=hereToWrite;
142             _position+=hereToWrite;
143             _dirty=true;
144         }
145     }
146
147     public void sync() throws IOException {
148         // FIXME internalSync(_page);
149
}
150
151     private void internalSync(MappedByteBuffer page) {
152         if(_dirty&&page!=null) {
153             page.flip();
154             page.force();
155         }
156     }
157
158     public void unlock() {
159     }
160
161     public void lock() {
162     }
163
164     private MappedByteBuffer page(int pageId) throws IOException {
165         MappedByteBuffer page=_channel.map(FileChannel.MapMode.READ_WRITE,pagePosition(pageId),_pageSize);
166         page.limit(pageSize(pageId));
167         return page;
168     }
169     
170     private long pagePosition(int pageId) {
171         return (long)pageId*_pageSize;
172     }
173
174     private int pageSize(int pageId) throws IOException {
175         long sizeLeft=_size-pagePosition(pageId);
176         return (sizeLeft>_pageSize ? _pageSize : (int)sizeLeft);
177     }
178
179     private void forcePage() throws IOException {
180         int pageId=pageId(_position);
181         int pageOffset=pageOffset(_position);
182         Integer JavaDoc pageIdKey=new Integer JavaDoc(pageId);
183         if(_id2Page.containsKey(pageIdKey)) {
184             _lruPages.remove(pageIdKey);
185             _lruPages.addFirst(pageIdKey);
186             _page=(MappedByteBuffer)_id2Page.get(pageIdKey);
187             _page.limit(pageSize(pageId));
188             hits++;
189             return;
190         }
191         closePage();
192         loadPage(pageId,pageOffset);
193         if (_lruPages.size()==_lruLimit) {
194             Integer JavaDoc dropPageKey=(Integer JavaDoc)_lruPages.removeLast();
195             MappedByteBuffer page=(MappedByteBuffer)_id2Page.remove(dropPageKey);
196             try {
197                 Method unmap=FileChannelImpl.class.getDeclaredMethod("unmap",new Class JavaDoc[]{MappedByteBuffer.class});
198                 unmap.setAccessible(true);
199                 unmap.invoke(null,new Object JavaDoc[]{page});
200             } catch (Exception JavaDoc exc) {
201                 exc.printStackTrace();
202             }
203         }
204         Integer JavaDoc addedPageKey=new Integer JavaDoc(_pageId);
205         _id2Page.put(addedPageKey,_page);
206         _lruPages.addFirst(addedPageKey);
207         _dirty=false;
208         misses++;
209     }
210     
211     private void closePage() throws IOException {
212         closePage(_page);
213         _page=null;
214     }
215
216     private void closePage(MappedByteBuffer page) throws IOException {
217         if(page!=null) {
218             internalSync(page);
219         }
220     }
221
222     private void loadPage(int pageId,int pageOffset) throws IOException {
223         _page=page(pageId);
224         _pageId=pageId;
225         _dirty=false;
226     }
227
228     private int pageId(long position) {
229         return (int)(position/_pageSize);
230     }
231
232     private int pageOffset(long position) {
233         return (int)(position%_pageSize);
234     }
235
236     private long min(long a,long b) {
237         return (a>b ? b : a);
238     }
239
240     private long max(long a,long b) {
241         return (a<b ? b : a);
242     }
243
244     public IoAdapter open(String JavaDoc path, boolean lockFile, long initialLength) throws IOException {
245         return new NIOFileAdapter(path,lockFile,initialLength,_pageSize,_lruLimit);
246     }
247 }
248
Popular Tags