From: Bryan T. <tho...@us...> - 2007-02-22 16:59:40
|
Update of /cvsroot/cweb/bigdata/src/java/com/bigdata/journal In directory sc8-pr-cvs4.sourceforge.net:/tmp/cvs-serv16247/src/java/com/bigdata/journal Modified Files: TransientBufferStrategy.java Tx.java MappedBufferStrategy.java ITransactionManager.java BlockWriteCache.java IJournal.java DiskBackedBufferStrategy.java TemporaryRawStore.java Options.java DiskOnlyStrategy.java FileMetadata.java Journal.java Log Message: Lots of little changes to get the test suites to use temporary files and to remove them when tests complete. At present, this only helps if the test succeeds. You need to do a try {} finally {} to get the tests to remove their files on failure. Index: IJournal.java =================================================================== RCS file: /cvsroot/cweb/bigdata/src/java/com/bigdata/journal/IJournal.java,v retrieving revision 1.6 retrieving revision 1.7 diff -C2 -d -r1.6 -r1.7 *** IJournal.java 21 Feb 2007 20:17:21 -0000 1.6 --- IJournal.java 22 Feb 2007 16:59:34 -0000 1.7 *************** *** 50,54 **** import java.util.Properties; - import com.bigdata.objndx.BTree; import com.bigdata.objndx.IIndex; import com.bigdata.rawstore.IRawStore; --- 50,53 ---- *************** *** 95,97 **** --- 94,127 ---- public IIndex getIndex(String name); + /** + * Return the named index isolated by the transaction having the + * specified start time. + * + * @param startTime The transaction start time. + */ + public IIndex getIndex(String name, long startTime); + + /** + * Return a read-only view of the current root block. + * + * @return The current root block. + */ + public IRootBlockView getRootBlockView(); + + /** + * Return the {@link ICommitRecord} for the most recent committed state + * whose commit timestamp is less than or equal to <i>timestamp</i>. This + * is used by a {@link Tx transaction} to locate the committed state that is + * the basis for its operations. + * + * @param timestamp + * Typically, the timestamp assigned to a transaction. + * + * @return The {@link ICommitRecord} for the most recent committed state + * whose commit timestamp is less than or equal to <i>timestamp</i> + * -or- <code>null</code> iff there are no {@link ICommitRecord}s + * that satisify the probe. + */ + public ICommitRecord getCommitRecord(long commitTime); + } Index: DiskOnlyStrategy.java =================================================================== RCS file: /cvsroot/cweb/bigdata/src/java/com/bigdata/journal/DiskOnlyStrategy.java,v retrieving revision 1.18 retrieving revision 1.19 diff -C2 -d -r1.18 -r1.19 *** DiskOnlyStrategy.java 21 Feb 2007 20:17:21 -0000 1.18 --- DiskOnlyStrategy.java 22 Feb 2007 16:59:34 -0000 1.19 *************** *** 318,321 **** --- 318,333 ---- } + public void closeAndDelete() { + + close(); + + if(!file.delete()) { + + System.err.println("WARN: Could not delete: "+file.getAbsolutePath()); + + } + + } + public void deleteFile() { Index: TemporaryRawStore.java =================================================================== RCS file: /cvsroot/cweb/bigdata/src/java/com/bigdata/journal/TemporaryRawStore.java,v retrieving revision 1.1 retrieving revision 1.2 diff -C2 -d -r1.1 -r1.2 *** TemporaryRawStore.java 21 Feb 2007 20:17:21 -0000 1.1 --- TemporaryRawStore.java 22 Feb 2007 16:59:34 -0000 1.2 *************** *** 153,156 **** --- 153,164 ---- } + public File getFile() { + + if(!open) throw new IllegalStateException(); + + return buf.getFile(); + + } + /** * Close the store and delete the associated file, if any. *************** *** 162,168 **** open = false; ! buf.close(); ! buf.deleteFile(); buf = null; --- 170,178 ---- open = false; ! // buf.close(); ! // ! // buf.deleteFile(); ! buf.closeAndDelete(); buf = null; *************** *** 170,173 **** --- 180,190 ---- } + public void closeAndDelete() { + + // Close already deletes the backing file. + close(); + + } + public void force(boolean metadata) { *************** *** 247,251 **** int segmentId = 0; ! File file = null; // request a unique filename. /* --- 264,278 ---- int segmentId = 0; ! File file; ! ! try { ! ! file = File.createTempFile("bigdata", ".tmpStore"); ! ! } catch (IOException ex) { ! ! throw new RuntimeException(ex); ! ! } /* *************** *** 253,259 **** * twice the data in the in-memory buffer. */ ! long initialExtent = FileMetadata.headerSize0 + tmp.getUserExtent() * 2; ! final boolean create = true; final boolean readOnly = false; --- 280,292 ---- * twice the data in the in-memory buffer. */ ! final long initialExtent = FileMetadata.headerSize0 + tmp.getUserExtent() * 2; ! final long maximumDiskExtent = Bytes.gigabyte32 * 2; ! ! final boolean create = false; ! ! final boolean isEmptyFile = true; ! ! final boolean deleteOnExit = true; final boolean readOnly = false; *************** *** 267,274 **** FileMetadata fileMetadata = new FileMetadata(segmentId, file, BufferMode.Disk, useDirectBuffers, initialExtent, ! create, readOnly, forceWrites); ! ! // Mark the file for deletion on exit. ! fileMetadata.file.deleteOnExit(); // Open the disk-based store file. --- 300,305 ---- FileMetadata fileMetadata = new FileMetadata(segmentId, file, BufferMode.Disk, useDirectBuffers, initialExtent, ! maximumDiskExtent, create, isEmptyFile, deleteOnExit, ! readOnly, forceWrites); // Open the disk-based store file. Index: FileMetadata.java =================================================================== RCS file: /cvsroot/cweb/bigdata/src/java/com/bigdata/journal/FileMetadata.java,v retrieving revision 1.13 retrieving revision 1.14 diff -C2 -d -r1.13 -r1.14 *** FileMetadata.java 21 Feb 2007 20:17:21 -0000 1.13 --- FileMetadata.java 22 Feb 2007 16:59:34 -0000 1.14 *************** *** 159,165 **** * The unique segment identifier. * @param file ! * The name of the file to be opened - when null, a file with a ! * unique name will be created in the default temporary ! * directory. * @param bufferMode * The {@link BufferMode}. --- 159,163 ---- * The unique segment identifier. * @param file ! * The name of the file to be opened. * @param bufferMode * The {@link BufferMode}. *************** *** 170,176 **** * {@link BufferMode#Disk} and {@link BufferMode#Mapped} modes. * @param initialExtent ! * The initial extent of the file iff a new file is created. * @param create * When true, the file is created if it does not exist. * @param readOnly * When true, the file is opened in a read-only mode and it is an --- 168,188 ---- * {@link BufferMode#Disk} and {@link BufferMode#Mapped} modes. * @param initialExtent ! * The initial extent of the journal. The size of the journal is ! * automatically increased up to the <i>maximumExtent</i> on an ! * as necessary basis. ! * @param maximumExtent ! * The maximum extent of the journal before it will ! * {@link Journal#overflow()}. * @param create * When true, the file is created if it does not exist. + * @param isEmptyFile + * This flag must be set when the temporary file mechanism is + * used to create a new temporary file otherwise an empty file is + * treated as an error since it does not contain valid root + * blocks. + * @param deleteOnExit + * When set, a <em>new</em> file will be marked for deletion + * when the VM exits. This may be used as part of a temporary + * store strategy. * @param readOnly * When true, the file is opened in a read-only mode and it is an *************** *** 186,194 **** */ FileMetadata(int segmentId, File file, BufferMode bufferMode, ! boolean useDirectBuffers, long initialExtent, boolean create, boolean readOnly, ForceEnum forceWrites) throws RuntimeException { ! // if (file == null) ! // throw new IllegalArgumentException(); if (bufferMode == null) --- 198,207 ---- */ FileMetadata(int segmentId, File file, BufferMode bufferMode, ! boolean useDirectBuffers, long initialExtent, long maximumExtent, ! boolean create, boolean isEmptyFile, boolean deleteOnExit, boolean readOnly, ForceEnum forceWrites) throws RuntimeException { ! if (file == null) ! throw new IllegalArgumentException(); if (bufferMode == null) *************** *** 226,231 **** this.readOnly = readOnly; ! this.exists = file != null && file.exists(); ! if (exists) { --- 239,246 ---- this.readOnly = readOnly; ! this.exists = !isEmptyFile && file.exists(); ! ! this.file = file; ! if (exists) { *************** *** 243,247 **** } ! if ( ! create ) { throw new RuntimeException("File does not exist and '" --- 258,262 ---- } ! if ( ! create && ! isEmptyFile ) { throw new RuntimeException("File does not exist and '" *************** *** 251,274 **** } - if (file == null) { - - try { - - file = File.createTempFile("bigdata", ".store"); - - } catch (IOException ex) { - - throw new RuntimeException(ex); - - } - - } - System.err.println("Will create file: " + file.getAbsoluteFile()); } - this.file = file; - try { --- 266,273 ---- *************** *** 460,468 **** */ /* * Set the initial extent. */ ! this.extent = initialExtent; this.userExtent = extent - headerSize0; --- 459,474 ---- */ + // Mark the file for deletion on exit. + if(deleteOnExit) file.deleteOnExit(); + /* * Set the initial extent. + * + * Note: since a mapped file CAN NOT be extended, we pre-extend + * it to its maximum extent here. */ ! this.extent = (bufferMode == BufferMode.Mapped ? maximumExtent ! : initialExtent); this.userExtent = extent - headerSize0; Index: ITransactionManager.java =================================================================== RCS file: /cvsroot/cweb/bigdata/src/java/com/bigdata/journal/ITransactionManager.java,v retrieving revision 1.1 retrieving revision 1.2 diff -C2 -d -r1.1 -r1.2 *** ITransactionManager.java 20 Feb 2007 00:27:03 -0000 1.1 --- ITransactionManager.java 22 Feb 2007 16:59:34 -0000 1.2 *************** *** 56,60 **** * @version $Id$ */ ! public interface ITransactionManager { /** --- 56,60 ---- * @version $Id$ */ ! public interface ITransactionManager extends ITimestampService { /** Index: Options.java =================================================================== RCS file: /cvsroot/cweb/bigdata/src/java/com/bigdata/journal/Options.java,v retrieving revision 1.9 retrieving revision 1.10 diff -C2 -d -r1.9 -r1.10 *** Options.java 21 Feb 2007 20:17:21 -0000 1.9 --- Options.java 22 Feb 2007 16:59:34 -0000 1.10 *************** *** 44,47 **** --- 44,48 ---- package com.bigdata.journal; + import java.io.File; import java.nio.channels.FileChannel; import java.util.Properties; *************** *** 67,72 **** /** ! * <code>bufferMode</code> - One of "transient", "direct", "mapped", ! * or "disk". See {@link BufferMode} for more information about each * mode. * --- 68,73 ---- /** ! * <code>bufferMode</code> - One of "Transient", "Direct", "Mapped", ! * or "Disk". See {@link BufferMode} for more information about each * mode. * *************** *** 201,215 **** */ public static final String DOUBLE_SYNC = "doubleSync"; /** ! * <code>deleteOnClose</code> - This optional boolean option causes ! * the journal file to be deleted when the journal is closed (default ! * <em>false</em>). This option is used by the test suites to keep ! * down the disk burden of the tests and MUST NOT be used with live ! * data. */ public final static String DELETE_ON_CLOSE = "deleteOnClose"; /** * The default for {@link #USE_DIRECT_BUFFERS}. */ --- 202,246 ---- */ public static final String DOUBLE_SYNC = "doubleSync"; + + /** + * <code>createTempFile</code> - This boolean option causes a new file to + * be created using the + * {@link File#createTempFile(String, String, File) temporary file mechanism}. + * If {@link #DELETE_ON_EXIT} is also specified, then the temporary file + * will be {@link File#deleteOnExit() marked for deletion} when the JVM + * exits. This option is often used when preparing a journal for a unit + * test. The default temporary directory is used unless it is overriden by + * the {@link #TMP_DIR} option. + */ + public final static String CREATE_TEMP_FILE = "createTempFile"; /** ! * <code>deleteOnClose</code> - This boolean option causes the journal ! * file to be deleted when the journal is closed (default <em>false</em>). ! * This option is used by the some test suites (those that do not test ! * restart safety) to keep down the disk burden of the tests and MUST NOT be ! * used with restart-safe data. */ public final static String DELETE_ON_CLOSE = "deleteOnClose"; + + /** + * <code>deleteOnExit</code> - This boolean option causes the journal file + * to be deleted when the VM exits (default <em>false</em>). This option + * is used by the test suites to keep down the disk burden of the tests + * and MUST NOT be used with restart-safe data. + */ + public final static String DELETE_ON_EXIT = "deleteOnExit"; /** + * <code>tmp.dir</code> - The property whose value is the name of the + * directory in which temporary files will be created. When not specified + * the default is governed by the value of the System property named + * <code>java.io.tmpdir</code>. There are several kinds of temporary + * files that can be created, including temporary journals, intermediate + * files from an index merge process, etc. + */ + public static final String TMP_DIR = "tmp.dir"; + + /** * The default for {@link #USE_DIRECT_BUFFERS}. */ *************** *** 259,261 **** --- 290,307 ---- public final static boolean DEFAULT_DELETE_ON_CLOSE = false; + /** + * The default for the {@link #DELETE_ON_EXIT} option. + */ + public final static boolean DEFAULT_DELETE_ON_EXIT = false; + + /** + * The default for the {@link #CREATE_TEMP_FILE} option. + */ + public final static boolean DEFAULT_CREATE_TEMP_FILE = false; + + /** + * The recommened extension for journal files. + */ + public static final String JNL = ".jnl"; + } Index: Journal.java =================================================================== RCS file: /cvsroot/cweb/bigdata/src/java/com/bigdata/journal/Journal.java,v retrieving revision 1.55 retrieving revision 1.56 diff -C2 -d -r1.55 -r1.56 *** Journal.java 21 Feb 2007 20:17:21 -0000 1.55 --- Journal.java 22 Feb 2007 16:59:34 -0000 1.56 *************** *** 49,52 **** --- 49,53 ---- import java.io.File; + import java.io.IOException; import java.nio.ByteBuffer; import java.util.Map; *************** *** 64,140 **** import com.bigdata.objndx.BTreeMetadata; import com.bigdata.objndx.IIndex; import com.bigdata.rawstore.Addr; import com.bigdata.rawstore.Bytes; import com.bigdata.util.concurrent.DaemonThreadFactory; /** * <p> ! * An append-only persistence capable data structure supporting atomic commit, ! * scalable named indices, and transactions. Writes are logically appended to ! * the journal to minimize disk head movement. ! * </p> ! * ! * <p> ! * The journal provides for fast migration of committed data to a read-optimized ! * database. Data may be migrated as soon as a transaction commits and only the ! * most recent state for any datum need be migrated. Note that the criteria for ! * migration typically are met before the slots occupied by those objects may be ! * released. This is because a concurrent transaction must be permitted to read ! * from the committed state of the database at the time that the transaction was ! * begun. ! * </p> ! * <p> ! * The journal is a ring buffer divised of slots. The slot size and initial ! * extent are specified when the journal is provisioned. Objects are written ! * onto free slots. Slots are released once no active transaction can read from ! * that slots. In this way, the journal buffers consistent histories. ! * </p> ! * <p> ! * The journal maintains two indices: ! * <ol> ! * <li>An object index from int32 object identifier to a slot allocation; and ! * </li> ! * <li>An allocation index from slot to a slot status record.</li> ! * </ol> ! * These data structures are b+trees. The nodes of the btrees are stored in the ! * journal. These data structures are fully isolated. The roots of the indices ! * are choosen based on the transaction begin time. Changes result in a copy on ! * write. Writes percolate up the index nodes to the root node. ! * </p> ! * <p> ! * Commit processing. The journal also maintains two root blocks. Commit updates ! * the root blocks using the Challis algorithm. (The root blocks are updated ! * using an alternating pattern and timestamps are recorded at the head and tail ! * of each root block to detect partial writes.) When the journal is backed by a ! * disk file, the file is flushed to disk on commit. ! * </p> ! * <p> ! * A journal may be used without a database file as an object database. The ! * design is very efficient for absorbing writes, but read operations are not ! * optimized. Overall performance will degrade as the journal size increases ! * beyond the limits of physical memory and as the object index depth increases. * </p> * <p> ! * A journal and a database file form a logical segment in the bigdata ! * distributed database architecture. In bigdata, the segment size is generally ! * limited to a few hundred megabytes. At this scale, the journal and database ! * may both be wired into memory for the fastest performance. If memory ! * constraits are tighted, these files may be memory-mapped or used as a ! * disk-base data structures. A single journal may buffer for multiple copies of ! * the same database segment or journals may be chained for redundancy. * </p> * <p> ! * Very large objects should be handled by specially provisioned database files ! * using large pages and a "never overwrite" strategy. * </p> * <p> ! * Note: This class is NOT thread-safe. Instances of this class MUST use a ! * single-threaded context. That context is the single-threaded journal server ! * API. The journal server may be either embedded (in which case objects are ! * migrated to the server using FIFO queues) or networked (in which case the ! * journal server exposes a non-blocking service with a single thread for reads, ! * writes and deletes on the journal). (However, note transaction processing MAY ! * be concurrent since the write set of a transaction is written on a ! * {@link TemporaryRawStore}.) * </p> * --- 65,103 ---- import com.bigdata.objndx.BTreeMetadata; import com.bigdata.objndx.IIndex; + import com.bigdata.objndx.IndexSegment; import com.bigdata.rawstore.Addr; import com.bigdata.rawstore.Bytes; + import com.bigdata.scaleup.PartitionedJournal.Options; import com.bigdata.util.concurrent.DaemonThreadFactory; /** * <p> ! * The {@link Journal} is an append-only persistence capable data structure ! * supporting atomic commit, named indices, and transactions. Writes are ! * logically appended to the journal to minimize disk head movement. * </p> * <p> ! * Commit processing. The journal maintains two root blocks. Commit updates the ! * root blocks using the Challis algorithm. (The root blocks are updated using ! * an alternating pattern and timestamps are recorded at the head and tail of ! * each root block to detect partial writes.) When the journal is backed by a ! * disk file, the data ! * {@link Options#FORCE_ON_COMMIT optionally flushed to disk on commit}. If ! * desired, the writes may be flushed before the root blocks are updated to ! * ensure that the writes are not reordered - see {@link Options#DOUBLE_SYNC}. * </p> * <p> ! * Note: This class does NOT provide a thread-safe implementation of the ! * {@link IRawStore} API. Writes on the store MUST be serialized. Transaction ! * that write on the store are automatically serialized by {@link #commit(long)}. * </p> * <p> ! * Note: transaction processing MAY occur be concurrent since the write set of a ! * each transaction is written on a distinct {@link TemporaryRawStore}. ! * However, each transaction is NOT thread-safe and MUST NOT be executed by more ! * than one concurrent thread. Typically, a thread pool of some fixed size is ! * created and transctions are assigned to threads when they start on the ! * journal. If and as necessary, the {@link TemporaryRawStore} will spill from ! * memory onto disk allowing scalable transactions (up to 2G per transactions). * </p> * *************** *** 145,149 **** * <ol> * <li> Transaction isolation.</li> ! * <li> Scale out database (automatic re-partitioning of indices).</li> * <li> Distributed database protocols.</li> * <li> Segment server (mixture of journal server and read-optimized database --- 108,114 ---- * <ol> * <li> Transaction isolation.</li> ! * <li> Concurrent load for RDFS w/o rollback.</li> ! * <li> Scale out database (automatic re-partitioning of indices and processing ! * of deletion markers).</li> * <li> Distributed database protocols.</li> * <li> Segment server (mixture of journal server and read-optimized database *************** *** 186,193 **** * detected. * - * FIXME Write tests for writable and read-only fully isolated transactions, - * including the non-duplication of per-tx data structures (e.g., you always get - * the same object back when you ask for an isolated named index). - * * @todo I need to revisit the assumptions for very large objects in the face of * the recent / planned redesign. I expect that using an index with a key --- 151,154 ---- *************** *** 195,198 **** --- 156,167 ---- * limited to 32k or so. Writes on such indices should probably be * directed to a journal using a disk-only mode. + * + * @todo Checksums and/or record compression are currently handled on a per-{@link BTree} + * or other persistence capable data structure basis. It is nice to be + * able to choose for which indices and when ( {@link Journal} vs + * {@link IndexSegment}) to apply these algorithms. However, it might be + * nice to factor their application out a bit into a layered api - as long + * as the right layering is correctly re-established on load of the + * persistence data structure. */ public class Journal implements IJournal { *************** *** 228,243 **** /** ! * The implementation logic for the current {@link BufferMode}. */ ! final IBufferStrategy _bufferStrategy; ! /** ! * The service used to generate commit timestamps. ! * ! * @todo parameterize using {@link Options} so that we can resolve a ! * low-latency service for use with a distributed database commit ! * protocol. */ ! protected final ITimestampService timestampFactory = LocalTimestampService.INSTANCE; /** --- 197,208 ---- /** ! * The directory that should be used for temporary files. */ ! final public File tmpDir; ! /** ! * The implementation logic for the current {@link BufferMode}. */ ! final IBufferStrategy _bufferStrategy; /** *************** *** 324,329 **** boolean useDirectBuffers = Options.DEFAULT_USE_DIRECT_BUFFERS; boolean create = Options.DEFAULT_CREATE; ! boolean readOnly = Options.DEFAULT_READ_ONLY; boolean deleteOnClose = Options.DEFAULT_DELETE_ON_CLOSE; ForceEnum forceWrites = Options.DEFAULT_FORCE_WRITES; ForceEnum forceOnCommit = Options.DEFAULT_FORCE_ON_COMMIT; --- 289,297 ---- boolean useDirectBuffers = Options.DEFAULT_USE_DIRECT_BUFFERS; boolean create = Options.DEFAULT_CREATE; ! boolean createTempFile = Options.DEFAULT_CREATE_TEMP_FILE; ! boolean isEmptyFile = false; boolean deleteOnClose = Options.DEFAULT_DELETE_ON_CLOSE; + boolean deleteOnExit = Options.DEFAULT_DELETE_ON_EXIT; + boolean readOnly = Options.DEFAULT_READ_ONLY; ForceEnum forceWrites = Options.DEFAULT_FORCE_WRITES; ForceEnum forceOnCommit = Options.DEFAULT_FORCE_ON_COMMIT; *************** *** 336,339 **** --- 304,308 ---- this.properties = properties = (Properties) properties.clone(); + // this.properties = properties; /* *************** *** 426,429 **** --- 395,442 ---- /* + * "createTempFile" + */ + + val = properties.getProperty(Options.CREATE_TEMP_FILE); + + if (val != null) { + + createTempFile = Boolean.parseBoolean(val); + + if(createTempFile) { + + create = false; + + isEmptyFile = true; + + } + + } + + // "tmp.dir" + val = properties.getProperty(Options.TMP_DIR); + + tmpDir = val == null ? new File(System.getProperty("java.io.tmpdir")) + : new File(val); + + if (!tmpDir.exists()) { + + if (!tmpDir.mkdirs()) { + + throw new RuntimeException("Could not create directory: " + + tmpDir.getAbsolutePath()); + + } + + } + + if(!tmpDir.isDirectory()) { + + throw new RuntimeException("Not a directory: " + + tmpDir.getAbsolutePath()); + + } + + /* * "readOnly" */ *************** *** 492,495 **** --- 505,573 ---- /* + * "deleteOnExit" + */ + + val = properties.getProperty(Options.DELETE_ON_EXIT); + + if (val != null) { + + deleteOnExit = Boolean.parseBoolean(val); + + } + + /* + * "file" + */ + + File file; + + if(bufferMode==BufferMode.Transient) { + + file = null; + + } else { + + val = properties.getProperty(Options.FILE); + + if(createTempFile && val != null) { + + throw new RuntimeException("Can not use option '" + + Options.CREATE_TEMP_FILE + "' with option '" + + Options.FILE + "'"); + + } + + if( createTempFile ) { + + try { + + val = File.createTempFile("bigdata-" + bufferMode + "-", + ".jnl", tmpDir).toString(); + + // // the file that gets opened. + // properties.setProperty(Options.FILE, val); + // // turn off this property to facilitate re-open of the same file. + // properties.setProperty(Options.CREATE_TEMP_FILE,"false"); + + } catch(IOException ex) { + + throw new RuntimeException(ex); + + } + + } + + if (val == null) { + + throw new RuntimeException("Required property: '" + + Options.FILE + "'"); + + } + + file = new File(val); + + } + + /* * Create the appropriate IBufferStrategy object. */ *************** *** 541,564 **** /* - * "file" - */ - - val = properties.getProperty(Options.FILE); - - if (val == null) { - - throw new RuntimeException("Required property: '" - + Options.FILE + "'"); - - } - - File file = new File(val); - - /* * Setup the buffer strategy. */ FileMetadata fileMetadata = new FileMetadata(segmentId, file, ! BufferMode.Direct, useDirectBuffers, initialExtent, create, readOnly, forceWrites); --- 619,628 ---- /* * Setup the buffer strategy. */ FileMetadata fileMetadata = new FileMetadata(segmentId, file, ! BufferMode.Direct, useDirectBuffers, initialExtent, ! maximumExtent, create, isEmptyFile, deleteOnExit, readOnly, forceWrites); *************** *** 575,598 **** /* - * "file" - */ - - val = properties.getProperty(Options.FILE); - - if (val == null) { - - throw new RuntimeException("Required property: '" - + Options.FILE + "'"); - - } - - File file = new File(val); - - /* * Setup the buffer strategy. */ FileMetadata fileMetadata = new FileMetadata(segmentId, file, ! BufferMode.Mapped, useDirectBuffers, initialExtent, create, readOnly, forceWrites); --- 639,648 ---- /* * Setup the buffer strategy. */ FileMetadata fileMetadata = new FileMetadata(segmentId, file, ! BufferMode.Mapped, useDirectBuffers, initialExtent, ! maximumExtent, create, isEmptyFile, deleteOnExit, readOnly, forceWrites); *************** *** 609,632 **** /* - * "file" - */ - - val = properties.getProperty(Options.FILE); - - if (val == null) { - - throw new RuntimeException("Required property: '" - + Options.FILE + "'"); - - } - - File file = new File(val); - - /* * Setup the buffer strategy. */ FileMetadata fileMetadata = new FileMetadata(segmentId, file, ! BufferMode.Disk, useDirectBuffers, initialExtent, create, readOnly, forceWrites); --- 659,668 ---- /* * Setup the buffer strategy. */ FileMetadata fileMetadata = new FileMetadata(segmentId, file, ! BufferMode.Disk, useDirectBuffers, initialExtent, ! maximumExtent, create, isEmptyFile, deleteOnExit, readOnly, forceWrites); *************** *** 706,712 **** } ! /** ! * Close immediately. ! */ public void close() { --- 742,751 ---- } ! public File getFile() { ! ! return _bufferStrategy.getFile(); ! ! } ! public void close() { *************** *** 731,734 **** --- 770,785 ---- } + public void closeAndDelete() { + + close(); + + if (!deleteOnClose) { + + _bufferStrategy.deleteFile(); + + } + + } + private void assertOpen() { *************** *** 1282,1298 **** /** - * Return the {@link ICommitRecord} for the most recent committed state - * whose commit timestamp is less than or equal to <i>timestamp</i>. This - * is used by a {@link Tx transaction} to locate the committed state that is - * the basis for its operations. - * - * @param timestamp - * Typically, the timestamp assigned to a transaction. - * - * @return The {@link ICommitRecord} for the most recent committed state - * whose commit timestamp is less than or equal to <i>timestamp</i> - * -or- <code>null</code> iff there are no {@link ICommitRecord}s - * that satisify the probe. - * * @todo the {@link CommitRecordIndex} is a possible source of thread * contention since transactions need to use this code path in order --- 1333,1336 ---- *************** *** 1301,1307 **** * handling this. */ ! public ICommitRecord getCommitRecord(long timestamp) { ! return _commitRecordIndex.find(timestamp); } --- 1339,1345 ---- * handling this. */ ! public ICommitRecord getCommitRecord(long comitTime) { ! return _commitRecordIndex.find(comitTime); } *************** *** 1326,1339 **** } /* * ITransactionManager and friends. * ! * @todo refactor into a service. provide an implementation that supports ! * only a single Journal resource and an implementation that supports a ! * scale up/out architecture. the journal should resolve the service using ! * JINI. the timestamp service should probably be co-located with the ! * transaction service. */ /** --- 1364,1387 ---- } + /* * ITransactionManager and friends. * ! * @todo refactor into an ITransactionManager service. provide an ! * implementation that supports only a single Journal resource and an ! * implementation that supports a scale up/out architecture. the journal ! * should resolve the service using JINI. the timestamp service should ! * probably be co-located with the transaction service. ! */ ! ! /** ! * The service used to generate commit timestamps. ! * ! * @todo parameterize using {@link Options} so that we can resolve a ! * low-latency service for use with a distributed database commit ! * protocol. */ + protected final ITimestampService timestampFactory = LocalTimestampService.INSTANCE; /** *************** *** 1373,1378 **** // + _rootBlock.getCommitCounter()); ! return new Tx(this, timestampFactory.nextTimestamp(), readOnly) ! .getStartTimestamp(); } --- 1421,1429 ---- // + _rootBlock.getCommitCounter()); ! final long startTime = nextTimestamp(); ! ! new Tx(this, startTime, readOnly); ! ! return startTime; } *************** *** 1384,1399 **** } - public IIndex getIndex(String name, long ts) { - - if(name == null) throw new IllegalArgumentException(); - - ITx tx = activeTx.get(ts); - - if(tx==null) throw new IllegalStateException(); - - return tx.getIndex(name); - - } - public void abort(long ts) { --- 1435,1438 ---- *************** *** 1650,1653 **** --- 1689,1710 ---- } + + public long nextTimestamp() { + + return timestampFactory.nextTimestamp(); + + } + + public IIndex getIndex(String name, long ts) { + + if(name == null) throw new IllegalArgumentException(); + + ITx tx = activeTx.get(ts); + + if(tx==null) throw new IllegalStateException(); + + return tx.getIndex(name); + + } } Index: MappedBufferStrategy.java =================================================================== RCS file: /cvsroot/cweb/bigdata/src/java/com/bigdata/journal/MappedBufferStrategy.java,v retrieving revision 1.9 retrieving revision 1.10 diff -C2 -d -r1.9 -r1.10 *** MappedBufferStrategy.java 21 Feb 2007 20:17:21 -0000 1.9 --- MappedBufferStrategy.java 22 Feb 2007 16:59:34 -0000 1.10 *************** *** 5,9 **** import com.bigdata.rawstore.Addr; - import com.bigdata.scaleup.PartitionedJournal; /** --- 5,8 ---- *************** *** 19,23 **** * Note: Extension and truncation of a mapped file are not possible with the JDK * since there is no way to guarentee that the mapped file will be unmapped in a ! * timely manner. * </p> * --- 18,31 ---- * Note: Extension and truncation of a mapped file are not possible with the JDK * since there is no way to guarentee that the mapped file will be unmapped in a ! * timely manner. Journals that handle {@link IJournal#overflow()} should ! * trigger overflow just a bit earlier for a {@link MappedByteBuffer} in an ! * attempt to avoid running out of space in the journal. If a transaction can ! * not be committed due to overflow, it could be re-committed <em>after</em> ! * handling the overflow event (e.g., throw a "CommitRetryException"). ! * </p> ! * <p> ! * Note that the use of mapped files might not prove worth the candle due to the ! * difficulties with resource deallocation for this strategy and the good ! * performance of some alternative strategies. * </p> * *************** *** 27,38 **** * @see http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4724038 * @see BufferMode#Mapped - * - * @todo since the mapped file can not be extended or truncated, use of mapped - * files pretty much suggests that we pre-extend to the maximum allowable - * extent. it something can not be committed due to overflow, then a tx - * could be re-committed after a rollover of a {@link PartitionedJournal}. - * Note that the use of mapped files might not prove worth the candle due - * to the difficulties with resource deallocation for this strategy and - * the good performance of some alternative strategies. */ public class MappedBufferStrategy extends DiskBackedBufferStrategy { --- 35,38 ---- Index: BlockWriteCache.java =================================================================== RCS file: /cvsroot/cweb/bigdata/src/java/com/bigdata/journal/BlockWriteCache.java,v retrieving revision 1.2 retrieving revision 1.3 diff -C2 -d -r1.2 -r1.3 *** BlockWriteCache.java 21 Feb 2007 20:17:21 -0000 1.2 --- BlockWriteCache.java 22 Feb 2007 16:59:34 -0000 1.3 *************** *** 80,84 **** * </p> * ! * FIXME Implement and integrate this buffering strategy in order to recover an * approximately 5x overhead introduced by doing too many IOs. * --- 80,84 ---- * </p> * ! * @todo Implement and integrate this buffering strategy in order to recover an * approximately 5x overhead introduced by doing too many IOs. * Index: DiskBackedBufferStrategy.java =================================================================== RCS file: /cvsroot/cweb/bigdata/src/java/com/bigdata/journal/DiskBackedBufferStrategy.java,v retrieving revision 1.9 retrieving revision 1.10 diff -C2 -d -r1.9 -r1.10 *** DiskBackedBufferStrategy.java 15 Feb 2007 22:01:18 -0000 1.9 --- DiskBackedBufferStrategy.java 22 Feb 2007 16:59:34 -0000 1.10 *************** *** 104,107 **** --- 104,119 ---- } + public void closeAndDelete() { + + close(); + + if(!file.delete()) { + + System.err.println("WARN: Could not delete: "+file.getAbsolutePath()); + + } + + } + public void deleteFile() { Index: TransientBufferStrategy.java =================================================================== RCS file: /cvsroot/cweb/bigdata/src/java/com/bigdata/journal/TransientBufferStrategy.java,v retrieving revision 1.9 retrieving revision 1.10 diff -C2 -d -r1.9 -r1.10 *** TransientBufferStrategy.java 21 Feb 2007 20:17:21 -0000 1.9 --- TransientBufferStrategy.java 22 Feb 2007 16:59:34 -0000 1.10 *************** *** 1,7 **** package com.bigdata.journal; import java.nio.ByteBuffer; - /** * Transient buffer strategy uses a direct buffer but never writes on disk. --- 1,7 ---- package com.bigdata.journal; + import java.io.File; import java.nio.ByteBuffer; /** * Transient buffer strategy uses a direct buffer but never writes on disk. *************** *** 39,46 **** BufferMode.Transient, // (useDirectBuffers ? ByteBuffer ! .allocateDirect((int) assertNonDiskExtent(initialExtent)) ! : ByteBuffer ! .allocate((int) assertNonDiskExtent(initialExtent))) ! ); open = true; --- 39,44 ---- BufferMode.Transient, // (useDirectBuffers ? ByteBuffer ! .allocateDirect((int) initialExtent) : ByteBuffer ! .allocate((int) initialExtent))); open = true; *************** *** 61,64 **** --- 59,71 ---- } + + /** + * Always returns <code>null</code>. + */ + public File getFile() { + + return null; + + } public void close() { *************** *** 70,79 **** } - // force(true); - open = false; } final public boolean isOpen() { --- 77,90 ---- } open = false; } + public void closeAndDelete() { + + close(); + + } + final public boolean isOpen() { Index: Tx.java =================================================================== RCS file: /cvsroot/cweb/bigdata/src/java/com/bigdata/journal/Tx.java,v retrieving revision 1.32 retrieving revision 1.33 diff -C2 -d -r1.32 -r1.33 *** Tx.java 21 Feb 2007 20:17:21 -0000 1.32 --- Tx.java 22 Feb 2007 16:59:34 -0000 1.33 *************** *** 214,226 **** /** - * Create a fully isolated read-write transaction. - */ - public Tx(Journal journal,long timestamp) { - - this(journal, timestamp, false); - - } - - /** * Create a transaction starting the last committed state of the journal as * of the specified startTime. --- 214,217 ---- *************** *** 408,412 **** * support a distributed database commit protocol. */ ! commitTimestamp = journal.timestampFactory.nextTimestamp(); try { --- 399,403 ---- * support a distributed database commit protocol. */ ! commitTimestamp = journal.nextTimestamp(); try { |