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

org.objectfabric.Multi Maven / Gradle / Ivy

There is a newer version: 0.9.1
Show 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 java.util.concurrent.CyclicBarrier;
import java.util.concurrent.atomic.AtomicInteger;

import org.junit.Ignore;
import org.junit.Test;
import org.objectfabric.Workspace.Granularity;
import org.objectfabric.generated.LimitN;

@Ignore
public class Multi extends TestsHelper {

    private int todo;

    public static final int DEFAULT_WRITE_COUNT = Debug.ENABLED ? 10 : 1000;

    public static final int FLAG_USE_ABORTS = 1 << 0;

    public static final int FLAG_NO_WRITE = 1 << 1;

    public static final int FLAG_RESETS = 1 << 2;

    public static final int MAX_FLAG = 2;

    public static final int ALL_FLAGS = (1 << (MAX_FLAG + 1)) - 1;

    @Test
    public void runSimple1() {
        run(null, 1, DEFAULT_WRITE_COUNT, 0);
    }

    @Test
    public void runSimple2() {
        run(null, 2, DEFAULT_WRITE_COUNT, 0);
    }

    @Test
    public void runSimple3() {
        run(null, 1, DEFAULT_WRITE_COUNT, FLAG_USE_ABORTS);
    }

    @Test
    public void runSimple4() {
        run(null, 2, DEFAULT_WRITE_COUNT, FLAG_USE_ABORTS);
    }

    @Test
    public void runSimple5() {
        run(null, 1, DEFAULT_WRITE_COUNT, FLAG_RESETS);
    }

    @Test
    public void runSimple6() {
        run(null, 2, DEFAULT_WRITE_COUNT, FLAG_RESETS);
    }

    @Test
    public void runCoalesce1() {
        run(Granularity.COALESCE, 1, DEFAULT_WRITE_COUNT, 0);
    }

    @Test
    public void runCoalesce2() {
        run(Granularity.COALESCE, 1, DEFAULT_WRITE_COUNT, FLAG_USE_ABORTS);
    }

    @Test
    public void runCoalesce3() {
        run(Granularity.COALESCE, 2, DEFAULT_WRITE_COUNT, 0);
    }

    @Test
    public void runCoalesce4() {
        run(Granularity.COALESCE, 2, DEFAULT_WRITE_COUNT, FLAG_USE_ABORTS);
    }

    @Test
    public void runCoalesce5() {
        run(Granularity.COALESCE, 2, DEFAULT_WRITE_COUNT, FLAG_RESETS);
    }

    Resource getResource(Workspace workspace) {
        return workspace.resolve("");
    }

    public void run(final Granularity granularity, final int writers, final int writeCount, final int flags) {
        final Workspace workspace = Platform.get().newTestWorkspace(granularity);
        Resource resource = getResource(workspace);
        final All all = new All(resource, writers, flags);

        System.out.println();
        String message = "Starting " + writers + " threads, " + writeCount + " writes, " + "listener: " + granularity + ", ";
        message += "client flags: " + writeFlags(flags);
        System.out.println(message);

        final ArrayList threads = new ArrayList();
        final CyclicBarrier barrier = new CyclicBarrier(writers + 1);
        final AtomicInteger commitCount = new AtomicInteger();
        final AtomicInteger attemptCount = new AtomicInteger();
        final AtomicInteger abortCount = new AtomicInteger();
        final AtomicInteger totalDeltas = new AtomicInteger();

        for (int t = 0; t < writers; t++) {
            Thread thread = new Thread("Thread " + t) {

                @Override
                public void run() {
                    try {
                        barrier.await();
                    } catch (Exception e) {
                        throw new RuntimeException(e);
                    }

                    for (int i = 0; i < writeCount; i++) {
                        final AtomicInteger delta = new AtomicInteger();

                        try {
                            workspace.atomic(new Runnable() {

                                @Override
                                public void run() {
                                    All.check(all.Root, flags);

                                    if ((flags & FLAG_NO_WRITE) == 0)
                                        delta.set(All.update(all.Root, flags));
                                    else
                                        delta.set(0);

                                    if ((flags & FLAG_USE_ABORTS) != 0 && Platform.get().randomBoolean()) {
                                        abortCount.incrementAndGet();
                                        ExpectedExceptionThrower.throwAbortException();
                                    }

                                    attemptCount.incrementAndGet();
                                }
                            });

                            commitCount.incrementAndGet();
                            totalDeltas.addAndGet(delta.get());
                        } catch (AbortException ex) {
                            // Ignore, for aborts
                        }
                    }
                }
            };

            threads.add(thread);
            thread.start();
        }

        try {
            barrier.await();
        } catch (Exception e) {
            throw new RuntimeException(e);
        }

        for (Thread thread : threads) {
            try {
                thread.join();
            } catch (java.lang.InterruptedException e) {
            }
        }

        All.check(all.Root, flags);
        workspace.flushNotifications();
        LimitN limitN = (LimitN) all.Root.get("" + 0);
        int total = 0;

        for (int i = 0; i < limitN.getFieldCount(); i++)
            total += (Integer) limitN.getField(i);

        workspace.close();

        if (writers == 1)
            if ((flags & FLAG_USE_ABORTS) == 0)
                Debug.assertAlways(commitCount.get() == writeCount * writers);

        Debug.assertAlways(attemptCount.get() <= writeCount * writers * writers);

        if ((flags & FLAG_NO_WRITE) != 0)
            Debug.assertAlways(total == 0);
        else {
            Debug.assertAlways(total == totalDeltas.get());

            if (Stats.ENABLED) {
                long committed = Stats.Instance.Committed.get();
                long retries = Stats.Instance.TransactionRetries.get();
                Debug.assertAlways(committed == limitN.getFieldCount() + commitCount.get());
                Debug.assertAlways(committed + retries == limitN.getFieldCount() + attemptCount.get());
                Debug.assertAlways(Stats.Instance.ValidationRetriesMax.get() <= writers);
                Debug.assertAlways(writers * writeCount - abortCount.get() == commitCount.get());
            }
        }
    }

    public static String writeFlags(int flags) {
        StringBuilder sb = new StringBuilder();

        if ((flags & FLAG_USE_ABORTS) != 0)
            sb.append("USE_ABORTS, ");

        if ((flags & FLAG_NO_WRITE) != 0)
            sb.append("NO_WRITE, ");

        if ((flags & FLAG_RESETS) != 0)
            sb.append("RESETS, ");

        return sb.toString();
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy