KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > caucho > db > store > Block


1 /*
2  * Copyright (c) 1998-2006 Caucho Technology -- all rights reserved
3  *
4  * This file is part of Resin(R) Open Source
5  *
6  * Each copy or derived work must preserve the copyright notice and this
7  * notice unmodified.
8  *
9  * Resin Open Source is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  *
14  * Resin Open Source is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, or any warranty
17  * of NON-INFRINGEMENT. See the GNU General Public License for more
18  * details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with Resin Open Source; if not, write to the
22  *
23  * Free Software Foundation, Inc.
24  * 59 Temple Place, Suite 330
25  * Boston, MA 02111-1307 USA
26  *
27  * @author Scott Ferguson
28  */

29
30 package com.caucho.db.store;
31
32 import com.caucho.log.Log;
33 import com.caucho.util.FreeList;
34 import com.caucho.util.L10N;
35 import com.caucho.util.SyncCacheListener;
36
37 import java.io.IOException JavaDoc;
38 import java.util.logging.Level JavaDoc;
39 import java.util.logging.Logger JavaDoc;
40
41 /**
42  * Represents a versioned row
43  */

44 abstract public class Block implements SyncCacheListener {
45   private static final Logger JavaDoc log = Log.open(Block.class);
46   private static final L10N L = new L10N(Block.class);
47
48   protected static final FreeList<byte[]> _freeBuffers
49     = new FreeList<byte[]>(4);
50
51   private final Store _store;
52   private final long _blockId;
53
54   private final Lock _lock;
55
56   private int _useCount = 1;
57
58   private boolean _isFlushDirtyOnCommit;
59   private boolean _isValid;
60   
61   private int _dirtyMin = Store.BLOCK_SIZE;
62   private int _dirtyMax;
63
64   Block(Store store, long blockId)
65   {
66     store.validateBlockId(blockId);
67     
68     _store = store;
69     _blockId = blockId;
70     
71     _lock = new Lock("block:" + store.getName() + ":" + _blockId);
72     
73     _isFlushDirtyOnCommit = _store.isFlushDirtyBlocksOnCommit();
74
75     if (log.isLoggable(Level.FINER))
76       log.finer(this + " create");
77     
78     //System.out.println(this + " CREATE");
79
}
80
81   /**
82    * Returns true if the block should be flushed on a commit.
83    */

84   public boolean isFlushDirtyOnCommit()
85   {
86     return _isFlushDirtyOnCommit;
87   }
88
89   /**
90    * True if the block should be flushed on a commit.
91    */

92   public void setFlushDirtyOnCommit(boolean isFlush)
93   {
94     _isFlushDirtyOnCommit = isFlush;
95   }
96
97   /**
98    * Allocates the block for a query.
99    */

100   boolean allocate()
101   {
102     synchronized (this) {
103       if (getBuffer() == null)
104     return false;
105       
106       _useCount++;
107       
108       if (log.isLoggable(Level.FINEST))
109     log.finest(this + " allocate");
110       
111       //System.out.println(this + " ALLOCATE " + _useCount);
112

113       if (_useCount > 32 && log.isLoggable(Level.FINE)) {
114     Thread.dumpStack();
115     log.fine("using " + this + " " + _useCount + " times");
116       }
117     }
118
119     return true;
120   }
121
122   /**
123    * Returns the block's table.
124    */

125   Store getStore()
126   {
127     return _store;
128   }
129
130   /**
131    * Returns the block's id.
132    */

133   public long getBlockId()
134   {
135     return _blockId;
136   }
137
138   public Lock getLock()
139   {
140     return _lock;
141   }
142   
143   /**
144    * Returns the block's buffer.
145    */

146   abstract public byte []getBuffer();
147
148   /**
149    * Reads into the block.
150    */

151   public void read()
152     throws IOException JavaDoc
153   {
154     synchronized (this) {
155       if (! _isValid) {
156     if (log.isLoggable(Level.FINER))
157       log.finer("read db-block " + this);
158       
159     _store.readBlock(_blockId & Store.BLOCK_MASK,
160              getBuffer(), 0, Store.BLOCK_SIZE);
161     _isValid = true;
162
163     _dirtyMin = Store.BLOCK_SIZE;
164     _dirtyMax = 0;
165       }
166     }
167   }
168
169   /**
170    * Handle any database writes necessary at commit time. If
171    * isFlushDirtyOnCommit() is true, this will write the data to
172    * the backing file.
173    */

174   public void commit()
175     throws IOException JavaDoc
176   {
177     if (! _isFlushDirtyOnCommit)
178       return;
179     else
180       write();
181   }
182
183   /**
184    * Forces a write of the data (should be private?)
185    */

186   public void write()
187     throws IOException JavaDoc
188   {
189     synchronized (this) {
190       int dirtyMin = _dirtyMin;
191       _dirtyMin = Store.BLOCK_SIZE;
192
193       int dirtyMax = _dirtyMax;
194       _dirtyMax = 0;
195
196       if (dirtyMin < dirtyMax) {
197     if (log.isLoggable(Level.FINER))
198       log.finer("write db-block " + this + " [" + dirtyMin + ", " + dirtyMax + "]");
199
200     //System.out.println(this + " WRITE_BEGIN");
201
writeImpl(dirtyMin, dirtyMax - dirtyMin);
202     //System.out.println(this + " WRITE_END");
203
}
204       else {
205     if (log.isLoggable(Level.FINER))
206       log.finer("not-dirty db-block " + this);
207       }
208       
209       _isValid = true;
210     }
211   }
212
213   /**
214    * Write the dirty block.
215    */

216   protected void writeImpl(int offset, int length)
217     throws IOException JavaDoc
218   {
219     _store.writeBlock((_blockId & Store.BLOCK_MASK) + offset,
220               getBuffer(), offset, length);
221   }
222
223   /**
224    * Marks the block's data as invalid.
225    */

226   public void invalidate()
227   {
228     if (_dirtyMin < _dirtyMax)
229       throw new IllegalStateException JavaDoc();
230     
231     _isValid = false;
232     _dirtyMin = Store.BLOCK_SIZE;
233     _dirtyMax = 0;
234   }
235
236   /**
237    * Marks the data as valid.
238    */

239   void validate()
240   {
241     _isValid = true;
242   }
243
244   /**
245    * Marks the block's data as dirty
246    */

247   public void setDirty(int min, int max)
248   {
249     if (Store.BLOCK_SIZE < max)
250       Thread.dumpStack();
251     
252     _isValid = true;
253
254     if (min < _dirtyMin)
255       _dirtyMin = min;
256     
257     if (_dirtyMax < max)
258       _dirtyMax = max;
259   }
260
261   /**
262    * Returns true if the block needs writing
263    */

264   public boolean isDirty()
265   {
266     return _dirtyMin < _dirtyMax;
267   }
268
269   /**
270    * Return true if this is a free block.
271    */

272   public boolean isFree()
273   {
274     return _useCount == 0;
275   }
276
277   /**
278    * Frees a block from a query.
279    */

280   public final void free()
281   {
282     synchronized (this) {
283       if (log.isLoggable(Level.FINEST))
284     log.finest(this + " free");
285
286       _useCount--;
287       
288       //System.out.println(this + " FREE " + _useCount);
289

290       if (_useCount > 0)
291     return;
292       
293       // If the block is clean, just discard it
294
if (_dirtyMax <= _dirtyMin) {
295     freeImpl();
296
297     return;
298       }
299     }
300
301     // dirty blocks get queued for writing
302
BlockManager.getBlockManager().addLruDirtyWriteBlock(this);
303   }
304
305   /**
306    * Called when the block is removed from the cache.
307    */

308   public final void syncRemoveEvent()
309   {
310     free();
311   }
312   
313   /**
314    * Called when the block is removed from the cache.
315    */

316   // called only from BlockManagerWriter.run()
317
void close()
318   {
319     synchronized (this) {
320       if (_dirtyMin < _dirtyMax) {
321     try {
322       write();
323     } catch (Throwable JavaDoc e) {
324       log.log(Level.FINER, e.toString(), e);
325     }
326       }
327
328       if (_useCount <= 0)
329     freeImpl();
330
331       if (log.isLoggable(Level.FINER))
332     log.finer("db-block remove " + this);
333     }
334   }
335
336   /**
337    * Frees any resources.
338    */

339   protected void freeImpl()
340   {
341   }
342
343   public String JavaDoc toString()
344   {
345     return "Block[" + _store + "," + _blockId / Store.BLOCK_SIZE + "]";
346   }
347 }
348
Popular Tags