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
|
/* ConcurrentLogging.java -- Test Concurrent access to Logger
Copyright (C) 2008 Mario Torre <neugens@limasoftware.net>
This file is part of Mauve.
Mauve is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
Mauve 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 for more details.
You should have received a copy of the GNU General Public License
along with Mauve; see the file COPYING. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
*/
// Tags: JDK1.4
package gnu.testlet.java.util.logging.Logger;
import java.util.logging.Handler;
import java.util.logging.Level;
import java.util.logging.LogRecord;
import java.util.logging.Logger;
import gnu.testlet.TestHarness;
import gnu.testlet.Testlet;
/**
* Fix PR35974, when multiple threads try to access methods or Logger.
*
* @author Mario Torre <neugens@limasoftware.net>
*/
public class PR35974
implements Testlet
{
private static final boolean DEBUG = false;
private static Logger parentLogger =
Logger.getLogger("new caprica event logger");
private TestHarness harness = null;
static volatile boolean fighting = true;
public void test(TestHarness harness)
{
this.harness = harness;
HarnessHandler handler = new HarnessHandler();
LoggerThread galactica = new LoggerThread("Galactica", handler);
LoggerThread cylonBasestar1 =
new LoggerThread("Cylon Basestar #1", handler);
LoggerThread cylonBasestar2 =
new LoggerThread("Cylon Basestar #2", handler);
LoggerThread cylonBasestar3 =
new LoggerThread("Cylon Basestar #3", handler);
galactica.start();
cylonBasestar1.start();
cylonBasestar2.start();
cylonBasestar3.start();
BattlestarPegasusThread pegasus = new BattlestarPegasusThread();
pegasus.start();
}
private class HarnessHandler extends Handler
{
public void close() throws SecurityException
{
/* does nothing */
}
@Override
public void flush()
{
/* does nothing */
}
public void success()
{
harness.check(true, Thread.currentThread().getName());
}
@Override
public void publish(LogRecord record)
{
if (DEBUG == false)
return;
// this is not correct in real world code, but it's ok for our
// simple test
if (Thread.currentThread().getName().equalsIgnoreCase("Galactica"))
harness.debug(record.getMessage() + "--------------------------->");
else
harness.debug("\t\t\t\t\t\t\t\t\t\t\t\t\t<---------------------------"
+ record.getMessage());
}
}
private static class BattlestarPegasusThread extends Thread
{
private long startTime = System.currentTimeMillis();
public BattlestarPegasusThread()
{
super("Pegasus to the rescue...");
}
@Override
public void run()
{
parentLogger.log(Level.INFO, this.getName());
long stopTime = System.currentTimeMillis();
while ((stopTime - startTime) < 30000)
{
stopTime = System.currentTimeMillis();
}
fighting = false;
parentLogger.log(Level.INFO, "Pegasus destroyed...");
}
}
private static class LoggerThread extends Thread
{
private static Logger brokenLogger = null;
private HarnessHandler handler = null;
public LoggerThread(String name, HarnessHandler handler)
{
super(name);
super.setDaemon(true);
this.handler = handler;
}
@Override
public void run()
{
parentLogger.log(Level.INFO, this.getName() +
" did the jump into new caprica orbit ");
while (fighting)
{
// These methods are all synchronized in the implementation.
// Of course, you see the problem, there is no synchronization
// between the first instruction and the others, and you can see
// this because some output from the logger is still left on even when
// we setLevel(Level.OFF), this is because of some concurrent access,
// but it's ok, because what we do here is to force a concurrent
// access somehow hoping for a deadlock at some point, which will
// not happen because the locking system on the Logger class has been
// improved, but still will left our brokenLogger in a somewhat
// confused state (that is, it works only because handler and
// parentLogger are always the same, otherwise it would not work)
// This code is broken by design, so don't try to imitate this style
// in real word code, please.
brokenLogger = Logger.getLogger(this.getName());
if (DEBUG == false)
brokenLogger.setLevel(Level.OFF);
else
brokenLogger.setParent(parentLogger);
brokenLogger.addHandler(handler);
brokenLogger.log(Level.INFO, this.getName() + " fires");
}
parentLogger.log(Level.INFO, this.getName() + " jumps");
handler.success();
}
}
}
|