@SuppressWarnings("unchecked")
    @Override
    protected void getAsync(UserTObject object, Object key, FutureWithCallback<Object> future) {
        if (object.getSharedVersion_objectfabric().getUnion() instanceof Record) {
            long record = getOrFetchRecord(object.getSharedVersion_objectfabric());

            if (Record.isStored(record)) {
                BTree tree = BTree.load(getRecordManager(), record, false);
                _writer.write(key);
                byte[] data = new byte[_writer.getOffset()];
                PlatformAdapter.arraycopy(_writer.getBuffer(), 0, data, 0, data.length);
                long id = tree.fetch(data);

                if (id != 0) {
                    data = getRecordManager().fetch(id);
                    Object value = _reader.read(data);

                    _reader.readVersions();

                    Version version = _reader.getOrCreateVersion(object);
                    TKeyedEntry entry = new TKeyedEntry(key, TKeyed.hash(key), value, false);

                    if (Debug.ENABLED)
                        Debug.assertion(value != TKeyedEntry.REMOVAL);

                    ((LazyMapVersion) version).putEntry(key, entry, true, true);
                    _reader.importVersions();
                    future.set(value);
                    return;
                }
            }
        }

        future.set(null);
    }
    @Override
    protected void fetchAsync(List<byte[]> refs, AsyncCallback<Object[]> objects) {
        Object[] result = new Object[refs.size()];

        for (int i = 0; i < result.length; i++) {
            result[i] = _reader.read(refs.get(i));
            _reader.readVersions();
            _reader.importVersions();
        }

        objects.onSuccess(result);
    }
    @Override
    protected void getRootAsync(FutureWithCallback<Object> future) {
        long rootId = _jdbm.getRoot(ROOT);
        byte[] data = null;

        if (rootId == 0)
            future.set(null);
        else {
            data = _jdbm.fetch(rootId);

            if (data == null)
                throw new RuntimeIOException(Strings.CORRUPTED_STORE);

            Object root = _reader.read(data);

            _reader.readVersions();
            _reader.importVersions();
            future.set(root);
        }
    }
    public final void start() {
        onStarting();

        long sessionsId = _jdbm.getRoot(SESSIONS);

        if (sessionsId != 0) {
            _sessions = BTree.load(_jdbm, sessionsId, true);

            if (_sessions == null)
                throw new RuntimeIOException(Strings.CORRUPTED_STORE);
        } else {
            _sessions = new BTree(_jdbm, true);
            _jdbm.setRoot(SESSIONS, _sessions.getId());
        }

        if (Debug.THREADS) {
            ThreadAssert.exchangeGive(this, _sessions);
            ThreadAssert.exchangeGiveList(this, _reader.getThreadContextObjects());
            ThreadAssert.exchangeGiveList(this, _writer.getThreadContextObjects());
            ThreadAssert.exchangeGive(this, this);
        }

        onStarted();
    }