alvinalexander.com | career | drupal | java | mac | mysql | perl | scala | uml | unix  

Java example source code file (RetryDirtyCalls.java)

This example Java source code file (RetryDirtyCalls.java) is included in the alvinalexander.com "Java Source Code Warehouse" project. The intent of this project is to help you "Learn Java by Example" TM.

Learn more about this Java project at its project page.

Java - Java tags/keywords

failed, flake_factor, ioexception, net, network, passed, remote, remoteexception, retrydirtycalls, rmi, rmisocketfactory, runtimeexception, self, serversocket, testsf, timeout, unreferenced

The RetryDirtyCalls.java Java example source code

/*
 * Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */

/* @test
 * @bug 4268258
 * @summary When a DGC dirty call fails, RMI's client-side DGC implementation
 * should attempt to retry the same dirty call a few times, at least until the
 * known lease for that endpoint has expired, instead of just giving up
 * renewing that lease at all after the first failure.
 * @author Peter Jones (inspired by Adrian Colley's test case in 4268258)
 *
 * @build RetryDirtyCalls RetryDirtyCalls_Stub
 * @run main/othervm RetryDirtyCalls
 */

import java.io.*;
import java.net.*;
import java.rmi.*;
import java.rmi.server.*;

interface Self extends Remote {
    Self getSelf() throws RemoteException;
}

public class RetryDirtyCalls implements Self, Unreferenced {

    /** how long we wait before declaring that this test has passed */
    private final static long TIMEOUT = 20000;

    /** true if this object's unreferenced method has been called */
    private boolean unreferenced = false;

    /**
     * Return this object.  The need for this method is explained below.
     */
    public Self getSelf() {
        return this;
    }

    public void unreferenced() {
        synchronized (this) {
            unreferenced = true;
            notifyAll();
        }
    }

    public static void main(String[] args) {

        System.err.println("\nRegression test for bug 4268258\n");

        /*
         * Set properties to tweak DGC behavior so that this test will execute
         * quickly: set the granted lease duration to 10 seconds, the interval
         * that leases are checked to 3 seconds.
         */
        System.setProperty("java.rmi.dgc.leaseValue", "10000");
        System.setProperty("sun.rmi.dgc.checkInterval", "3000");

        /*
         * Make idle connections time out almost instantly (0.1 seconds) so
         * that the DGC implementation will have to make a new connection for
         * each dirty call, thus going through the socket factory, where we
         * can easily cause the operation to fail.
         */
        System.setProperty("sun.rmi.transport.connectionTimeout", "100");

        RetryDirtyCalls impl = new RetryDirtyCalls();

        try {
            TestSF sf = new TestSF();
            RMISocketFactory.setSocketFactory(sf);

            /*
             * The stub returned by UnicastRemoteObject.exportObject() does
             * not participate in DGC, but it does allow us to invoke a method
             * on the remote object through RMI.  Therefore, we invoke the
             * getSelf() method through RMI, which returns an equivalent stub
             * that does participate in DGC.
             */
            Self stub = (Self) UnicastRemoteObject.exportObject(impl);
            Self dgcStub = stub.getSelf();
            stub = null;                // in case 4114579 has been fixed

            /*
             * Set the socket factory to cause 3 connections attempts in a row
             * to fail before allowing a connection to succeed, expecting the
             * client-side DGC implementation to make at least four attempts.
             */
            final int FLAKE_FACTOR = 3;
            sf.setFlakeFactor(FLAKE_FACTOR);

            long deadline = System.currentTimeMillis() + TIMEOUT;
            boolean unreferenced;

            synchronized (impl) {
                while (!(unreferenced = impl.unreferenced)) {
                    long timeToWait = deadline - System.currentTimeMillis();
                    if (timeToWait > 0) {
                        impl.wait(timeToWait);
                    } else {
                        break;
                    }
                }
            }

            if (unreferenced) {
                throw new RuntimeException("remote object unreferenced");
            }

            int createCount = sf.getCreateCount();
            if (createCount == 0) {
                throw new RuntimeException("test socket factory never used");
            } else if (createCount < (FLAKE_FACTOR + 3)) {
                /*
                 * The unreferenced method was not invoked for some reason,
                 * but the dirty calls were clearly not retried well enough.
                 */
                throw new RuntimeException(
                    "test failed because dirty calls not retried enough, " +
                    "but remote object not unreferenced");
            }

            System.err.println(
                "TEST PASSED: remote object not unreferenced");

        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException("TEST FAILED: " + e.toString());
        } finally {
            /*
             * When all is said and done, try to unexport the remote object
             * so that the VM has a chance to exit.
             */
            try {
                UnicastRemoteObject.unexportObject(impl, true);
            } catch (Exception e) {
            }
        }
    }
}

class TestSF extends RMISocketFactory {

    private int flakeFactor = 0;

    private int flakeState = 0;

    private int createCount = 0;

    public synchronized void setFlakeFactor(int newFlakeFactor) {
        flakeFactor = newFlakeFactor;
    }

    public synchronized int getCreateCount() {
        return createCount;
    }

    public synchronized Socket createSocket(String host, int port)
        throws IOException
    {
        createCount++;

        if (++flakeState > flakeFactor) {
            flakeState = 0;
        }

        if (flakeState == 0) {
            return new Socket(host, port);
        } else {
            throw new IOException("random network failure");
        }
    }

    public ServerSocket createServerSocket(int port) throws IOException {
        return new ServerSocket(port);
    }
}

Other Java examples (source code examples)

Here is a short list of links related to this Java RetryDirtyCalls.java source code file:

... this post is sponsored by my books ...

#1 New Release!

FP Best Seller

 

new blog posts

 

Copyright 1998-2021 Alvin Alexander, alvinalexander.com
All Rights Reserved.

A percentage of advertising revenue from
pages under the /java/jwarehouse URI on this website is
paid back to open source projects.