Just An Application

December 12, 2009

What’s New In MIDP 3.0: Redux – RMS

Filed under: Java, JME, MIDP, MIDP3, MIDP3Issues, RMS — Tags: , , , , , , — Simon Lewis @ 12:16 pm

Original Post

Changes Since Proposed Final Draft

RecordStore.openRecordStore(String,boolean,int,boolean,String)

This new variant of the RecordStore.openRecordStore() method now throws a SecurityException

if the recordStoreName corresponds to an existing RecordStore in the current MIDlet Suite and the password does not match that of the existing RecordStore

This change addresses the issue descibed in my original post. It mandates that the implementation be capable of determining whether the supplied password is correct.

If this change had not been made it would have been necessary for each MIDlet using an encrypted RecordStore to try and determine whether the user supplied password was invalid in some ad-hoc manner.

  • Note

    The words

    in the current MIDlet Suite

    are superflous as this variant of the method can only be used to open RecordStores owned by the MIDlet Suite which contains the calling MIDlet.

RecordStore.openRecordStore(String,String,String,String)

This new variant of the RecordStore.openRecordStore() method now also throws a SecurityException

if the recordStoreName corresponds to an existing RecordStore in the current MIDlet Suite and the password does not match that of the existing RecordStore

This change is identical to the one above and is probably intended to have the same effect. Unfortunately in this context repeating the text verbatim is unnecessarily ambiguous.

Since this method can be used to open RecordStores owned by MIDlet Suites other than that containing the calling MIDlet, and RecordStores owned by LIBlets, presumably the behaviour is not actually intended to be confined to RecordStores

in the current MIDlet Suite

RecordStore.addRecord(byte[],int,int)

The documentation for this method now specifies that it throws an ArrayIndexOutOfBoundsException

if either offset or numBytes is negative, or if offset + numBytes > data.length

This change mandates that an implementation throw an ArrayIndexOutOfBoundsException in these circumstances, which certainly tightens up the specification.

This is never a bad thing, and if this was just one of a large number of such changes it would be unremarkable, but it is actually one of a very small number of changes to the proposed final draft, and arguably there are far more important issues that should have been addressed first.

RecordStore.addRecord(byte[],int,int,int)

The documentation for this method now specifies that it throws an ArrayIndexOutOfBoundsException

if either offset or numBytes is negative, or if offset + numBytes > data.length

See the comments made above.

RecordStore.getRecord(int,byte[],int)

The documentation for this method now specifies that it also throws an ArrayIndexOutOfBoundsException

if offset is negative or greater than or equal to the buffer length

See the comments made above.

RecordStore.setRecord(int,byte[],int,int)

The documentation for this method now specifies that it throws an ArrayIndexOutOfBoundsException

if either offset or numBytes is negative, or if offset + numBytes > data.length

See the comments made above.

RecordStore.setRecord(int,byte[],int,int,int)

The documentation for this method now specifies that it throws an ArrayIndexOutOfBoundsException

if either offset or numBytes is negative, or if offset + numBytes > data.length

See the comments made above.

Issues

RecordStore.exportRecordStore(OutputStream,String,String,String)

When exporting a RecordStore encrypted, the caller of this method still has no control over ths encryption parameters to be used. for example, key length.

The change to the variants of the RecordStore.openRecordStore() method which operate on an encrypted RecordStore, which requires the implementation to detect an invalid password, has not been made to this method. Hence, it is not possible for the caller to determine whether the password for an encrypted RecordStore which is to be exported is invalid, other than by calling one of those RecordStore.openRecordStore() methods first.

RecordStore.importRecordStore(InputStream,String,String)

It is still not possible for the caller of this method to determine whether the method failed because the supplied password was invalid or the supplied data was not in the correct format.

RecordStore.setMode(int,boolean)

The documentation for this method still says

This method can only be called if this recordstore is NOT open by a MIDlet in this suite or in a different MIDlet suite. If this recordStore is open by any MIDlet, an IllegalStateException will be thrown by the method.

Since this method is not static, a literal reading of the text implies that it is actually not possible to ever call it successfully, since to call it you have to have the RecordStore open.

If the intention is that the text should be interpreted as saying

This method can only be called if this recordstore is NOT open by any other MIDlet in this suite or in a different MIDlet suite. If this recordStore is open by any other MIDlet, an IllegalStateException will be thrown by the method.

then it should have been changed to say exactly that.

After all, this is intended to be a technical specification, not material for a case study in hermeneutics.


Copyright (c) 2009 By Simon Lewis. All Rights Reserved.

Advertisements

June 11, 2009

What’s New In MIDP 3.0 ? Part 6: RMS

Filed under: Java, JME, MIDP, MIDP3, RMS — Tags: , , , , — Simon Lewis @ 9:37 am

1. Application Level Access Authorization Support

Access to RecordStores can now be controlled using Application Level Access Authorization.

The constant

    AUTHMODE_APPLEVEL

has been added to the RecordStore class to enable this.

This value can be passed to any RecordStore method which takes an authorization mode.

Adding this support permits much finer-grained sharing of RecordStores between MIDlet Suites
than was possible previously, when a RecordStore was either private to a MIDlet Suite, or
accessible by any MIDlet Suite.

For example, it is now possible to share a RecordStore only between MIDlet Suites in the same
domain, or only between MIDlet suites from a specific vendor.

2. RecordStore Encryption

It is now possible to create a RecordStore the contents of which are stored on the device encrypted.

The encryption is performed using a symmetric-key cipher algorithm, the key being derived
from a password supplied when the RecordStore is created. The algorithm used to
perform the encryption, and the algorithm used to derive the key from the supplied
password, are both implementation specific.

2.1 Creating An Encrypted RecordStore

An encrypted RecordStore can be created using the new RecordStore static method

    
    openRecordStore(
        String  recordStoreName,
        boolean createIfNecessary,
        int     authMode,
        boolean writeable,
        String  password)
	

The first four arguments are identical to the original version of this method.

The password argument specifies the password from which to derive the key to use to encrypt the created RecordStore.

2.2 Opening An Encrypted RecordStore

An existing local encrypted RecordStore can be opened using the variant of openRecordStore() described above.

An existing non-local encrypted RecordStore that is shared can be opened using using the new RecordStore static method

    
    openRecordStore(
        String recordStoreName,
        String vendorName,
        String suiteName,
        String password)
	

The recordStoreName argument specifies the name of the encrypted RecordStore.

The vendorName argument specifies the vendor of the MIDlet suite, or LIBlet, which owns the encrypted RecordStore.

The suiteName argument specifies the name of the MIDlet suite, or LIBlet, which owns the encrypted RecordStore.

The password argument specifies the password that was supplied when the RecordStore was created.

It is an error if the specified RecordStore does not exist, and a RecordStoreNotFoundException will be thrown.

It is an error if the invoking MIDlet is not authorized to access the specified RecordStore, and a SecurityException will be thrown.

Note

The specification does not explicitly require that an implementation detect when the password used to open a previously created encrypted RecordStore is incorrect. Depending upon the implementation, this situation could either result in an exception being thrown or in invalid data being returned when a record is accessed. This implies that in the case where a MIDlet may specify an incorrect password, because it is obtained from the user for example, the MIDlet itself is responsible for detecting this situation in some way. Depending upon the context, this may be more or less difficult.

3. The Interchange File Format

The RMS Interchange File Format (IFF) specifies a binary data format for representing a single RecordStore.

Data in this format can be used to create RecordStores at installation, and runtime, and an existing RecordStore can be exported as data in this format.

The recommended suffix for files in IFF is

    .rms

and the MIME type is

    application/vnd.jcp.javame.midlet-rms

3.1 Encryption Support

The IFF supports the optional encryption of the data representing the RecordStore using a symmetric-key cipher algorithm. The key to use is derived from a password, using the key derivation algorithm PBKDF2, as specified by PKCS#5 v2.0.

The cipher and parameters used to perform the encryption, and the parameters used to derive the key are included in the IFF data.

An implementation must support the AES cipher algorithm, used with a 128 bit key, in CBC mode with PKCS5Padding.

Note

Although the IFF permits the use of arbitrary ciphers any data produced in IFF for the purposes of interchange is more or less going to have to use the default cipher, AES/CBS/PKCS5Padding with a 128-bit key, or there is no guarantee that the data will actually be interchangable.

3.2 Format

Data in the Interchange File Format comprises four sections, the second of which is optional.

Header
EncryptionParameters [Optional]
RecordStoreData
MessageDigestData

In the IFF a string (UTF8String) is represented as though written by the method

    java.io.DataOutputStream.writeUTF()

In the IFF a 32-bit integer (int) is represented as though written by the method

    java.io.DataOutputStream.writeInt()

In the IFF a 64-bit integer (long) is represented as though written by the method

    java.io.DataOutputStream.writeLong()

3.2.1 Header Format

Signature byte[6]
Major byte
Minor byte
Encrypted byte
MessageDigestAlgorithm UTF8String

3.2.1.1 Signature

The six bytes

     0x4d, 0x49, 0x44, 0x52, 0x4d, 0x53

These are the ASCII characters of the string

    MIDRMS

3.2.1.2 Major

Specifies the major version number of the IFF to which the data conforms. Must be 3.

3.2.1.2 Minor

Specifies the minor version number of the IFF to which the data conforms. Must be 0.

3.2.1.3 Encrypted

Specifies whether RecordStoreData and MessageDigestData are encrypted. 1 if they are, 0 otherwise.

3.2.1.4 MessageDigestAlgorithm

Specifies the Message Digest algorithm used to compute MessageDigestData.

3.2.2 EncryptionParameters Format

The EncryptionParameters section is only present if the Encrypted field of the Header has the value 1.

EncryptionAlgorithm UTF8String
IVLength int
IV byte[IVLength]
SaltLength int
Salt bytes[SaltLength]
IterationCount int
KeyLength int

3.2.2.1 EncryptionAlgorithm

Specifies the cipher used to perform the encryption.

It must be of the form

    algorithm

or

    algorithm/mode/padding

3.2.2.2 IVLength

Specifies the length in bytes of the following IV field.

3.2.2.3 IV

The value of the Initialization Vector used by the cipher when the encryption was performed.

3.2.2.4 SaltLength

Specifies the length in bytes of the following Salt field.

3.2.2.5 Salt

Specifies the salt to use when deriving the key.

3.2.2.6 IterationCount

Specifies the iteration count to use when deriving the key.

3.2.2.7 KeyLength

Specifies the length in bits of the key to derive.

3.2.3 RecordStoreData Format

RecordStoreData comprises the RecordStore section followed by zero or more Records.

RecordStore
Record [Zero or more]

Note

Although the specification does not say so, there are a number of integrity constraints that the data in this section must conform to if it is to be used to create a valid RecordStore. I would assume that an implementation is responsible for enforcing those constraints when constructing a RecordStore from data in IFF.

3.2.3.1 RecordStore Format

Name UTF8String
LastModified long
Version int
AuthMode int
Writable byte
NumberOfRecords int

3.2.3.1.1 Name

The name of this RecordStore.

3.2.3.1.2 LastModified

The time of the last modification of this RecordStore.

The value is equal to that which would have been returned by a call to System.currentTimeMillis() made at that time.

3.2.3.1.3 Version

The version of the RecordStore.

3.2.3.1.4 AuthMode

The authorization mode of this RecordStore. Must be one of the RecordStore constants
</p

  • AUTHMODE_PRIVATE
  • AUTHMODE_ANY
  • AUTHMODE_APPLEVEL

3.2.3.1.5 Writable

1 if this RecordStore is writable by authorized MIDlets in other MIDlet Suites, 0 otherwise.

3.2.3.1.6 NumberOfRecords

The number of Records following this section.

3.2.3.2 Record Format

RecordID int
Tag int
RecordDataSize int
RecordData byte[RecordDataSize]

3.2.3.2.1 RecordID

The id of this record.

3.2.3.2.2 Tag

The tag of this record.

3.2.3.2.3 RecordDataSize

The size in bytes of the following RecordData field.

3.2.3.2.4 RecordData

The contents of this record.

3.2.4 MessageDigestData Format

MessageDigestLength int
MessageDigest byte[MessageDigestLength]

3.2.4.1 MessageDigestLength

Specifies the length in bytes of the following MessageDigest field.

3.2.4.1 MessageDigest

The value of the message digest computed on EncryptionParameters, if present, and RecordStoreData

4. LIBlet RecordStores

RecordStores can be created on a per-LIBlet basis. These stores can only be created at installation time. They can only be accessed at runtime by MIDlets contained in MIDlet suites which are dependent upon the LIBlets which created the RecordStores.

4.1 Creation

Per-LIBlet RecordStores can be created at installation time by the specification of one or more

    LIBLet-Persistent-Data-URL-<n>

attributes in the LIBlet JAD and the manifest of the LIBlet Jar.

Note

The description of this attribute in the specification does not contain the usual strictures about ordinals starting at 1 and then being consecutive, with attributes after the first gap being ignored, but I would assume they do in fact apply.

The value of each specified attribute is of the form

    <dataURL> [" " encryptLocally]

where <dataURL> must be an RFC3986 compliant absolute or relative URL.

If the URI is absolute then the data is external to the LIBlet, and it is automatically downloaded from the specified location.

If the URI is relative then the data is bundled with the LIBlet, and it is loaded from the specified
location within the LIBlet Jar.

If encryptLocally is specified then the created RecordStore will be encrypted, the password being obtained from the user.

It is an error if the specified file cannot be found.

It is an error if the data in the specified file does not conform to the IFF.

It is an error if the value of RecordStore.AuthMode field in the data is not equal to RecordStore.AUTHMODE_PRIVATE.

If there is an error the Installation of the LIBlet, and hence of the MIDlet Suite will fail .

4.2 Runtime Access

A per-LIBlet RecordStore can be accessed at runtime using either the new RecordStore static method

    
    openRecordStore(
        String recordStoreName,
        String vendorName,
        String suiteName,
        String password)
	

if the RecordStore is encrypted, or the original RecordStore static method

    
    openRecordStore(
        String recordStoreName,
        String vendorName,
        String suiteName)
	

if it is not, and specifying the vendor and name of the LIBlet that owns the RecordStore.

5. Exporting A RecordStore

The contents of a RecordStore can now be exported using the newly defined RecordStore static method

    
    exportRecordStore(
        Outputstream outputStream,
        String       recordStoreName,
        String       internalPassword,
        String       exportPassword)
	

The outputStream argument is an instance of OutputStream to which the contents of the RexcordStore will be written in Interchange File Format.

The recordStoreName argument is the name of the RecordStore to export.

The internalPassword argument is the password supplied when the RecordStore was created, or null. This argument is ignored if the specified RecordStore is not encrypted.

The exportPassword argument is the password to use to encrypt the exported RecordStore. If null the exported RecordStore is not encrypted.

It is an error if the specified RecordStore does not exist, and a RecordStoreException will be thrown.

Notes

  1. The specification does not state what message digest algorithm should be used, nor what cipher should be used if the exported data is to be encrypted, nor is it possible to specify either the message digest or cipher via the method call. I would assume that it is intended to be implementation specific. I would also assume that unless it was feeling exceptionally anti-social an implementation would use the default message digest algorithm, SHA1, and the default ciper, AES/CBC/PKCS5Padding, and a 128-bit key.

  2. The specification does not explicitly require that an implementation detect when the password passed to this method is not the same as the password used to create the encrypted RecordStore being exported. Depending on the implementation, this could lead either to an exception being throw, or invalid data being exported. It is not clear how a MIDlet could detect this situation without considerable effort.

Code Fragment

Export an unencrypted store unencrypted

import java.io.OuputStream;
import javax.microedition.rms.RecordStore;

...

    // Get the OutputStream to write the data to
	
    OutputStream os = ...
	
    RecordStore.export(os, "ExampleStore", null, null);

...

Code Fragment

Export an unencrypted store encrypted

import java.io.OuputStream;
import javax.microedition.rms.RecordStore;

...

    // Get the OutputStream to write the data to
	
    OutputStream os = ...
	
    // Get the password for the exported data
	
    String exportPassword = ...
	
    RecordStore.export(os, "ExampleStore", null, exportPassword);

...

Code Fragment

Export an encrypted store unencrypted. Possibly not a good idea.

import java.io.OuputStream;
import javax.microedition.rms.RecordStore;

...

    // Get the OutputStream to write the data to
	
    OutputStream os = ...
	
    // Get the password for theRecordStore
	
    String recordStorePassword = ...
	
    RecordStore.export(os, "ExampleStore", recordStorePassword, null);

...

Code Fragment

Export an encrypted store encrypted.

import java.io.OuputStream;
import javax.microedition.rms.RecordStore;

...

    // Get the OutputStream to write the data to
	
    OutputStream os = ...
	
    // Get the password for theRecordStore
	
    String recordStorePassword = ...
	
    // Get the password for the exported data
	
    String exportPassword = ...
	
    RecordStore.export(os, "ExampleStore", recordStorePassword, exportPassword);

...

6. Importing A RecordStore

A RecordStore can now be created at runtime from data in the Interchange File Format by using the newly defined RecordStore static method

    
    importRecordStore(
        InputStream inputStream,
        String      importPassword,
        String      internalPassword)
	

The inputStream argument is an instance of java.io.InputStream from which to read the data.

The importPassword argument is the password to use to decrypt the data being imported.

The internalPassword argument is the password to use to encrypt the created RecordStore. If it is null then the created RecordStore will not be encrypted.

It is an error if a RecordStore with the same name as that being imported already exists, and a RecordStoreException will be thrown.

If the data to import is encrypted and there is a cryptographic error a SecureRecordStoreException will be thrown.

Note

The specification does not enumerate any further possible errors, although there is at least one,
which is when the supplied data does not conform to the IFF, and for this or, for any other error
the only suitable declared exception is RecordStoreException.

Code Fragment

Create an unencrypted RecordStore from unencrypted data.


import java.io.InputStream;

import javax.microedition.rms.RecordStore;

...

    // Get data to import as an InputStream
	
    InputStream is = ...
	
    RecordStore.importRecordStore(is, null, null);
	
...

Code Fragment

Create an unencrypted RecordStore from encrypted data. Possibly not a good idea.


import java.io.InputStream;

import javax.microedition.rms.RecordStore;

...

    // Get the data to import as an InputStream
	
    InputStream is = ...
	
    // Get the password to use to decrypt the imported data.
	
    String importPassword = ...
	
    RecordStore.importRecordStore(is, importPassword, null);
	
...

Code Fragment

Create an encrypted RecordStore from unencrypted data.


import java.io.InputStream;

import javax.microedition.rms.RecordStore;

...

    // Get the data to import as an InputStream
	
    InputStream is = ...
	



    // Get the password to use to encrypt the created RecordStore.
	
    String recordStorePassword = ...
	
    RecordStore.importRecordStore(is, null, recordStorePassword);
	
...

Code Fragment

Create an encrypted RecordStore from encrypted data.


import java.io.InputStream;

import javax.microedition.rms.RecordStore;

...

    // Get the data to import as an InputStream
	
    InputStream is = ...
	
    // Get the password to use to decrypt the imported data.
	
    String importPassword = ...
	
    // Get the password to use to encrypt the created RecordStore.
	
    String recordStorePassword = ...
	
    RecordStore.importRecordStore(is, importPassword, recordStorePassword);
	
...

7. MIDlet Suite Installation Time RecordStore Creation

At installation time a MIDlet Suite can now create RecordStores using data in the IFF. The data can either bundled with the MIDlet Suite, or the location of the data can be specified and it will be downloaded automatically.

7.1 The MIDlet-Persistent-Data-URL-<n> Attribute

A MIDlet suite can create one or more RecordStores at installation time by specifying the appropriate number of
MIDlet-Persistent-Data-URL-<n> attributes in the manifest of the MIDlet suite JAR.

Note

The description of this attribute in the specification does not contain the usual strictures about
ordinals starting at 1 and then being consecutive, with attributes after the first gap
being ignored, but I would assume they do in fact apply.

The value of each attribute specified must be of the form

    <dataURL> [" " overwrite] [" " encryptLocally]

The <dataURL> must be an RFC 3986 conformant absolute or relative URI.

If the URI is absolute then the data is external to the MIDlet Suite, and it is automatically downloaded
from the specified location.

If the URI is relative then the data is bundled with the MIDlet Suite, and it is loaded from the specified
location within the MIDlet Suite Jar.

Note

The specification states

If overwrite is specified in the MIDlet-Persistent-Data-URL-<n> attribute value, data from the RMS file MUST replace any existing record store of the same name in the device. If a record store with the same name exists in the device and overwrite is not specified, the data from the RMS file MUST be discarded.

I assume that this describes the required behaviour during the upgrade of a MIDlet Suite.

If encryptLocally is present the created RecordStore will be encrypted, the password to use being obtained from the user.

If the data specified for use in creating the RecordStore is encrypted the user will be prompted for the password to use to decrypt it.

It is an error if an attempt is made to create more than one RecordStore of the same name at installation time.

It is an error if the data at the specified location does not conform to the IFF.

If an error occurs then the MIDlet Suite installation will fail.

8. RecordStoreInfo

A new class RecordStoreInfo has been defined in the javax.microedition.rms package.

The class defines methods which can be used to access information about a RecordStore which was either, previously inaccessible,

  • getAuthMode()
  • isWritable()

did not previously exist,

  • isEncrypted()

or whose type has been changed.

  • getSize()
  • getSizeAvailable()

Note

The methods

  • getAuthMode()
  • isEncrypted()
  • isWritable()

could all have been added to the RecordStore class, but the return types of the existing RecordStore
methods

  • getSize()
  • getSizeAvailable()

could not have been changed without breaking binary compatibility.

I assume this is why the decision was made to introduce a new class.

An instance of RecordStoreInfo can be obtained by calling the RecordStore method getRecordStoreInfo().

The values returned by the methods of an instance of RecordStoreInfo reflect the current state of the associated RecordStore.

Once the associated RecordStore has been closed all the methods will throw a RecordStoreNotOpenException.

8.1 getAuthMode()

This method returns the authorization mode of the associated RecordStore as an int.

The returned value is guaranteed to be equal to the value of one of the following RecordStore constants.

  • AUTHMODE_PRIVATE
  • AUTHMODE_ANY
  • AUTHMODE_APPLEVEL

8.2 getSize()

This method returns the size in bytes of the associated RecordStore, including implementation overhead, as a long.

8.3 getSizeAvailable()

This method returns the size in bytes of the storage available for the growth of the associated RecordStore, as a long.

8.4 isEncrypted()

Returns true if the associated RecordStore is encrypted, false otherwise.

8.5 isWriteable()

Returns true if the associated RecordStore can be written by MIDlets authorized to access it, false otherwise.

9. Record Tags

Each record in a RecordStore now has an associated int valued tag.

9.1 Adding A Tagged Record

A tagged record can be added to a RecordStore by using the new RecordStore method

    addRecord(byte[] data, int offset, int nBytes, int tag)

The semantics of the method are the same as those of the original addRecord() method,
but in addition the tag of created record is the value specified.

The tag of a record added using the original addRecord() method is 0.

9.2 Getting A Record’s Tag

The tag of a specific record can be obtained by using the RecordStore method

    getTag(int recordId)

The method returns an int.

If a record with the specified does not exist then an InvalidRecordIDException is thrown.

9.3 Modifying A Record’s Tag

The tag of a specific record can be modified by using the RecordStore method

    
    setRecord(
        int    recordId,
        byte[] newData,
        int    offset,
        int    numBytes,
        int    tag)
	

The first four arguments are identical to the arguments of the original version of this method.

The tag argument specifies the new value of the tag.

The behavior of this method is identical to that of the original version of the method, but in
addition the value of the tag is set to the value specified.

Note

This method is decidedly sub-optimal if only the tag is to be changed as in this case it is always
necessary to obtain the contents of the record first.

9.4 Enumerating Tagged Records

An enumeration of the records whose tag matches one of a set of tags can be obtained using the method

    
    enumerateRecords(
        RecordFilter     filter,
        RecordComparator comparator,
        boolean          keepUpdated,
        int[]            tags)
    

The first three arguments are identical to those of the original version of the method.

The tags argument specifies the set of tags to be matched. The value can be one of

  • null
  • int[0] (an empty int array)
  • int[n > 0] (a non-empty int array)

The semantics of the method are the same as those of the original, except that the set of records returned,
modulo the filter, is constrained by the tags argument as follows

  • if it is null there is no constraint and the method behaves identically to the original version
  • if it is an empty array then the set of records is empty
  • if it is a non-empty array then the set will contain only those records with a tag equal to one of the values of tags

10. SecureRecordStoreException

The exception class SecureRecordStoreException has been defined in the package javax.microedition.rms. It is thrown when there is an encryption/decryption related error.

11. Deprecated RecordStore Methods

Following the addition of the RecordStoreInfo class, the RecordStore methods

  • getSize()
  • getSizeAvailable()

have been deprecated.

The corresponding methods on an associated instance of RecordStoreInfo should be used instead.

12. Support For Large RecordStores ?

The addition of the RecordStoreInfo class whose getSize() and getSizeAvailable() methods both return a long makes it possible for an implementation to support RecordStores larger than 2GB, in the sense that it can actually report the size of such a RecordStore correctly.

RecordStores of this size are clearly feasible in terms of the kind of storage capacity now available at least on some mobile devices, but they remain constrained in other respects.

  • the number of records in a RecordStore is still represented using an int
  • the version number of a RecordStore is still represented using an int
  • the id of a record is still represented using an int
  • the size of a record is still represented using an int

Unless the changes were seriously intended to make it possible for people to create terabyte-scale RecordStores none of this is likely to be a major problem. What may be a problem if people do begin to create gigabyte-scale RecordStores
is performance.

The RecordStore API is extremely low-level. The creation, deletion, and modification of records is single record atomic,
and the effects of these operations may have to be made visible to multiple MIDlets. This constrains the implementation
and the possible optimization techniques that can be applied. Operations on gigabyte scale RecordStores may not be all
that fast.


Copyright (c) 2009 By Simon Lewis. All Rights Reserved.

Blog at WordPress.com.

%d bloggers like this: