1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197
|
/*
* 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);
}
}
|