Welcome!

Welcome to the official BlackBerry Support Community Forums.

This is your resource to discuss support topics with your peers, and learn from each other.

inside custom component

Java Development

Reply
Highlighted
Developer
Posts: 111
Registered: ‎10-01-2009
My Device: Not Specified

background persistentobject commit

Im trying to keep a local version of database info so that my app is usable offline, and so only updates need to be downloaded. When i commit my data to the persistentstore, it completely locks up the app for a while (could be a few minutes). While i had it saving everytime i downloaded new data, i've now moved that to a seperate function that has to be called by user (selected from a menu).  should this be locking up the app though? ive put it in

 

UiApplication.getUiApplication().invokeLater(new Runnable() {
public void run() { /* commit here */ } });

 but since its not doing anything witht he screen, i shouldnt have to do this right? do i need to just make a regular thread that will either run commit at regular intervals in the background, or will the committ always lock up the app?

 

Developer
Posts: 1,474
Registered: ‎04-14-2009
My Device: Not Specified

Re: background persistentobject commit

The invokeLater code you posted will simply make the commit execute on the very same UI/event thread (thus blocking the UI anyway). It's just that the execution is delayed until after the current event (the one from which you post the invokeLater) is processed.

 

You're right though -- if the commit is taking very long, you should be running it in a separate thread. You can start a new thread every time you want to run commit.

 

If you are invoking such commits very frequently (sometimes many times a second), you don't want to start a new thread every time. You can simply wait until, say, 5 seconds elapse since the time of your last modification that requires a commit, and then start a new thread that will commit. You can achieve this by posting a "commit" TimerTask into a Timer, scheduling the task for 5 seconds in the future. Every time you perform a modification that requires a commit, you cancel the last scheduled timer task (if any), and schedule a new one.

Developer
Posts: 19,636
Registered: ‎07-14-2008
My Device: Not Specified

Re: background persistentobject commit

Just adding to klyubin's comments, my experience suggests the commit time is proportional to the amount of data that needs to be committed.  So if you add 15,000 Objects to a Vector, then commit the Vector, it will take a long time.  If you only update one row (out of 15,000), then the commit will be quick. 

Developer
Posts: 111
Registered: ‎10-01-2009
My Device: Not Specified

Re: background persistentobject commit

Well i changed it over to a regular thread. now it doesnt lock up immediately, but still locks up the app when it runs.

peter_strange: your response makes me think that I must be going about this completely wrong.  All my objects are custom which is probably my problem. I commit a single "Storage" class that contains all the data in various other custom classes inside.  I'm not sure if it would be better for me to just output my data to vectors and hashtables and then commit that, then re-parse on load instead.

Developer
Posts: 1,474
Registered: ‎04-14-2009
My Device: Not Specified

Re: background persistentobject commit

How are you kicking off that new thread and what does that thread do? I recall that commit does slow does the device, but I can't recall it completely locking up the app.

Developer
Posts: 19,636
Registered: ‎07-14-2008
My Device: Not Specified

Re: background persistentobject commit

[ Edited ]

"I commit a single "Storage" class that contains all the data" - I do something similar for most of the apps I write, so I wouldn't immediately blame this.

 

I suspect if we knew a little more about the underlying processing we would have a better idea how to manage this.  I have always assumed that when an object is persisted (Committed) if was cloned into flash memory.  Now I'm not so sure.  I suspect it would be possible for the cloning to also serialize the data and then encrypt or compress it - which has potential to save significant amounts of space.  This would, I suspect, be part of the infrastructure of the BlackBerry, from the days when it was really just an email machine and the persisted data was streams of easily compressible text that needed to kept securely.

 

I did the 15,000 record then 1 record test to see if the single commit took as long as the large commit, I was surprised when it did not (but pleased for my application).  In this case, the single data storage class was an extension of Vector (so not a native class) and the Rows were also my own Objects.  However it was only a two tier hierarchy of Objects.  I've not tried this sort of performance testing where I have Objects containing Objects, which contain Objects etc.  When you do that, persisting the Object becomes much more complicated I guess. 

 

Anyway I wouldn't read too much into my test, it might be that just did something that suited the BlackBerry by accident, rather than doing something right.

 

I'm going to DevCon, I might hit on a RIM person to see if I can get details on how best to use PersistentStore in this regard. 

 

Edit: just noted klyubin's response. I agree, shouldn't block the app, unless you are waiting for it.

Developer
Posts: 111
Registered: ‎10-01-2009
My Device: Not Specified

Re: background persistentobject commit

to save, i have a menu item that calls the saveStorage method of  my static Storage:

 

	UiApplication.getUiApplication().invokeLater(new Runnable() {
            public void run() {
        		synchronized (store)
        		{
        			store.setContents(Storage.storage);
        			store.commit();
        		}
            }
        });
		

 

 

Developer
Posts: 1,474
Registered: ‎04-14-2009
My Device: Not Specified

Re: background persistentobject commit

This is not run on a separate thread. See my previous post. This code will be run on the event/UI thread, thus blocking your UI. Try this instead:

 

 

new Thread() {
  public void run() {
    synchronized (store)
    {
      store.setContents(Storage.storage);
      store.commit();
    }
  }

}.start();

 

 

Developer
Posts: 111
Registered: ‎10-01-2009
My Device: Not Specified

Re: background persistentobject commit

@peter_strange: Since i am somewhat replicating a database, i have a pretty convoluted structure. Basically structure is ... [list of clients], for each list, [list of staff], [list of devices], etc. and there is some linking between different items (like staff to device).  It is mostly implemented using objects that implement Persistable that contain a hashtable - the hashtable is for the many different properties of the items (like staff first name, last name, or device cpu, memory, etc). All of which is put into another persistable type that contains a vector, the vector containing the list of clients.

So if i am just updating a list of staff for one office, i have to update that staff list, which updates the client, which updates the clientlist. so when i commit the list, i think its updating the whole thing. i think?

this is will be much, much less complicated when i port over to OS5w/sqllite (i have a feeling i will regret saying this later).

Developer
Posts: 111
Registered: ‎10-01-2009
My Device: Not Specified

Re: background persistentobject commit

[ Edited ]
@klyubin - sorry, its too early for me. thats my old code, i updated it after your response last night. i created a new thread, and i call it by calling CommitThread.commit()
but ill try your solution you posted above b/c my thread is crap Smiley Happy

 

  public void commit()
    {
    	synchronized(this)
    	{
        	_start = true;
    		
    	}
    } 

public void run()
    {
        for(;;)
        {
            // Thread control.
            while( !_start && !_stop)
            {
                // Sleep for a bit so we don't spin.
                try 
                {
                    sleep(TIMEOUT);
                } 
                catch (InterruptedException e) 
                {
                    System.err.println(e.toString());
                }
            }
            
            
            // Exit condition.
            if ( _stop )
            {
                return;
            }
            
            synchronized(this)
            {
            	
    		Storage.store.setContents(Storage.storage);
    		Storage.store.commit();
                
                _start = false;
            }
            
            UiApplication.getUiApplication().invokeLater(new Runnable()
            {

		public void run() {
			Dialog.alert("save complete");
		}
            	
            });
            
        }
    }