×

Discussion Board

Results 1 to 2 of 2
  1. #1
    Regular Contributor
    Join Date
    Apr 2003
    Posts
    61

    Series 60: RecordStore size (rms.db file) keeps growing...

    I have been searching the messages on the Java forums and it seems there were/are problems with the record-store management of Series 60 phones (and others).

    The rms.db file keeps growing even if I have deleted all records from the record store:

    1 - Open the record store
    2 - Add a bunch of records
    3 - ... Modify/Delete them and add some others...
    4 - To test the problem:
    4a - Delete all records from the records store.
    4b - Check the number of existing records: returns none (this is OK).
    5 - Close the record store

    Each time I do the above, the rms.db file gets larger and larger, although the number of records in it is 0. Is this normal (does it grow to a maximum size and starts compacting the rms.db only when it grows too large)? Or is this a bug?
    If so, how could i solve this? I use the record-store to save some heap-memory for persisted data: Load one record at a time, do something with it and save its changes.

    Thank you very much.

    -- Anton.

  2. #2
    Regular Contributor
    Join Date
    Apr 2003
    Posts
    61
    I have found a workaround. Here is some code that implements that workaround (much of the code has been omitted, only the parts that deal with handling the record-store modifications).

    The idea is that i delete the current record-store every so now and then. I copy the records from the old one into the a new record-store:

    - Load all data into memory (i don't like this... but hey...)
    - Close and delete current record-store.
    - Create new record-store.
    - Write all the data into the new record-store.

    Here is parts of the code, where Program instances are written into the record-store for persistence:

    public class Program {
    ...

    private static RecordStore smProgramsDB = null; // The current record-store in use.
    private static int smModCount = 0;
    private static String smRecStorePrefix = "Progs_"; // Start of record-store name.

    public int mRSID = 0; // The record-store-id of the Program or 0 if new.
    public String mName = null; // The unique(!) name of the Program.
    ...

    public static void initialize() throws Exception
    {
    /* Find existing record-store starting with "Progs_".
    * If none found, use "Progs_0"
    */
    final String[] recStores = RecordStore.listRecordStores();
    String recName = smRecStorePrefix+smModCount;
    if (recStores != null)
    {
    for (int i = 0; i < recStores.length; i++)
    {
    if (recStores[ i ].startsWith(smRecStorePrefix))
    {
    recName = recStores[ i ];
    break;
    }
    }
    }

    smProgramsDB = RecordStore.openRecordStore(recName, true);
    }

    public static void release()
    {
    try {
    /* Compact and close record-store */
    compactRecStore(true);
    if (smProgramsDB != null)
    smProgramsDB.closeRecordStore();

    }catch (Exception e) { }
    }


    public static Vector getAllPrograms()
    {
    final Vector allProgs = new Vector();
    RecordEnumeration recordEnum = null;
    try {
    recordEnum = smProgramsDB.enumerateRecords(null, null, true);

    final String recStoreName = smProgramsDB.getName();
    while (recordEnum.hasNextElement())
    {
    final int recordID = recordEnum.nextRecordId();
    final byte[] progData = smProgramsDB.getRecord(recordID);
    final DataInputStream dis = new DataInputStream(new ByteArrayInputStream(progData));

    try {
    final String name = dis.readUTF();

    final Program prog = new Program(name);
    prog.mRecStoreName = recStoreName;
    prog.readProgramData(dis);
    dis.close();

    prog.mRSID = recordID;
    allProgs.addElement(prog);
    }
    catch (Exception e2) {
    /* OOPS */
    dis.close();
    }
    }
    } catch (Exception e) {
    e.printStackTrace();
    } finally {
    if (recordEnum != null)
    recordEnum.destroy();
    }
    return allProgs;
    }

    public void save(String pName) throws Exception
    {
    final ByteArrayOutputStream bos = new ByteArrayOutputStream();
    final DataOutputStream dos = new DataOutputStream(bos);

    writeProgramData(dos);

    final byte[] progRow = bos.toByteArray();

    checkID(true);
    if (mRSID != 0)
    smProgramsDB.setRecord(mRSID, progRow, 0, progRow.length);
    else
    mRSID = smProgramsDB.addRecord(progRow, 0, progRow.length);

    dos.close();
    compactRecStore(false);
    }

    public void load() throws Exception
    {
    RecordEnumeration recordEnum = null;
    try {
    checkID(false);
    recordEnum = smProgramsDB.enumerateRecords(null, null, false);

    DataInputStream disInput = null;
    while (recordEnum.hasNextElement())
    {
    final int recordID = recordEnum.nextRecordId();
    final byte[] progData = smProgramsDB.getRecord(recordID);
    final DataInputStream dis = new DataInputStream(new ByteArrayInputStream(progData));
    final String progName = dis.readUTF();

    if (mRSID != 0 && mRSID == recordID)
    { // Found Program with specified ID
    mName = progName;
    disInput = dis;
    break;
    }
    else if (mName != null && mName.equals(progName))
    { // Found Program with specified name
    mRSID = recordID;
    disInput = dis;
    break;
    }
    else
    dis.close();
    }

    if (mRSID == 0) // nothing found...
    return;

    if (disInput == null)
    throw new IOException("Program with ID " + mRSID + " has not been found. (Previously deleted?)");

    readProgramData(disInput);
    disInput.close();
    } catch (Exception e) {
    throw e;
    } finally {
    if (recordEnum != null)
    recordEnum.destroy();
    }
    }

    public void delete() throws Exception
    {
    checkID(true);
    if (mRSID != 0)
    {
    smProgramsDB.deleteRecord(mRSID);
    compactRecStore(false);
    }

    mRSID = 0;
    mName = null;
    }


    /* This method checks if the Program's ID (mRSID) is still
    * valid. It is valid if it is 0 (new Program) or - when not 0 -
    * if the current record-store is the same record-store that was
    * used to load the program or used in a previous save.
    */
    private boolean checkID(boolean pReload) throws Exception
    {
    if (mRSID != 0)
    {
    final String recStoreName = smProgramsDB.getName();
    if (!recStoreName.equals(mRecStoreName))
    { // Record-store changed! Invalidate the mRSID
    // and, if needed, try to reload from new record-store.
    mRSID = 0;
    if (pReload)
    load();
    return false;
    }
    }
    return true;
    }

    /* This method compacts the record-store by copying the current one
    * into a new one and the making the new one the current one.
    */
    private static void compactRecStore(boolean pForce) throws Exception
    {
    if (smModCount < 0) // Sentinel
    return;

    smModCount++;

    // Force compacting now or do it only every 10 calls.
    if (pForce || smModCount >= 10)
    {
    smModCount = -1;
    /* First get and load all the current progs.
    * I don't like this too much... it means that all the data is now
    * in main memory.... but what can you do...?
    * I have not tried to create the new record-store before deleting
    * the current one.. this may work as well. This would allow me to
    * not have all Programs in main memory...
    */
    final Vector progs = getAllPrograms();

    /* Close and delete current one. */
    final String curRSName = smProgramsDB.getName();
    smProgramsDB.closeRecordStore();
    smProgramsDB = null;
    RecordStore.deleteRecordStore(curRSName);

    /* Reopen new one. */
    smProgramsDB = RecordStore.openRecordStore(smRecStorePrefix+System.currentTimeMillis(), true);

    /* Save all the Programs into the new store. */
    Program prog;
    for (int i = 0; i < progs.size(); i++)
    {
    prog = (Program)progs.elementAt(i);
    prog.mRSID = 0;
    prog.save(null);
    }

    smModCount = 0;
    }
    }
    }

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  
×