@Override
    protected void setRootAsync(Object value, FutureWithCallback<Void> future) {
        if (value instanceof UserTObject && ((UserTObject) value).getTrunk().getStore() != BinaryStore.this)
            future.setException(new RuntimeException(Strings.WRONG_STORE));
        else {
            byte[] data = writeObject(value);
            long id = _jdbm.getRoot(ROOT);

            if (id != 0)
                _jdbm.update(id, data);
            else {
                id = _jdbm.insert(data);
                _jdbm.setRoot(ROOT, id);
            }

            future.set(null);
        }
    }
    @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();
    }