BlackBerry Persistent Storage Models

Download Report

Transcript BlackBerry Persistent Storage Models

BlackBerry Persistent Storage Models
Persistent Storage APIs
and
Record Management System
Overview
• Part 1– Persistent Storage APIs
• Part 2– MIDP Record Store (RMS)
http://cmer.cis.uoguelph.ca
2
PART 1 – PERSISTENT
STORAGE APIS
http://cmer.cis.uoguelph.ca
3
PersistentStore class
• PersistentStore provides a means for storing
persistent objects
• The class to work with persistent store is
net.rim.device.api.system.PersistentStore
• Persistent objects consisting of a key-value
pair, are committed to the persistent store.
• You can retrieve them from the persistent
store by their key.
http://cmer.cis.uoguelph.ca
4
PersistentStore class
(Cont.)
• To retrieve them, invoke
PersistentStore.getPersistentObject(long key)
method.
• Example:
// Hash of cmer.project.persistentobject.uniquekey
long KEY = 0x5602c4fba32d702L ;
static PersistentObject store;
Static{
store = PersistentStore.getPersistentObject( KEY );
}
http://cmer.cis.uoguelph.ca
5
PersistentStore class
(Cont.)
• In the previous example, using a static
constructor means that the PersistentObject is
created only once.
• The key is a hash of a string. The string is
typically the name of your package.
http://cmer.cis.uoguelph.ca
6
Persistent Objects
• Persistent Objects are objects whose content
remains persistent between device resets.
• There are two types of persistent objects:
– PersistentObject
– Implicit persistence
• Persistent objects are stored permanently in a
PersistentStore object.
http://cmer.cis.uoguelph.ca
7
Implicit persistence
• A custom data types are implicitly persistable
if they implement a Persistable interface.
• These data types are:
–
–
–
–
–
Boolean
Byte
Integer
Long
String
-Vector
- Hashtable
- Object
- Short
http://cmer.cis.uoguelph.ca
8
Example- Implicit
Persistence
private static final class Employee implements Persistable {
private String name;
private String address;
public Employee() {
}
public String getName() {
return this.name;
}
public void setName(String value) {
this.name = value;
}
……
}
http://cmer.cis.uoguelph.ca
9
PersistentObject Class
• The class to work with Persistent Object is
net.rim.device.api.system.PersistentObject
• Persistent objects are stored in a PersistentStore
object.
• When a persistent object is stored to persistent
store, the persistent object is stored in flash
memory.
http://cmer.cis.uoguelph.ca
10
PersistentObject class
(Cont.)
• A persistent Object consists of a key-value
pair.
• Each PersistentObject has a unique long
key.
• The unique key acts as an identifier for an
object meaning that objects can be retrieved
from a PersistentStore via this key.
http://cmer.cis.uoguelph.ca
11
PersistentObject class
(Cont.)
• In BlackBerry JDE, you are able to build a
unique key.
• You can do it by writing a string in IDE (any
string) such as
“cmer.project.persistentobject.uniquekey”
• Then, Right-click this string and select
“convert to long”
http://cmer.cis.uoguelph.ca
12
PersistentObject class
(Cont.)
http://cmer.cis.uoguelph.ca
13
PersistentObject class
(Cont.)
• You can get and set the contents of the object
using these methods:
– void setContents( Object contents)
– Object getContents()
• When you set the content of the object, you
may want to store the object in the persistent
store. This is done by invoking commit().
• Commit() method writes the contents of the
persistent object to flash memory (persistent
memory)
http://cmer.cis.uoguelph.ca
14
Steps for Storing Data in
Persistent Store
1. Create a unique key
2. Retrieve a persistentObject from the
persistent store by the key
3. Create, change or update the object’s value.
The object can be any data type such as
String, int, String[], …
4. Set the contents of the persistentObject to the
object you have in step 3
5. Commit the persistentObject to the Persistent
Store
http://cmer.cis.uoguelph.ca
15
Example- Create a
Persistent Object
static {
//Create a long key – Key: CMER.lab1.persistentAPI
long dbkey = 0x6b5fddcbb010cf0cL;
store = PersistentStore.getPersistentObject(dbkey);
synchronized (store) {
if (store.getContents() == null) {
store.setContents(new Vector());
store.commit();
}
}
table = new Vector();
table = (Vector) store.getContents();
}
http://cmer.cis.uoguelph.ca
16
Example- Store a
Persistent Object
private static Vector table;
private static PersistentObject store;
……
private MenuItem _save = new MenuItem("Save", 110, 10) {
public void run() {
table.addElement(favor);
synchronized (store) {
store.setContents(table);
store.commit();
}
}
http://cmer.cis.uoguelph.ca
17
Example- Retrieve a
Persistent Object
private static Vector table;
private static PersistentObject store;
……
private MenuItem _retrieve = new MenuItem("Retrieve", 110, 11) {
public void run() {
synchronized (store) {
table = (Vector) store.getContents();
}
}
};
http://cmer.cis.uoguelph.ca
18
Transactions in
Persistent Storage Model
• There are two common ways to commit objects
to the persistent store:
– Single transaction
– Batches of transactions
• In single transaction, commit() and forceCommit()
are used to commit a single object to the
persistent store.
http://cmer.cis.uoguelph.ca
19
Transactions in Persistent
Storage Model (Cont.)
• These two methods do the same thing.
However, forceCommit() commits the object
immediately to the persistent store.
• Example:
synchronized (store) {
store.setContents(table);
store.commit();
}
http://cmer.cis.uoguelph.ca
20
Batches of Transaction
• A batch transaction commits objects to the
persistent store.
• To do this:
– Invoke PersistentStore.getSyncObject()
• This method retrieves the persistent store monitor to
lock the object.
– Synchronize on the object
– Invoke commit() as necessary.
http://cmer.cis.uoguelph.ca
21
Example- Batches of
Transaction
synchronized (PersistentStore.getSynchObject()) {
…..
store.commit();
}
http://cmer.cis.uoguelph.ca
22
Delete a Database
• To delete a database, invoke
– PersistentStore.destroyPersistentObject(long key)
• It removes the persistent object from the store
by key.
• By deleting the PersistentObject, you
permanently remove all persistent data that
your application has stored.
http://cmer.cis.uoguelph.ca
23
PART 2 – RMS (RECORD
MANAGEMENT SYSTEM)
http://cmer.cis.uoguelph.ca
24
Record Management
System
• MIDP provides a mechanism for Midlets to
persistently store data and retrieve it later
to/from small device.
• This is called Record Management System
(RMS)
• It is a Java ME package. However, BlackBerry
devices support RMS. Although, it is limited in
capabilities
http://cmer.cis.uoguelph.ca
25
RMS (Cont.)
• RMS library package is javax.microedition.rms
• A Record Store is a collection of persistent
records
• Each Record Store has a unique name which is
case-sensitive and between 1-32 unicode
characters
RecordStore
Record ID 0
Record ID 1
http://cmer.cis.uoguelph.ca
26
Record
• A Record is an array of Bytes
• Each record in a record store can have a
different length and different types
• Each record has a unique identifier called
recordID
– It is used to retrieve a record from record store
– It is assigned automatically by an increasing-byone algorithm
http://cmer.cis.uoguelph.ca
27
Methods
• public static RecordStore openRecordStore(
String recordStoreName , boolean createIfNecessary)
throws RecordStoreException,
RecordStoreFullException,
RecordStoreNotFoundException
Opens a record store and returns a
RecordStore object. For any access to record
store, you should call it first
http://cmer.cis.uoguelph.ca
28
Methods (Cont.)
• public String getName() throws
RecordStoreNotOpenException
Returns the name of the record store opened
or created
• public int getNumRecords() throws
RecordStoreNotOpenException
Returns the number of records currently in
the record store.
http://cmer.cis.uoguelph.ca
29
Methods (Cont.)
• public static void
deleteRecordStore(String recordStoreName)
throws RecordStoreException,
RecordStoreNotFoundException
Deletes the named record store. MIDlet suites
are only allowed to delete their own record
stores. A record must be closed before it can be
deleted.
http://cmer.cis.uoguelph.ca
30
Methods (Cont.)
• public void closeRecordStore() throws
RecordStoreNotOpenException,
RecordStoreException
This method is called when the MIDlet
requests to close the record store. Note that
the record store will be closed since
closeRecordStore() is called as many times as
openRecordStore() is called
http://cmer.cis.uoguelph.ca
31
Sharing Record Store
• Midlets within a MIDlet suit can share their
record store.
• If multiple midlet within a MIDlet suit want to
access a record store, the synchronization of
the access operation must be implemented.
• In MIDP 2.0, Midlets whitin a midlet suit can
access to the record stores of the other midlet
suits on the device. In MIDP 1.0, this capability
is not supported.
http://cmer.cis.uoguelph.ca
32
Sharing Record Store
(Cont.)
• To share a record store, you should set
options when you create a record store using
openRecordStore( )
– authmod: it can be AUTHMODE_PRIVATE meaning
that only midlet suit that created the record store
can access to it OR AUTHMODE_ANY allows any
midlet to access the record store
– writable: also , you can identify the type of access
whether it is read-only or it allows others to write to
it.
http://cmer.cis.uoguelph.ca
33
Manipulating Records
• public int addRecord(byte[] data, int offset,
int numBytes) throws
RecordStoreNotOpenException,
RecordStoreException, RecordStoreFullException
Adds a new record to the record store. The recordID for this new
record is returned.
data - the data to be stored in this record.
offset - the index into the data buffer of the first relevant byte for
this record
numBytes - the number of bytes of the data buffer used for this
record (may be zero)
http://cmer.cis.uoguelph.ca
34
Manipulating Records
(Cont.)
• public void deleteRecord(int recordId) throws
RecordStoreNotOpenException,
InvalidRecordIDException, RecordStoreException
To delete a record from the record store
• public byte[] getRecord(int recordId) throws
RecordStoreNotOpenException,
InvalidRecordIDException,
RecordStoreException
Returns a record
http://cmer.cis.uoguelph.ca
35
Manipulating Records
(Cont.)
• public int getRecord(int recordId, byte[] buffer,
int offset) throws RecordStoreException,
RecordStoreNotOpenException,
InvalidRecordIDException,
Returns the record in the given record store,
recordId - the ID of the record to be retrieved
buffer - the byte array in which to copy the data
offset - the index into the buffer in which to start copying
http://cmer.cis.uoguelph.ca
36
Manipulating Records
(Cont.)
• public void setRecord(int recordId, byte[] newData,
int offset, int numBytes)
throws
RecordStoreNotOpenException,
InvalidRecordIDException,
RecordStoreException, RecordStoreFullException
Override the record identified by recordId
http://cmer.cis.uoguelph.ca
37
Example- Open & Close a
Record Store
try{
// To open a record store
RecordStore rs =
RecordStore.openRecordStore(recordStore_name,true);
….
//Close a record store
rs.closeRecordStore();
}catch(Exception e)
{
System.err.println(e.toString());
}
http://cmer.cis.uoguelph.ca
38
Example- Add & Delete a
Record
byte[] rec = str.getBytes();
try {
//Add a new record
rs.addRecord(rec, 0, rec.length);
….
//Delete a record
rs.deleteRecord(recId);
}catch (Exception e)
{
System.err.println(e.toString());
}
http://cmer.cis.uoguelph.ca
39
Example- Retrieve &
Update a Record
byte[] recData= null;
try {
//Retrieve a record from the record store
recData = rs.getRecord(recId);
String retrievedRecord = new String(recData);
…..
//Update a record in the record store
rs.setRecord(recordId, str.getBytes(), 0, str.length());
} catch (Exception e) {
System.err.println(e.toString());
return null;
}
http://cmer.cis.uoguelph.ca
40
Example- Delete a
Record Store
if (RecordStore.listRecordStores() != null)
{
try {
//Delete a record store
RecordStore.deleteRecordStore(recordStore_name);
} catch (Exception e)
{
System.err.println(e.toString());
}
http://cmer.cis.uoguelph.ca
41
Filtering, Comparing, Listening
and Enumerating Records
• RMS provides 4 Java interfaces used to filter,
search and sort a record store:
–
–
–
–
RecordFilter Interface
RecordComparator Interface
RecordListener Interface
RecordEnumerator Interface
http://cmer.cis.uoguelph.ca
42
RecordFilter Interface
• Allows to define filter for searching records It
has the following method:
public boolean matches(byte[] record)
Returns true if the candidate matches the userdefined search criteria.
record - the record to consider.
http://cmer.cis.uoguelph.ca
43
Example- RecordFilter
public class SearchFilter implements RecordFilter {
private String searchText = null;
public SearchFilter(String searchText) {
this.searchText = searchText.toLowerCase(); // This is the text to search for
}
public boolean matches(byte[] candidate) {
String str = new String(candidate).toLowerCase();
// Look for a match
if (searchText != null && str.indexOf(searchText) != -1)
return true;
else
return false;
}
http://cmer.cis.uoguelph.ca
44
RecordComparator
Interface
• It is used to compare two records to check if
they match
public int compare(byte[] rec1, byte[] rec2)
rec1- the first record to use for comparison.
rec2 - the second record to use for comparison.
Return value:
EQUIVALENT: two records are the same in terms of the search
FOLLOWS: the first record follows the second record in terms of
search or search order
PRECEDES: the first record precedes the right record in terms of
search or sort order.
http://cmer.cis.uoguelph.ca
45
ExampleRecordComparator
public class SortCompare implements RecordComparator {
public int compare(byte[] rec1, byte[] rec2){
String str1 = new String(rec1);
String str2 = new String(rec2);
int result = str1.compareTo(str2);
if (result == 0)
return RecordComparator.EQUIVALENT;
else if (result < 0)
return RecordComparator.PRECEDES;
else
return RecordComparator.FOLLOWS;
}
}
http://cmer.cis.uoguelph.ca
46
RecordListener Interface
• It is used to monitor the manipulating records such as
add, delete, …
– public void recordAdded(RecordStore recordStore,
int recordId)
it is called when a record is added to the record store
– public void recordChanged(RecordStore recordStore,
int recordId)
it is called after a record in a record store has been changed.
http://cmer.cis.uoguelph.ca
47
RecordListener Interface
(Cont.)
– public void recordDeleted( RecordStore recordStore,
int recordId)
it is called after a record has been deleted from a record
store. If the implementation of this method tries to retrieve
the record from the record store, an
InvalidRecordIDException will be thrown
http://cmer.cis.uoguelph.ca
48
Example- RecordListener
public class Lab10RecordListner implements RecordListener{
public void recordAdded(RecordStore recordStore, int recordId) {
try {
System.out.println("Record with ID#: " + recordId +
" added to RecordStore: " + recordStore.getName());
}
catch (Exception e)
{
System.err.println(e);
}
}
public void recordDeleted(RecordStore recordStore, int recordId) {
try {
System.out.println("Record with ID#: " + recordId +
" deleted from RecordStore: " + recordStore.getName());
} catch (Exception e) {
System.err.println(e); }
}
public void recordChanged(RecordStore recordStore, int recordId) {}
}
http://cmer.cis.uoguelph.ca
49
RecordEnumerator
Interface
• It provides a method to return an enumeration for
traversing a set of records in the record store
•
public RecordEnumeration enumerateRecords( RecordFilter filter,
RecordComparator comparator, boolean keepUpdated)
throws RecordStoreNotOpenException
filter :
- if non-null, it determines what subset of the record store records will
be used
Comparator:
- if non-null, it will be used to determine the order in which the
records are returned
http://cmer.cis.uoguelph.ca
50
RecordEnumerator
Interface (Cont.)
keepUpdated
- if true, the enumerator will keep its enumeration current with any
changes in the records of the record store.
- If false the enumeration will not be kept current and may return
recordIds for records that have been deleted or miss records that
are added later.
http://cmer.cis.uoguelph.ca
51
Example- Sort
• Sort using Record Enumerator
public void sortingReadRMS(){
try{
if (rs.getNumRecords() > 0){
SortCompare comp = new SortCompare();
RecordEnumeration re=rs.enumerateRecords(null, comp, false);
list1.deleteAll();
while (re.hasNextElement()){
String str = new String(re.nextRecord());
list1.append(str, null);
}
}
} catch (Exception e) {
System.err.println(e.toString());
}
http://cmer.cis.uoguelph.ca
}
52