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

org.objectfabric.Clock 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 org.objectfabric.Range.Id;
import org.objectfabric.Range.Ref;
import org.objectfabric.Resource.NewBlock;
import org.objectfabric.TObject.Version;
import org.objectfabric.ThreadAssert.AllowSharedRead;
import org.objectfabric.ThreadAssert.SingleThreaded;

/**
 * Generates vector clock ids.
 */
@SingleThreaded
class Clock {

    @AllowSharedRead
    private final Watcher _watcher;

    private final List _blocks = new List();

    private Peer _peer;

    private long _time;

    private long _object;

    //

    private boolean _tickUsed;

    private Range _range;

    Clock(Watcher watcher) {
        _watcher = watcher;
    }

    final Watcher watcher() {
        return _watcher;
    }

    final List blocks() {
        return _blocks;
    }

    final Peer peer() {
        return _peer;
    }

    final long time() {
        return _time;
    }

    final long object() {
        return _object;
    }

    final void start() {
        if (peer() != null)
            _time = time(_time, _tickUsed);
    }

    static long time(long last, boolean used) {
        // In case machine clock moved back or writing too fast (TODO avoid drift)
        long min = used ? last + 1 : last;

        // 1/125s since 1970, stored on 5 bytes -> good until 2248
        long time = System.currentTimeMillis() / 8;

        if (time < min)
            time = min;

        return time;
    }

    void writing(Resources resources) {
    }

    final void init(Peer peer, long time, long object) {
        _peer = peer;
        _time = time;
        _object = object;
        _tickUsed = false;
    }

    final void onBlock(Resource resource, Version[] versions) {
        _blocks.add(resource.writeNewBlock(Tick.get(_peer.index(), _time), versions));
        _tickUsed = true;
    }

    void commit() {
        while (_blocks.size() > 0) {
            NewBlock block = _blocks.removeLast();
            publish(block.Resource, block.Tick, block.Buffs, block.Removals, null);
        }
    }

    static final void publish(Resource resource, long tick, Buff[] buffs, long[] removals, Location cache) {
        Object key;

        if (Debug.THREADS) {
            for (int i = 0; i < buffs.length; i++)
                ThreadAssert.exchangeGive(buffs, buffs[i]);

            ThreadAssert.suspend(key = new Object());
        }

        Exception exception = resource.uri().onBlock(resource, tick, buffs, removals, false, null, true, cache);

        if (Debug.THREADS) {
            ThreadAssert.resume(key);
            ThreadAssert.exchangeTake(buffs);
        }

        if (Debug.ENABLED)
            Debug.assertion(exception == null);
    }

    //

    final void assignId(TObject object) {
        long range = ++_object >>> Range.SHIFT;

        if (_range == null || range != _range.id().Value) {
            Id id = new Id(_peer, range);
            _range = _watcher.workspace().getOrCreateRange(id);
        }

        object.range(_range);
        object.id((int) _object & 0xff);
        _range.set(object.id(), new Ref(object));
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy