blob: 551e98557d0041f49419c081c1f4fe38b51473c7 [file] [log] [blame]
J. Duke319a3b92007-12-01 00:00:00 +00001/*
2 * Copyright 2005 Sun Microsystems, Inc. All Rights Reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.
8 *
9 * This code is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12 * version 2 for more details (a copy is included in the LICENSE file that
13 * accompanied this code).
14 *
15 * You should have received a copy of the GNU General Public License version
16 * 2 along with this work; if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
20 * CA 95054 USA or visit www.sun.com if you need additional information or
21 * have any questions.
22 */
23
24/*
25 * @test
26 * @bug 4652922
27 *
28 * @summary synopsis: ReliableLog.update should pad records to 4-byte
29 * boundaries
30 * @author Ann Wollrath
31 *
32 * @build LogTest
33 * @run main/othervm/timeout=240 LogTest
34 */
35
36import sun.rmi.log.LogHandler;
37import sun.rmi.log.ReliableLog;
38import java.io.FileDescriptor;
39import java.io.FileNotFoundException;
40import java.io.IOException;
41import java.io.Serializable;
42
43public class LogTest {
44
45 private static int crashPoint = 0;
46 private static boolean spansBoundary = false;
47 private static ReliableLog log = null;
48 private static Counter counter = new Counter();
49
50 public static void main(String[] args) throws Exception {
51
52 System.err.println("\nRegression test for bug 4652922\n");
53
54 System.setProperty("sun.rmi.log.class", MyLogFile.class.getName());
55 //System.setProperty("sun.rmi.log.debug", "true");
56
57 log = new ReliableLog(".", new TestLogHandler(counter), false);
58
59 writeUpdatesCrashAndRecover(10, 1, false, 10);
60 writeUpdatesCrashAndRecover(10, 1, true, 20);
61 writeUpdatesCrashAndRecover(10, 2, true, 30);
62 writeUpdatesCrashAndRecover(9, 2, false, 40);
63 writeUpdatesCrashAndRecover(9, 3, true, 50);
64 log.close();
65 }
66
67 private static void writeUpdatesCrashAndRecover(int updates,
68 int crashValue,
69 boolean spans,
70 int expectedCount)
71 throws IOException
72 {
73 /*
74 * Write updates
75 */
76 System.err.println("\nwrite updates: " + updates);
77 for (int i = 0; i < updates; i++) {
78 counter.increment();
79 log.update(counter);
80 }
81
82 /*
83 * Crash
84 */
85 crashPoint = crashValue;
86 spansBoundary = spans;
87 System.err.println("crash during next update on sync #" +
88 crashPoint +
89 " (spansBoundary = " + spansBoundary + ")");
90 try {
91 System.err.println(
92 "write one update (update record should " +
93 ((counter.value() + 1 == expectedCount) ? "" : "not ") +
94 "be complete)");
95 counter.increment();
96 log.update(counter);
97 throw new RuntimeException("failed to reach crashpoint " +
98 crashPoint);
99 } catch (IOException e) {
100 System.err.println("caught IOException; message: " +
101 e.getMessage());
102 log.close();
103 }
104
105 /*
106 * Recover
107 */
108 log = new ReliableLog(".", new TestLogHandler(null), false);
109 try {
110 System.err.println("recover log");
111 counter = (Counter) log.recover();
112 System.err.println("recovered counter value: " + counter.value());
113 if (counter.value() != expectedCount) {
114 throw new RuntimeException("unexpected counter value " +
115 counter.value());
116 }
117 System.err.println("log recovery successful");
118
119 } catch (IOException e) {
120 System.err.println("log should recover after crash point");
121 e.printStackTrace();
122 throw new RuntimeException(
123 "log should recover after crash point");
124 }
125
126 }
127
128 private static class Counter implements Serializable {
129 private static long serialVersionUID = 1;
130 private int count = 0;
131
132 Counter() {}
133
134 int increment() {
135 return ++count;
136 }
137
138 int value() {
139 return count;
140 }
141
142 void update(Counter value) {
143 if (value.value() < count) {
144 throw new IllegalStateException(
145 "bad update (count = " + count + ", value = " + value + ")");
146 } else {
147 count = value.value();
148 }
149 }
150 }
151
152 static class TestLogHandler extends LogHandler {
153
154 private final Counter initialState;
155
156 TestLogHandler(Counter initialState) {
157 this.initialState = initialState;
158 }
159
160 public Object initialSnapshot() {
161 if (initialState == null) {
162 throw new IllegalStateException(
163 "attempting initialSnapshot with null");
164 }
165 return initialState;
166 }
167
168 public Object applyUpdate(Object update, Object state) {
169 ((Counter) state).update((Counter) update);
170 return state;
171 }
172 }
173
174 public static class MyLogFile extends ReliableLog.LogFile {
175
176 public MyLogFile(String name, String mode)
177 throws FileNotFoundException, IOException
178 {
179 super(name, mode);
180 }
181
182 protected void sync() throws IOException {
183 if (crashPoint != 0) {
184 if (--crashPoint == 0) {
185 throw new IOException("crash point reached");
186 }
187 }
188 super.sync();
189 }
190
191 protected boolean checkSpansBoundary(long fp) {
192 return
193 crashPoint > 0 ? spansBoundary : super.checkSpansBoundary(fp);
194 }
195 }
196}