001: /*
002: * HA-JDBC: High-Availability JDBC
003: * Copyright (c) 2004-2007 Paul Ferraro
004: *
005: * This library is free software; you can redistribute it and/or modify it
006: * under the terms of the GNU Lesser General Public License as published by the
007: * Free Software Foundation; either version 2.1 of the License, or (at your
008: * option) any later version.
009: *
010: * This library is distributed in the hope that it will be useful, but WITHOUT
011: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
012: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
013: * for more details.
014: *
015: * You should have received a copy of the GNU Lesser General Public License
016: * along with this library; if not, write to the Free Software Foundation,
017: * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
018: *
019: * Contact: ferraro@users.sourceforge.net
020: */
021: package net.sf.hajdbc.balancer;
022:
023: import net.sf.hajdbc.Balancer;
024: import net.sf.hajdbc.Database;
025: import net.sf.hajdbc.MockDatabase;
026: import net.sf.hajdbc.sql.Invoker;
027:
028: import org.testng.annotations.Test;
029:
030: /**
031: * @author Paul Ferraro
032: * @version $Revision: 2016 $
033: * @since 1.0
034: */
035: @Test
036: @SuppressWarnings("nls")
037: public class TestLoadBalancer extends AbstractTestBalancer {
038: /**
039: * @see net.sf.hajdbc.balancer.AbstractTestBalancer#createBalancer()
040: */
041: @Override
042: protected Balancer<Void> createBalancer() {
043: return new LoadBalancer<Void>();
044: }
045:
046: /**
047: * @see net.sf.hajdbc.balancer.AbstractTestBalancer#next(net.sf.hajdbc.Balancer)
048: */
049: @Override
050: protected void next(Balancer<Void> balancer) {
051: Database<Void> database0 = new MockDatabase("0", 0);
052: Database<Void> database1 = new MockDatabase("1", 1);
053: Database<Void> database2 = new MockDatabase("2", 2);
054:
055: balancer.add(database0);
056:
057: Database<Void> next = balancer.next();
058:
059: assert database0.equals(next) : next;
060:
061: balancer.add(database2);
062:
063: next = balancer.next();
064:
065: assert database2.equals(next) : next;
066:
067: balancer.add(database1);
068:
069: next = balancer.next();
070:
071: assert database2.equals(next) : next;
072:
073: // Add enough load to database2 to shift relative effective load
074: Thread[] database2Threads = new Thread[2];
075: for (int i = 0; i < 2; ++i) {
076: database2Threads[i] = new InvokerThread(balancer,
077: new MockInvoker(), database2);
078: database2Threads[i].start();
079: }
080:
081: next = balancer.next();
082:
083: assert database1.equals(next) : next;
084:
085: // Add enough load to database1 to shift relative effective load
086: Thread database1Thread = new InvokerThread(balancer,
087: new MockInvoker(), database1);
088: database1Thread.start();
089:
090: next = balancer.next();
091:
092: assert database2.equals(next) : next;
093:
094: database1Thread.interrupt();
095:
096: next = balancer.next();
097:
098: assert database1.equals(next) : next;
099:
100: for (int i = 0; i < 2; ++i) {
101: database2Threads[i].interrupt();
102: }
103:
104: next = balancer.next();
105:
106: assert database2.equals(next) : next;
107: }
108:
109: private static class InvokerThread extends Thread {
110: private Balancer<Void> balancer;
111: private Invoker<Void, Void, Void> invoker;
112: private Database<Void> database;
113:
114: /**
115: * Constructs a new InvokerThread.
116: * @param balancer
117: * @param invoker
118: * @param database
119: */
120: public InvokerThread(Balancer<Void> balancer,
121: Invoker<Void, Void, Void> invoker,
122: Database<Void> database) {
123: super ();
124:
125: this .balancer = balancer;
126: this .invoker = invoker;
127: this .database = database;
128:
129: this .setDaemon(true);
130: }
131:
132: /**
133: * @see java.lang.Runnable#run()
134: */
135: @Override
136: public void run() {
137: this .balancer.beforeInvocation(this .database);
138:
139: try {
140: this .invoker.invoke(this .database, null);
141:
142: this .balancer.afterInvocation(this .database);
143: } catch (Exception e) {
144: assert false : e;
145: }
146: }
147:
148: /**
149: * @see java.lang.Thread#start()
150: */
151: @Override
152: public synchronized void start() {
153: super .start();
154:
155: this .pause();
156: }
157:
158: /**
159: * @see java.lang.Thread#interrupt()
160: */
161: @Override
162: public void interrupt() {
163: super .interrupt();
164:
165: this .pause();
166: }
167:
168: private void pause() {
169: try {
170: Thread.sleep(10);
171: } catch (InterruptedException e) {
172: assert false : e;
173: }
174: }
175: }
176:
177: static class MockInvoker implements Invoker<Void, Void, Void> {
178: @Override
179: public Void invoke(Database<Void> database, Void object) {
180: // Simulate a long operation
181: try {
182: Thread.sleep(10000);
183: } catch (InterruptedException e) {
184: // Ignore
185: }
186:
187: return null;
188: }
189: }
190: }
|