KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > caucho > db > table > Table


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.table;
31
32 import com.caucho.db.Database;
33 import com.caucho.db.index.BTree;
34 import com.caucho.db.index.KeyCompare;
35 import com.caucho.db.sql.CreateQuery;
36 import com.caucho.db.sql.Expr;
37 import com.caucho.db.sql.Parser;
38 import com.caucho.db.sql.QueryContext;
39 import com.caucho.db.store.Block;
40 import com.caucho.db.store.Lock;
41 import com.caucho.db.store.Store;
42 import com.caucho.db.store.Transaction;
43 import com.caucho.log.Log;
44 import com.caucho.sql.SQLExceptionWrapper;
45 import com.caucho.util.L10N;
46 import com.caucho.vfs.Path;
47 import com.caucho.vfs.ReadStream;
48 import com.caucho.vfs.TempBuffer;
49 import com.caucho.vfs.TempStream;
50 import com.caucho.vfs.WriteStream;
51
52 import java.io.IOException JavaDoc;
53 import java.sql.SQLException JavaDoc;
54 import java.util.ArrayList JavaDoc;
55 import java.util.logging.Level JavaDoc;
56 import java.util.logging.Logger JavaDoc;
57
58 /**
59  * Table format:
60  *
61  * <pre>
62  * Block 0: allocation table
63  * Block 1: fragment table
64  * Block 2: table definition
65  * 0 - store data
66  * 1024 - table data
67  * 1024 - index pointers
68  * 2048 - CREATE text
69  * Block 3: first data
70  * </pre>
71  */

72 public class Table extends Store {
73   private final static Logger JavaDoc log = Log.open(Table.class);
74   private final static L10N L = new L10N(Table.class);
75
76   private final static int ROOT_DATA_OFFSET = STORE_CREATE_END;
77   private final static int INDEX_ROOT_OFFSET = ROOT_DATA_OFFSET + 32;
78   
79   private final static int ROOT_DATA_END = ROOT_DATA_OFFSET + 1024;
80   
81   public final static int INLINE_BLOB_SIZE = 120;
82   
83   public final static long ROW_CLOCK_MIN = 1024;
84
85   public final static byte ROW_VALID = 0x1;
86   public final static byte ROW_ALLOC = 0x2;
87   public final static byte ROW_MASK = 0x3;
88
89   private final static String JavaDoc DB_VERSION = "Resin-DB 3.1.0";
90   private final static String JavaDoc MIN_VERSION = "Resin-DB 3.1.0";
91   
92   private final Row _row;
93
94   private final int _rowLength;
95   private final int _rowsPerBlock;
96   private final int _rowEnd;
97
98   private final Constraint[]_constraints;
99   
100   private final Column _autoIncrementColumn;
101
102   private long _entries;
103
104   private final Object JavaDoc _rowClockLock = new Object JavaDoc();
105   private long _rowClockAddr;
106   private long _rowClockTotal;
107   private long _rowClockUsed;
108   private int _rowClockCount;
109   private int _rowAllocCount;
110
111   private long _autoIncrementValue = -1;
112
113   private Lock _allocLock;
114   private Lock _insertLock;
115
116   Table(Database database, String JavaDoc name, Row row, Constraint constraints[])
117   {
118     super(database, name, null);
119     
120     _row = row;
121     _constraints = constraints;
122
123     _rowLength = _row.getLength();
124     _rowsPerBlock = BLOCK_SIZE / _rowLength;
125     _rowEnd = _rowLength * _rowsPerBlock;
126
127     _rowClockAddr = 0;
128     
129     Column []columns = _row.getColumns();
130     Column autoIncrementColumn = null;
131     for (int i = 0; i < columns.length; i++) {
132       columns[i].setTable(this);
133       
134       if (columns[i].getAutoIncrement() >= 0)
135     autoIncrementColumn = columns[i];
136     }
137     _autoIncrementColumn = autoIncrementColumn;
138
139     _insertLock = new Lock("table-insert:" + name);
140     _allocLock = new Lock("table-alloc:" + name);
141   }
142
143   Row getRow()
144   {
145     return _row;
146   }
147
148   /**
149    * Returns the length of a row.
150    */

151   int getRowLength()
152   {
153     return _rowLength;
154   }
155
156   /**
157    * Returns the end of the row
158    */

159   int getRowEnd()
160   {
161     return _rowEnd;
162   }
163   
164   public final Column []getColumns()
165   {
166     return _row.getColumns();
167   }
168
169   /**
170    * Returns the table's constraints.
171    */

172   public final Constraint []getConstraints()
173   {
174     return _constraints;
175   }
176
177   /**
178    * Returns the auto-increment column.
179    */

180   public Column getAutoIncrementColumn()
181   {
182     return _autoIncrementColumn;
183   }
184
185   /**
186    * Returns the column for the given column name.
187    *
188    * @param name the column name
189    *
190    * @return the column
191    */

192   public Column getColumn(String JavaDoc name)
193   {
194     Column []columns = getColumns();
195
196     for (int i = 0; i < columns.length; i++) {
197       if (columns[i].getName().equals(name))
198     return columns[i];
199     }
200
201     return null;
202   }
203
204   /**
205    * Returns the column index for the given column name.
206    *
207    * @param name the column name
208    *
209    * @return the column index.
210    */

211   public int getColumnIndex(String JavaDoc name)
212     throws SQLException JavaDoc
213   {
214     Column []columns = getColumns();
215
216     for (int i = 0; i < columns.length; i++) {
217       if (columns[i].getName().equals(name))
218     return i;
219     }
220
221     return -1;
222   }
223
224   /**
225    * Loads the table from the file.
226    */

227   public static Table loadFromFile(Database db, String JavaDoc name)
228     throws IOException JavaDoc, SQLException JavaDoc
229   {
230     Path path = db.getPath().lookup(name + ".db");
231
232     if (! path.exists())
233       throw new IOException JavaDoc(L.l("table {0} does not exist", name));
234
235     String JavaDoc version = null;
236
237     ReadStream is = path.openRead();
238     try {
239       // skip allocation table and fragment table
240
is.skip(DATA_START + ROOT_DATA_OFFSET);
241
242       StringBuilder JavaDoc sb = new StringBuilder JavaDoc();
243       int ch;
244
245       while ((ch = is.read()) > 0) {
246     sb.append((char) ch);
247       }
248
249       version = sb.toString();
250
251       if (! version.startsWith("Resin-DB")) {
252     throw new SQLException JavaDoc(L.l("table {0} is not a Resin DB. Version '{1}'",
253                    name, version));
254       }
255       else if (version.compareTo(MIN_VERSION) < 0 ||
256            DB_VERSION.compareTo(version) < 0) {
257     throw new SQLException JavaDoc(L.l("table {0} is out of date. Old version {1}.",
258                    name, version));
259       }
260     } finally {
261       is.close();
262     }
263
264     is = path.openRead();
265     try {
266       // skip allocation table and fragment table
267
is.skip(DATA_START + ROOT_DATA_END);
268
269       StringBuilder JavaDoc cb = new StringBuilder JavaDoc();
270
271       int ch;
272       while ((ch = is.read()) > 0) {
273     cb.append((char) ch);
274       }
275
276       String JavaDoc sql = cb.toString();
277
278       if (log.isLoggable(Level.FINER))
279     log.finer("Table[" + name + "] " + version + " loading\n" + sql);
280
281       try {
282     CreateQuery query = (CreateQuery) Parser.parse(db, sql);
283
284     TableFactory factory = query.getFactory();
285
286     if (! factory.getName().equalsIgnoreCase(name))
287       throw new IOException JavaDoc(L.l("factory {0} does not match", name));
288     
289     Table table = new Table(db, factory.getName(), factory.getRow(),
290                 factory.getConstraints());
291
292     table.init();
293
294     table.clearIndexes();
295     table.initIndexes();
296     table.rebuildIndexes();
297       
298     return table;
299       } catch (Throwable JavaDoc e) {
300     log.log(Level.FINE, e.toString(), e);
301     
302     log.warning(e.toString());
303
304     throw new SQLException JavaDoc(L.l("can't load table {0} in {1}.\n{2}",
305                    name, path.getNativePath(), e.toString()));
306       }
307     } finally {
308       is.close();
309     }
310   }
311
312   /**
313    * Creates the table.
314    */

315   public void create()
316     throws IOException JavaDoc, SQLException JavaDoc
317   {
318     super.create();
319
320     initIndexes();
321
322     byte []tempBuffer = new byte[BLOCK_SIZE];
323
324     readBlock(BLOCK_SIZE, tempBuffer, 0, BLOCK_SIZE);
325
326     TempStream ts = new TempStream();
327       
328     WriteStream os = new WriteStream(ts);
329
330     try {
331       for (int i = 0; i < ROOT_DATA_OFFSET; i++)
332     os.write(tempBuffer[i]);
333       
334       writeTableHeader(os);
335     } finally {
336       os.close();
337     }
338
339     TempBuffer head = ts.getHead();
340     int offset = 0;
341     for (; head != null; head = head.getNext()) {
342       byte []buffer = head.getBuffer();
343       
344       int length = head.getLength();
345       
346       System.arraycopy(buffer, 0, tempBuffer, offset, length);
347
348       for (; length < buffer.length; length++) {
349     tempBuffer[offset + length] = 0;
350       }
351
352       offset += buffer.length;
353     }
354
355     for (; offset < BLOCK_SIZE; offset++)
356       tempBuffer[offset] = 0;
357
358     writeBlock(BLOCK_SIZE, tempBuffer, 0, BLOCK_SIZE);
359
360     _database.addTable(this);
361   }
362   
363   /**
364    * Initialize the indexes
365    */

366   private void initIndexes()
367     throws IOException JavaDoc, SQLException JavaDoc
368   {
369     Column []columns = _row.getColumns();
370     for (int i = 0; i < columns.length; i++) {
371       Column column = columns[i];
372
373       if (! column.isUnique())
374     continue;
375
376       KeyCompare keyCompare = column.getIndexKeyCompare();
377
378       if (keyCompare == null)
379     continue;
380
381       Block rootBlock = allocateIndexBlock();
382       long rootBlockId = rootBlock.getBlockId();
383       rootBlock.free();
384
385       BTree btree = new BTree(this, rootBlockId, column.getLength(),
386                   keyCompare);
387
388       column.setIndex(btree);
389     }
390   }
391   
392   /**
393    * Clears the indexes
394    */

395   private void clearIndexes()
396     throws IOException JavaDoc
397   {
398     Column []columns = _row.getColumns();
399
400     for (int i = 0; i < columns.length; i++) {
401       BTree index = columns[i].getIndex();
402
403       if (index == null)
404     continue;
405
406       long rootAddr = index.getIndexRoot();
407
408       Block block = readBlock(addressToBlockId(rootAddr));
409
410       try {
411     byte []blockBuffer = block.getBuffer();
412
413     synchronized (blockBuffer) {
414       for (int j = 0; j < blockBuffer.length; j++) {
415         blockBuffer[j] = 0;
416       }
417
418       block.setDirty(0, BLOCK_SIZE);
419     }
420       } finally {
421     block.free();
422       }
423     }
424
425     long blockAddr = 0;
426     
427     while ((blockAddr = firstBlock(blockAddr + BLOCK_SIZE, ALLOC_INDEX)) > 0) {
428       freeBlock(blockAddr);
429     }
430   }
431   
432   /**
433    * Rebuilds the indexes
434    */

435   private void rebuildIndexes()
436     throws IOException JavaDoc, SQLException JavaDoc
437   {
438     Transaction xa = Transaction.create();
439     xa.setAutoCommit(true);
440
441     try {
442       TableIterator iter = createTableIterator();
443
444       iter.init(xa);
445
446       Column []columns = _row.getColumns();
447     
448       while (iter.nextBlock()) {
449     iter.initRow();
450
451     byte []blockBuffer = iter.getBuffer();
452       
453     while (iter.nextRow()) {
454       long rowAddress = iter.getRowAddress();
455       int rowOffset = iter.getRowOffset();
456       
457       for (int i = 0; i < columns.length; i++) {
458         Column column = columns[i];
459
460         column.setIndex(xa, blockBuffer, rowOffset, rowAddress, null);
461       }
462     }
463       }
464     } finally {
465       xa.commit();
466     }
467   }
468
469   private void writeTableHeader(WriteStream os)
470     throws IOException JavaDoc
471   {
472     os.print(DB_VERSION);
473     os.write(0);
474
475     while (os.getBufferOffset() < INDEX_ROOT_OFFSET)
476       os.write(0);
477
478     Column []columns = _row.getColumns();
479     for (int i = 0; i < columns.length; i++) {
480       if (! columns[i].isUnique())
481     continue;
482
483       BTree index = columns[i].getIndex();
484
485       if (index != null) {
486     writeLong(os, index.getIndexRoot());
487       }
488       else {
489     writeLong(os, 0);
490       }
491     }
492
493     while (os.getBufferOffset() < ROOT_DATA_END)
494       os.write(0);
495
496     os.print("CREATE TABLE " + getName() + "(");
497     for (int i = 0; i < _row.getColumns().length; i++) {
498       Column column = _row.getColumns()[i];
499       
500       if (i != 0)
501     os.print(",");
502       
503       os.print(column.getName());
504       os.print(" ");
505
506       switch (column.getTypeCode()) {
507       case Column.VARCHAR:
508     os.print("VARCHAR(" + column.getDeclarationSize() + ")");
509     break;
510       case Column.INT:
511     os.print("INTEGER");
512     break;
513       case Column.LONG:
514     os.print("BIGINT");
515     break;
516       case Column.DOUBLE:
517     os.print("DOUBLE");
518     break;
519       case Column.DATE:
520     os.print("TIMESTAMP");
521     break;
522       case Column.BLOB:
523     os.print("BLOB");
524     break;
525       case Column.NUMERIC:
526     {
527       NumericColumn numeric = (NumericColumn) column;
528       
529       os.print("NUMERIC(" + numeric.getPrecision() + "," + numeric.getScale() + ")");
530       break;
531     }
532       default:
533     throw new UnsupportedOperationException JavaDoc();
534       }
535
536       if (column.isPrimaryKey())
537     os.print(" PRIMARY KEY");
538       else if (column.isUnique())
539     os.print(" UNIQUE");
540       
541       if (column.isNotNull())
542     os.print(" NOT NULL");
543
544       Expr defaultExpr = column.getDefault();
545       
546       if (defaultExpr != null) {
547     os.print(" DEFAULT (");
548     os.print(defaultExpr);
549     os.print(")");
550       }
551
552       if (column.getAutoIncrement() >= 0)
553     os.print(" auto_increment");
554     }
555     os.print(")");
556
557     /*
558     writeLong(os, _blockMax);
559     writeLong(os, _entries);
560     writeLong(os, _clockAddr);
561     */

562   }
563
564   public TableIterator createTableIterator()
565   {
566     assertStoreActive();
567     
568     return new TableIterator(this);
569   }
570
571   /**
572    * Returns the next auto-increment value.
573    */

574   public long nextAutoIncrement(QueryContext context)
575     throws SQLException JavaDoc
576   {
577     synchronized (this) {
578       if (_autoIncrementValue >= 0)
579     return ++_autoIncrementValue;
580     }
581
582     long max = 0;
583     
584     try {
585       TableIterator iter = createTableIterator();
586       iter.init(context);
587       while (iter.next()) {
588     byte []buffer = iter.getBuffer();
589       
590     long value = _autoIncrementColumn.getLong(buffer, iter.getRowOffset());
591
592     if (max < value)
593       max = value;
594       }
595     } catch (IOException JavaDoc e) {
596       throw new SQLExceptionWrapper(e);
597     }
598
599     synchronized (this) {
600       if (_autoIncrementValue < max)
601     _autoIncrementValue = max;
602
603       return ++_autoIncrementValue;
604     }
605   }
606
607   /**
608    * Inserts a new row, returning the row address.
609    */

610   public long insert(QueryContext queryContext, Transaction xa,
611              ArrayList JavaDoc<Column> columns,
612              ArrayList JavaDoc<Expr> values)
613     throws IOException JavaDoc, SQLException JavaDoc
614   {
615     if (log.isLoggable(Level.FINE))
616       log.fine("db table " + getName() + " insert row xa:" + xa);
617     
618     Block block = null;
619     
620     try {
621       long addr;
622       int rowOffset = 0;
623       
624       boolean isLoop = false;
625       boolean hasRow = false;
626
627       int rowClockCount = 0;
628       long rowClockAddr = 0;
629       long rowClockUsed = 0;
630       long rowClockTotal = 0;
631       
632       do {
633     long blockId = 0;
634
635     if (block != null) {
636       block.free();
637       block = null;
638     }
639
640     synchronized (_rowClockLock) {
641       blockId = firstRow(_rowClockAddr);
642
643       if (blockId >= 0) {
644       }
645       else if (! isLoop
646            && (ROW_CLOCK_MIN < _rowClockTotal
647                && 4 * _rowClockUsed < 3 * _rowClockTotal
648                || _rowAllocCount > 8)) {
649         //System.out.println("LOOP: used:" + _rowClockUsed + " total:" + _rowClockTotal + " frac:" + (double) _rowClockUsed / (double) (_rowClockTotal + 0.01));
650
// go around loop if there are sufficient entries, i.e. over
651
// ROW_CLOCK_MIN and at least 1/4 free entries.
652
isLoop = true;
653         _rowClockCount = 0;
654         _rowClockAddr = 0;
655         _rowClockUsed = 0;
656         _rowClockTotal = 0;
657         _rowAllocCount = 0;
658         continue;
659       }
660       else {
661         //System.out.println("ROW: used:" + _rowClockUsed + " total:" + _rowClockTotal + " frac:" + (double) _rowClockUsed / (double) (_rowClockTotal + 0.01));
662

663         _rowAllocCount++;
664         
665         // if no free row is available, allocate a new one
666
block = xa.allocateRow(this);
667         //System.out.println("ALLOC: " + block);
668

669         blockId = block.getBlockId();
670       }
671
672       rowClockCount = _rowClockCount;
673       rowClockAddr = blockIdToAddress(blockId);
674       rowClockUsed = _rowClockUsed;
675       rowClockTotal = _rowClockTotal;
676
677       // the next insert will try the following block
678
_rowClockCount++;
679       _rowClockAddr = rowClockAddr + BLOCK_SIZE;
680       _rowClockUsed = rowClockUsed + _rowsPerBlock;
681       _rowClockTotal = rowClockTotal + _rowsPerBlock;
682     }
683
684     if (block == null)
685       block = xa.readBlock(this, blockId);
686     
687     xa.lockWrite(block.getLock());
688     try {
689       rowOffset = 0;
690
691       byte []buffer = block.getBuffer();
692         
693       for (; rowOffset < _rowEnd; rowOffset += _rowLength) {
694         if (buffer[rowOffset] == 0) {
695           block.setDirty(rowOffset, rowOffset + 1);
696                  
697           hasRow = true;
698           buffer[rowOffset] = ROW_ALLOC;
699           break;
700         }
701       }
702     } finally {
703       xa.unlockReadAndWrite(block.getLock());
704     }
705       } while (! hasRow);
706
707       insertRow(queryContext, xa, columns, values,
708         block, rowOffset);
709
710       synchronized (_rowClockLock) {
711     if (rowClockCount < _rowClockCount) {
712       // the next insert will retry this block
713
int blocks = _rowClockCount - rowClockCount;
714
715       _rowClockCount = rowClockCount;
716       _rowClockAddr = rowClockAddr;
717       _rowClockUsed -= blocks * _rowsPerBlock;
718       _rowClockTotal -= blocks * _rowsPerBlock;
719     }
720       }
721
722       return blockIdToAddress(block.getBlockId(), rowOffset);
723     } finally {
724       if (block != null)
725     block.free();
726     }
727   }
728
729   public void insertRow(QueryContext queryContext, Transaction xa,
730             ArrayList JavaDoc<Column> columns,
731             ArrayList JavaDoc<Expr> values,
732             Block block, int rowOffset)
733     throws SQLException JavaDoc
734   {
735     byte []buffer = block.getBuffer();
736
737     long rowAddr = blockIdToAddress(block.getBlockId(), rowOffset);
738     //System.out.println("ADDR:" + rowAddr + " " + rowOffset + " " + block);
739

740     TableIterator iter = createTableIterator();
741     TableIterator []iterSet = new TableIterator[] { iter };
742     // QueryContext context = QueryContext.allocate();
743
queryContext.init(xa, iterSet, true);
744     iter.init(queryContext);
745
746     boolean isOkay = false;
747     queryContext.lock();
748     try {
749       iter.setRow(block, rowOffset);
750
751       block.setDirty(rowOffset, rowOffset + _rowLength);
752       
753       for (int i = rowOffset + _rowLength - 1; rowOffset < i; i--)
754     buffer[i] = 0;
755
756       for (int i = 0; i < columns.size(); i++) {
757     Column column = columns.get(i);
758     Expr value = values.get(i);
759
760     column.setExpr(xa, buffer, rowOffset, value, queryContext);
761       }
762
763       // lock for insert, i.e. entries, indices, and validation
764
// XXX: the set index needs to handle the validation
765
//xa.lockWrite(_insertLock);
766
try {
767     validate(block, rowOffset, queryContext, xa);
768       
769     buffer[rowOffset] = (byte) ((buffer[rowOffset] & ~ROW_MASK) | ROW_VALID);
770
771     for (int i = 0; i < columns.size(); i++) {
772       Column column = columns.get(i);
773       Expr value = values.get(i);
774
775       column.setIndex(xa, buffer, rowOffset, rowAddr, queryContext);
776     }
777
778     xa.addUpdateBlock(block);
779
780     if (_autoIncrementColumn != null) {
781       long value = _autoIncrementColumn.getLong(buffer, rowOffset);
782
783       synchronized (this) {
784         if (_autoIncrementValue < value)
785           _autoIncrementValue = value;
786       }
787     }
788       
789     _entries++;
790       
791     isOkay = true;
792       } finally {
793     // xa.unlockWrite(_insertLock);
794

795     if (! isOkay)
796       delete(xa, block, buffer, rowOffset);
797       }
798     } finally {
799       queryContext.unlock();
800     }
801   }
802
803   /**
804    * Validates the given row.
805    */

806   private void validate(Block block, int rowOffset,
807             QueryContext queryContext, Transaction xa)
808     throws SQLException JavaDoc
809   {
810     TableIterator row = createTableIterator();
811     TableIterator []rows = new TableIterator[] { row };
812
813     row.setRow(block, rowOffset);
814
815     for (int i = 0; i < _constraints.length; i++) {
816       _constraints[i].validate(rows, queryContext, xa);
817     }
818   }
819   
820   void delete(Transaction xa, Block block, byte []buffer, int rowOffset)
821     throws SQLException JavaDoc
822   {
823     byte rowState = buffer[rowOffset];
824
825     if ((rowState & ROW_MASK) != ROW_VALID)
826       return;
827     
828     buffer[rowOffset] = (byte) ((rowState & ~ROW_MASK) | ROW_ALLOC);
829     
830     Column []columns = _row.getColumns();
831     
832     for (int i = 0; i < columns.length; i++) {
833       columns[i].delete(xa, buffer, rowOffset);
834     }
835
836     buffer[rowOffset] = 0;
837     
838     synchronized (_rowClockLock) {
839       long addr = blockIdToAddress(block.getBlockId());
840       
841       if (addr <= _rowClockAddr) {
842     _rowClockUsed--;
843       }
844     }
845   }
846
847   private void writeLong(WriteStream os, long value)
848     throws IOException JavaDoc
849   {
850     os.write((int) (value >> 56));
851     os.write((int) (value >> 48));
852     os.write((int) (value >> 40));
853     os.write((int) (value >> 32));
854     os.write((int) (value >> 24));
855     os.write((int) (value >> 16));
856     os.write((int) (value >> 8));
857     os.write((int) value);
858   }
859
860   private void setLong(byte []buffer, int offset, long value)
861     throws IOException JavaDoc
862   {
863     buffer[offset + 0] = (byte) (value >> 56);
864     buffer[offset + 1] = (byte) (value >> 48);
865     buffer[offset + 2] = (byte) (value >> 40);
866     buffer[offset + 3] = (byte) (value >> 32);
867     buffer[offset + 4] = (byte) (value >> 24);
868     buffer[offset + 5] = (byte) (value >> 16);
869     buffer[offset + 6] = (byte) (value >> 8);
870     buffer[offset + 7] = (byte) (value);
871   }
872
873   private long getLong(byte []buffer, int offset)
874     throws IOException JavaDoc
875   {
876     long value = (((buffer[offset + 0] & 0xffL) << 56) +
877           ((buffer[offset + 1] & 0xffL) << 48) +
878           ((buffer[offset + 2] & 0xffL) << 40) +
879           ((buffer[offset + 3] & 0xffL) << 32) +
880
881           ((buffer[offset + 4] & 0xffL) << 24) +
882           ((buffer[offset + 5] & 0xffL) << 16) +
883           ((buffer[offset + 6] & 0xffL) << 8) +
884           ((buffer[offset + 7] & 0xffL)));
885
886     return value;
887   }
888   
889   public String JavaDoc toString()
890   {
891     return "Table[" + getName() + ":" + getId() + "]";
892   }
893 }
894
Popular Tags