borland Packages Class Hierarchy datastore Package Index
java.lang.Object +----borland.datastore.SaveListener +----borland.datastore.CacheOwner +----borland.datastore.DataStore
Variables Constructors Properties Methods Event Listeners
Implements Store
The DataStore component provides the main access point to high performance data caching and compact persistence. It uses a simple hierarchical file system which allows it to contain DataExpress DataSets and arbitrary files (including Java Objects).
Use a DataStore to
To cache and persist a StorageDataSet in a DataStore, set the store and storeName properties of the StorageDataSet.By default, all StorageDataSets (and its subclasses) use a MemoryStore component. Currently MemoryStore and DataStore are the only implementations for the store property. The storeName property is the name associated with this StorageDataSet in the DataStore directory; it must be unique. The value specified for storeName is case insensitive, though it is stored internally in upper case. To force a storeName to be case insensitive, enclose it in quotes, for example
"\"name\""
Adding a DataStore component to your application
To add a DataStore component to your application using the JBuilder UI design tools:
If you prefer, you may also create your DataStore manually (programmatically). Call the DataStore's create() method after setting the desired properties. Note that some properties cannot be changes after the call to the create() method.
DataStore directory structure
The directory structure of the DataStore associates a name and various directory status with a particular data stream. DataStore currently has these public data stream categories:
Data of type Object can be stored in the DataStore as a file stream. The DataStore component provides convenience methods to serialize and deserialize them through the readObject() and writeObject() methods. If these Objects are not serialized using Java serialization, an Exception is raised when the DataStore attempts to save the Object. Also, the class must exist on the classpath when the DataStore attempts to read an Object. (You can also persist Java Objects in a DataStore by using a DataSet with a Column that has an Object data type.)
You can access a DataStore's directory structure by calling its openDirectory() method. This returns a TableDataSet with several columns for the name, data stream category, modification time, size, delete status, and so on. The directory structure for the DataStore's file system typically contains multiple levels that you can traverse using this TableDataSet.
You delete streams in a DataStore by marking their directory entries as deleted. The contents of these streams are reallocated as new storage is needed for existing streams. Although streams can be undeleted, the entire contents may not be present if space was already used for new allocations.
Time values stored in the DataStore's directory DataSet and in Time, Date, and TimeStamp columns are recorded in UTC time.
See the openDirectory() method for more information on the directory DataSet.
Designing and debugging a DataStore application
Changing the store property of a DataSet from its default of MemoryStore to DataStore component is transparent to the DataSet as well as to any data-aware controls that are connected to the DataSet. The storage mechanism of DataStore or MemoryStore is seamlessly integrated into the JBuilder design tools. Object persistence, however, is evident when you shut down your application and reload it: the DataStore component has a "memory" and retains the data (and associated property settings) from the time the application was closed. Therefore, an application that uses a DataStore where the QueryDescriptor or ProcedureDescriptor's executeOnOpen property is enabled should empty the DataSet before re-executing the data provide phase (re-executing the query or stored procedure).
When designing an application that uses a DataStore, it is strongly recommended that:
Because of possible discrepancies that can emerge from object persistence, including your DataStore component in the DataModule ensures that all properties of the DataSet are persisted with the DataStore and are therefore applicable. When discrepancies arise, JBuilder sets the DataSet to read-only. You need to restructure the DataSet and perform a save operation so that the persisted DataSet object is updated with any variables, properties, methods, and events that were added since the object was originally persisted.
References to the StorageDataSets in the DataStore should be made through DataModule accessor methods such as "myBusinessModule.getCustomer()". This is because much of the functionality being surfaced through StorageDataSets is driven by property and event settings. Although most of the important structural StorageDataSet properties are persisted in the DataStore directory, the classes that implement the event listener interfaces are not. By instantiating the StorageDataSet with all event listener settings, constraints, calc fields, and filters implemented with events are properly maintained at run time and design time.
A daemon thread for all open DataStore instances saves modified cache data, by default, every 100 milliseconds. Although the DataStore daemon is very good at saving DataStore modifications, the following precautions should be taken:
If you suspect that cache contents were not properly saved on a DataStore, use the datastore.StreamVerifier class with public static verify() methods to verify a single stream or all streams in a DataStore.
If you use a RowFilter in an application using DataStore, the filter is persisted as a secondary index stream. This means that when you reopen the DataSet, the RowFilter will still be in affect.
You can restructure DataStore StorageDataSets using the Column Designer JBuilder UI. The Column Designer supports moving, deleting, and inserting columns and changing Column data types. To open the Column Designer, right-click any StorageDataSet in your application or DataModule and select the Activate Designer option from the context menu. For more information on the Column Designer, see the Column component.
When restructuring a DataStore, the move, insert, delete, and change type operations are not performed on the StorageDataSet immediately. The structural change is noted inside the DataStore directory as a "pending" operation (see StorageDataSet.getNeedsRestructure() and the StorageDataSet property needsRestructure). To commit the restructure, click the Restructure button from the Column Designer's toolbar, or call the restructure method of the StorageDataSet.
If a DataStore is busy whan an application loads (for example, it is in use by another application), a response event is sent and the application receiving the notification can decide how to respond rather than throw an Exception. If there is no response, the attempt to load the DataStore eventually times out.
The DataStore component differs from TableDataSet in that TableDataSet is intended for file-based import and export of data; there is little persistence except for the actual data. Also, the TableDataSet does not have any default resolver capabilities: the data is simply exported. With the DataStore component, data and property settings persist, under version control, between different runs of an application.
Note: The DataStore component is not intended for use as a database. It does not have multi-user or query capabilities, nor many other features required of a database management system.
When the data type of a Column component in a StorageDataSet that is bound to a DataStore is changed, type coercions occur when going from one type to another. The following table describes what happens when a data type is coerced to another data type. The data types on the left indicate the original data type of the Column with the data types listed along the top of the table indicating the new data type of the Column.
From\To | Big Decimal | Double | Float | Long | int | Short | boolean | Time | Date | Time stamp | String | Input Stream | Object |
BigDecimal | None | Prec | Prec | Prec | Prec | Prec | Prec | Prec | Prec | Prec | Ok | Loss | Loss |
Double | Prec | None | Prec | Prec | Prec | Prec | Prec | Prec | Prec | Prec | Ok | Loss | Loss |
Float | Prec | Ok | None | Prec | Prec | Prec | Prec | Prec | Prec | Prec | Ok | Loss | Loss |
Long | Ok | Prec | Prec | None | Prec | Prec | Prec | Prec | Prec | Prec | Ok | Loss | Loss |
int | Ok | Ok | Prec | Ok | None | Prec | Prec | Prec | Prec | Prec | Ok | Loss | Loss |
Short | Ok | Ok | Ok | Ok | Ok | None | Prec | Prec | Prec | Prec | Ok | Loss | Loss |
boolean | Ok | Ok | Ok | Ok | Ok | Ok | None | Prec | Prec | Prec | Ok | Loss | Loss |
Time | Prec | Prec | Prec | Prec | Prec | Prec | Prec | None | Prec | Prec | Ok | Loss | Loss |
Date | Prec | Prec | Prec | Prec | Prec | Prec | Prec | Prec | None | Prec | Ok | Loss | Loss |
Timestamp | Prec | Prec | Prec | Prec | Prec | Prec | Prec | Prec | Prec | None | Ok | Loss | Loss |
Where the table values represent the following:
DataStore specifications
The specifications of a DataStore are as follows:
Capacity | Max DataStore file size: Blocksize * 2 gigabytes (approx 4,400 gigabytes) |
Default block size | 4k |
Maximum rows | 4 gigabytes per DataSet. |
Maximum row length | 1/3 block size. Note: long values are stored as Binary Large Objects (BLOBs) (BLOBs have a 2 gigabyte limit) |
public static final short ACTIVE_STATE = 0x1Constant that designates a permanent, active stream. One of the possible state values stored in the State column of the directory DataSet.
See Also: openDirectory()
public static final short AGG_STREAM = (short)5|TABLE_STREAM|HIDDEN_STREAM
public static final short DELETED_STATE = 0x4Constant that designates a deleted stream. One of the possible state values stored in the State column of the DataStore's directory DataSet.
public static final short DELETED_STREAM = (short)2|TABLE_STREAM|HIDDEN_STREAM
public static final String DIR_ACCESS = "Access"
public static final String DIR_DEL_TIME = "DelTime"
public static final String DIR_ID = "Id"
public static final String DIR_LENGTH = "Length"
public static final String DIR_MOD_TIME = "ModTime"
public static final String DIR_PROPERTIES = "Properties"
public static final String DIR_STATE = "State"
public static final String DIR_STORE_NAME = "StoreName"
public static final String DIR_TYPE = "Type"
public static final short FETCH_STREAM = (short)6|TABLE_STREAM|HIDDEN_STREAM
public static final short FILE_STREAM = 0x2000
public static final short HIDDEN_STREAM = 0x4000The stream values stored in the directory DataSet "Type" column.
See Also: DataStore.openDirectory().
public static final short INSERTED_STREAM = (short)3|TABLE_STREAM|HIDDEN_STREAM
public static final short ORIGINALS_STREAM = (short)4|TABLE_STREAM|HIDDEN_STREAM
public static final short SECOND_INDEX_STREAM = (short)7|TABLE_STREAM|HIDDEN_STREAM
public static final short TABLE_FILE_STREAM = (short)1|TABLE_STREAM|HIDDEN_STREAM
public static final short TABLE_STREAM = (short)0x8000
public DataStore()Constructs a DataStore component with a default block size of 4k and a maximum sort buffer size of 12 meg.
public final int getBlockSize() public final synchronized void setBlockSize(int blockSize)Specifies the block size of the DataStore file, expressed in kilobytes. Unless specifically set, this property defaults to 4k. This property has no effect on an existing DataStore and is used only when creating a new DataStore. On failure, the setBlockSize method throws a DataSetException.
public final String getFileName() public final synchronized void setFileName(java.lang.String fileName)Specifies the String name of the DataStore file. If the DataStore is open when the setFileName() method is called, a DataSetException is thrown.
If the tempDirName property is not set, temporary files are created in the directory location of the fileName.
public Locale getLocale() public synchronized void setLocale(java.util.Locale locale)Specifies the locale associated with this DataStore. StorageDataSet components use this property when the locale property is not set at the StorageDataSet level.
public final String getLocaleName() public final void setLocaleName(java.lang.String localeName)Stores the locale name associated with this DataStore. StorageDataSets use this locale when the StorageDataSet.Locale property is not set.
public final int getMaxRowLength()Read-only property that returns the maximum length in bytes for a row stored in this DataStore. Note that Columns with large storage requirements like long Strings, Objects or BLOBs are stored separately and are not limited by this length.
public final int getMaxSortBuffer() public final void setMaxSortBuffer(int maxSortBuffer)Determines the maxiumum memory in bytes that is used for the buffer when performing sorting operations such as building indexes. Increasing this number may improve the performance of very large sorts. The minimum value for this property is 32*1024.
Note: Sorts that cannot be done in memory are done on disk.
public final int getMinCacheSize() public final void setMinCacheSize(int size)Determines the number of cache entries in the cache. Note that all DataStore components share the same cache.
public final boolean isOpen()Read-only property that returns whether the DataStore is open (true) or not (false).
public final synchronized void setOpenMode(java.lang.String mode)Write-only property that sets the DataStore to read-write.
public final boolean isReadOnly() public final void setReadOnly(boolean readOnly)If true, only read access is allowed for this DataStore.
public final long getSaveInterval() public final void setSaveInterval(long interval)Determines the time interval for asynchronous cache block saving for this DataStore component. The interval value is expressed in milliseconds and must be greater than or equal to 100 and less than or equal to 2500. Both the setter and getter may throw a DataSetException when applicable.
public final StoreInternals getStoreInternals()This property is used internally by other classes in the JBCL. You should never use this method directly.
public final String getTempDirName() public final void setTempDirName(java.lang.String tempDirName)Specifies the directory for temporary files that are used for operations such as large sorts. If this property is not set, the directory of the fileName property is used for temporary files.
public final synchronized void close()Closes the DataStore component and flushes the data cache. On failure, this method throws a DataSetException. If an IOException is generated, it is returned in the chained DataSetException object.
public final synchronized void closeDirectory()Closes the TableDataSet (returned by the openDirectory method) that contains information on the directory structure for this file system.
See also: openDirectory()
public final synchronized void create()Creates a new DataStore file using the fileName property. A DataSetException is thrown if the file specified in the fileName property already exists.
See also: open()
public final synchronized FileStream createFileStream(java.lang.String storeName)Creates a new FileStream inside the DataStore using storeName for the directory entry.
public final synchronized void deleteStream(java.lang.String storeName)Deletes the named file from the DataStore. To restore the file (if possible), use the undeleteFile() method.
public final synchronized boolean dropIndexStream(java.lang.String storeName, int id)Drops a secondary index of a DataSet. The storeName and id parameters passed into this method can be determined using the directory DataSet.
public final boolean fileExists(java.lang.String storeName)
public final void finalize()Closes the DataStore if it is still open.
Overrides: java.lang.Object.finalize()
public final synchronized StreamProperties getStreamProperties(java.lang.String storeName, int id)Returns a StreamProperties object for a stream with storeName and an id of id Stream and id are retrieved from the directory DataSet (use openDirectory()).
See also: StreamProperties class
public final synchronized void open()Opens a DataStore using the fileName property to locate and open the DataStore. When a StorageDataSet that uses a DataStore is opened, it automatically asks the DataStore to open. This method generates a DataStoreException of DATASTORE_NOT_FOUND or an IOException if appropriate.
public final synchronized StorageDataSet openDirectory()Returns information on the directory structure for this DataStore as a list of DataSets and file streams in the DataStore. This information is returned as rows in a TableDataSet component. The TableDataSet uses the locale setting of the DataStore, if set. If not set, it uses the locale for the DataSet object. On failure, this method throws a DataSetException.
The returned TableDataSet is sorted by the first five of its columns as follows:
Name | Type | Description |
State | short | Column that stores one of the DataStore.*_STATE values. |
DeleteTime | long | Column that stores the UTC time a stream was deleted. If the file has not been deleted, this value is always 0. |
StoreName | String | Column that stores a 128 character name for a stream. |
Type | short | Column that stores one of the DataStore.*_STREAM values. |
Id | int | Column that is a unique identifier for a stream. |
Properties | String | Column with list of persisted properties/events for a DataSet stream |
ModTime | long | Column that stores the last UTC time a stream was modified. |
Length | long | Column that stores the length in bytes of a stream. |
The names of all the columns in the DataStore's directory DataSet are available as constants, for example, DIR_STATE. Using these constants provides compile-time checking that the proper column name has been used.
public final synchronized FileStream openFileStream(java.lang.String storeName)Opens an existing FileStream. Although FileStream extends java.io.InputStream, it also provides seek() and write() methods. This method throws a DataStoreException of FILE_NOT_FOUND if the stream does not exist.
See also: createFileStream()
public final synchronized Object readObject(java.lang.String storeName)Retrieves a Java Object from a DataStore using Java serialization. Object must implement java.io.Serializable.
See Also: writeObject(java.lang.String, java.lang.Object)
public final synchronized void renameStream(java.lang.String storeName, java.lang.String newStoreName)Renames a stream from storeName to newStoreName.
public final void save()Saves the contents of the cache to the DataStore file. On error, this method throws a DataSetException.
public final boolean tableExists(java.lang.String storeName)Returns true if a table stream with the specified storeName exists.
public final synchronized boolean undeleteStream(java.lang.String storeName, int id)Undeletes a deleted stream if its space has not been reallocated to other active streams.
See Also: openDirectory(), deleteStream(String)
public final synchronized void writeObject(java.lang.String storeName, java.lang.Object object)Stores a Java Object into the DataStore using Java serialization. Object must implement java.io.Serializable.
See Also: readObject(java.lang.String)
public final void addResponseListener(borland.jbcl.dataset.ResponseListener listener) public final void removeResponseListener(borland.jbcl.dataset.ResponseListener listener)