Object Store space and setProperty()

I am writing a widget which will obtain data from a web request and store this in the object store. Depending on how I use the widget, I could fill up the 8k space limit of the object store. I have options which will delete data, and others that request and save data. Therefore I was wanting to ensure that the data gets saved correctly. I had expected the setProperty to return something other than null when it was successful. But it appears to always return null.

Short of calling setProperty() followed by getProperty() and checking I get what I set, is there a way to ensure that the setProperty worked and that I am not out of space?

In fact, when testing this it seems that in the simulator at least, if you try to save something bigger than 8K you get a runtime out of memory error, if I save multiple objects smaller than this but totalling more than 8K it seems to work but then the whole object store gets wiped when the widget exits.

Short of attempting to manage the size of the data I am saving in the object store myself, what is the best way to use the object store when I could hit the 8K limit?
  • There isn't anything that will tell you how much space is available in the object store. It seems that you need to avoid ever getting into the situation in the first place. You might have to use a strategy that allows you to leave some data on the server side and retrieve it as necessary instead of caching it all on the client side.

    Another option would be to write a wrapper around the object store, keep only store a single object in it, and validate you don't exceed the limits. Something like this (virtually untested)...

    class XApp extends App.AppBase
    {
    hidden var _M_properties;
    hidden var _M_size;

    function initialize() {
    AppBase.initialize();
    }

    function onStart(params) {
    _M_properties = AppBase.getProperty(1);
    if (_M_properties == null) {
    _M_properties = {};
    }

    _M_size = AppBase.getProperty(2);
    if (_M_size == null) {
    _M_size = calculateSize(_M_properties);
    }
    }

    function onStop(params) {
    AppBase.setProperty(1, _M_properties);
    AppBase.setProperty(2, _M_size);
    }

    function getInitialView() {
    return [ new XView(), new XBehaviorDelegate() ];
    }

    function clearProperties() {
    _M_properties = {};
    _M_size = calculateSize(_M_properties);
    }

    function deleteProperty(key) {
    var found = _M_properties.hasKey(key);
    if (!found) {
    return false;
    }

    var val = _M_properties.get(key);
    _M_properties.remove(key);

    _M_size -= calculateSize(key);
    _M_size -= calculateSize(val);

    Sys.println(_M_size);

    return true;
    }

    function getProperty(key) {
    return _M_properties.get(key);
    }

    function setProperty(key, value) {
    var new_size = _M_size;

    var old_value = _M_properties.get(key);
    if (old_value != null || _M_properties.hasKey(key)) {
    new_size -= calculateSize(old_value);
    new_size += calculateSize(value);
    }
    else {
    new_size += calculateSize(key);
    new_size += calculateSize(value);
    }

    if (new_size > 7500) {
    return false;
    }

    _M_properties.put(key, value);
    _M_size = new_size;

    Sys.println(_M_size);

    return true;
    }

    function validateProperty(key, value) {
    return AppBase.validateProperty(key, value);
    }

    hidden function calculateSize(object) {

    // there is probably some overhead in storing each
    // value type that i'm not accounting for. you'll have
    // to come up with better estimates on your own

    var size = 0;
    if (object == null) {
    size = 1;
    }
    else if (object instanceof Lang.Number) {
    size = 5;
    }
    else if (object instanceof Lang.Float) {
    size = 5;
    }
    else if (object instanceof Lang.Boolean) {
    size = 5;
    }
    else if (object instanceof Lang.String) {
    size = 5 + object.length();
    }
    else if (object instanceof Lang.Array) {
    size += 5;
    for (var i = 0; i < object.size(); ++i) {
    size += calculateSize(object);
    }
    }
    else if (object instanceof Lang.Dictionary) {
    size += 5;

    var keys = object.keys();
    for (var i = 0; i < keys.size(); ++i) {
    size += calculateSize(keys);
    size += calculateSize(object[keys]);
    }
    }

    return size;
    }
    }
    [/code]
  • Former Member
    Former Member over 8 years ago
    Unfortunately, the behavior you are seeing on the simulator is the way the object store currently works. The store is loaded into application memory at run-time, and as a result doesn't actually have a limit at that time. The size is only enforced when the application closes and the object store is committed to disk, which results in the entire store being lost if it is too large.

    We hope to make improvements to how this works in the future. For now, to be safe, you will unfortunately have to be pretty conservative and avoid getting close to the limit.
  • Thanks Brian. I'm glad the watch works the same way as the simulator at least and it's easier to handle that the entire store gets blown away rather than ending up inconsistent or corrupt if you try to save too much.

    I'll plan on doing my own memory management.

    And thanks for the sample code Travis. I'm only storing a number and string objects in the store, but this is a useful head start.