All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.objectfabric.IndexedDBView Maven / Gradle / Ivy

The newest version!
/**
 * This file is part of ObjectFabric (http://objectfabric.org).
 *
 * ObjectFabric is licensed under the Apache License, Version 2.0, the terms
 * of which may be found at http://www.apache.org/licenses/LICENSE-2.0.html.
 * 
 * Copyright ObjectFabric Inc.
 * 
 * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
 * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 */

package org.objectfabric;

import java.util.ArrayList;

import org.objectfabric.InFlight.Provider;

import com.google.gwt.core.client.JavaScriptObject;
import com.google.gwt.typedarrays.client.Uint8ArrayNative;
import com.google.gwt.typedarrays.shared.ArrayBuffer;

final class IndexedDBView extends ArrayView {

    private final String _uriKey;

    IndexedDBView(Location location, String uriKey) {
        super(location);

        _uriKey = uriKey;
    }

    final String getKey(long tick) {
        String tickKey = IndexedDB.getKey(tick);
        return _uriKey + tickKey;
    }

    final long getTick(String key) {
        return IndexedDB.getTick(key.substring(_uriKey.length()));
    }

    private final IndexedDB cache() {
        return (IndexedDB) location();
    }

    @Override
    final void getKnown(URI uri) {
        long[] ticks = copy();

        if (ticks != null) {
            if (ticks.length != 0 || !location().isCache())
                uri.onKnown(this, ticks);
        } else
            list(uri, null);
    }

    @Override
    final void onKnown(URI uri, long[] ticks) {
        if (isNull())
            list(uri, ticks);
        else
            getUnknown(uri, ticks);
    }

    private final void list(final URI uri, final long[] compare) {
        if (cache().db() == null) {
            cache().runWhenStarted(new Runnable() {

                @Override
                public void run() {
                    listImpl(uri, compare);
                }
            });
        } else
            listImpl(uri, compare);
    }

    private final void listImpl(final URI uri, long[] compare) {
        if (Debug.PERSISTENCE_LOG)
            Log.write("IndexedDBView openCursor " + uri);

        if (Stats.ENABLED)
            Stats.Instance.BlockListCount.incrementAndGet();

        ArrayList keys = new ArrayList();
        cursor(uri, cache().db(), IndexedDB.BLOCKS, _uriKey, keys, compare);
    }

    private native void cursor(URI uri, JavaScriptObject db, String store, String key, ArrayList keys, long[] compare) /*-{
    var transaction = db.transaction(store);
    var store = transaction.objectStore(store);
    var cursor = store.openCursor(window.IDBKeyRange.lowerBound(key));
    var this_ = this;

    cursor.onsuccess = function(e) {
      var result = e.target.result;
      var key = null;

      if (result)
        key = result.key;

      var done = [email protected]::step(Lorg/objectfabric/URI;Ljava/lang/String;Ljava/util/ArrayList;[J)(uri, key, keys, compare);

      if (!done)
        result["continue"]();
    };
    }-*/;

    @SuppressWarnings("null")
    private final boolean step(URI uri, String key, ArrayList keys, long[] compare) {
        boolean done = key == null;

        if (!done)
            for (int i = 0; i < SHA1Digest.LENGTH / 2; i++)
                if (key.charAt(i) != _uriKey.charAt(i))
                    done = true;

        if (!done)
            keys.add(key);
        else {
            long[] ticks = null;

            if (keys.size() > 0) {
                for (int i = 0; i < keys.size(); i++)
                    ticks = Tick.add(ticks, getTick(keys.get(i)));
            } else
                ticks = Tick.EMPTY;

            onLoad(uri, ticks, compare);
        }

        return done;
    }

    @Override
    void getBlock(URI uri, long tick) {
        if (Debug.PERSISTENCE_LOG)
            Log.write("IndexedDB read " + uri + " - " + Tick.toString(tick));

        Read read = read(cache().db(), IndexedDB.BLOCKS, getKey(tick), uri, tick);

        if (!InFlight.starting(uri, tick, read))
            read.cancel(uri, tick);
    }

    private native Read read(JavaScriptObject db, String store, String key, URI uri, Long tick) /*-{
    var transaction = db.transaction(store);
    var request = transaction.objectStore(store).get(key);
    var this_ = this;

    request.onsuccess = function(e) {
      [email protected]::onsuccess(Lorg/objectfabric/URI;Ljava/lang/Long;Lcom/google/gwt/typedarrays/shared/ArrayBuffer;)(uri, tick, e.target.result);
    };

    return transaction;
    }-*/;

    private final void onsuccess(URI uri, Long tick, ArrayBuffer buffer) {
        GWTBuff buff = new GWTBuff(Uint8ArrayNative.create(buffer));

        if (Debug.ENABLED)
            buff.lock(buff.limit());

        if (Stats.ENABLED)
            Stats.Instance.BlockReadCount.incrementAndGet();

        Buff[] buffs = new Buff[] { buff };
        Exception exception = uri.onBlock(this, tick, buffs, null, true, null, false, null);

        if (Debug.THREADS)
            ThreadAssert.exchangeTake(buffs);

        if (exception != null) {
            // TODO make sure exception is related to parsing
            Log.write("Corrupted block " + exception.toString());
            // TODO Make option or callback to clean corrupted
            // file.delete();
        }
    }

    static final class Read extends JavaScriptObject implements Provider {

        protected Read() {
        }

        @Override
        public void cancel(URI uri, long tick) {
            cancel(this);
        }

        private native void cancel(Read read)/*-{
      read.abort();
        }-*/;
    }

    @Override
    final void onBlock(URI uri, long tick, Buff[] buffs, long[] removals, boolean requested) {
        cache().queue().enqueueBlock(uri, tick, buffs, removals, requested);
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy