001 /* 002 Copyright (C) 2001-2002 Renaud Pawlak <renaud@aopsys.com> 003 004 This program is free software; you can redistribute it and/or modify 005 it under the terms of the GNU Lesser General Public License as 006 published by the Free Software Foundation; either version 2 of the 007 License, or (at your option) any later version. 008 009 This program is distributed in the hope that it will be useful, 010 but WITHOUT ANY WARRANTY; without even the implied warranty of 011 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 012 GNU Lesser General Public License for more details. 013 014 You should have received a copy of the GNU Lesser General Public License 015 along with this program; if not, write to the Free Software 016 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ 017 018 package org.objectweb.jac.aspects.distribution; 019 020 021 import java.util.*; 022 import org.aopalliance.intercept.ConstructorInvocation; 023 import org.aopalliance.intercept.MethodInvocation; 024 import org.apache.log4j.Logger; 025 import org.objectweb.jac.core.*; 026 import org.objectweb.jac.core.dist.*; 027 import org.objectweb.jac.util.Log; 028 029 /** 030 * This Aspect Component allows the programmer to easily implement 031 * load-balancing features for its application when JAC is running in 032 * distributed mode. 033 * 034 * @see LoadBalancingConf 035 * @author Renaud Pawlak 036 */ 037 038 public class LoadBalancingAC 039 extends AspectComponent 040 implements LoadBalancingConf 041 { 042 static Logger logger = Logger.getLogger("loadbalancing"); 043 044 public void addRoundTripLoadBalancer( 045 String wrappeeName, 046 String methods, 047 String hostName, 048 String replicaExpr) { 049 050 pointcut( 051 wrappeeName, 052 ".*", 053 methods + " && !CONSTRUCTORS && !STATICS", 054 new LoadBalancingWrapper(this, replicaExpr), 055 hostName, 056 null); 057 } 058 059 public void addRandomLoadBalancer( 060 String wrappeeName, 061 String methods, 062 String hostName, 063 String replicaExpr) { 064 065 pointcut( 066 wrappeeName, 067 ".*", 068 methods + " && !CONSTRUCTORS && !STATICS", 069 new LoadBalancingWrapper(this, replicaExpr), 070 hostName, 071 null); 072 } 073 074 /** 075 * This inner-wrapper handles the load-balancing wrapping methods that 076 * actually implement the load-balancing algorithms. */ 077 078 public class LoadBalancingWrapper extends Wrapper { 079 080 int count = 0; 081 Vector replicas = null; 082 Random random = new Random(); 083 String hostExpr; 084 boolean doFill = true; 085 086 public LoadBalancingWrapper(AspectComponent ac, String hostExpr) { 087 super(ac); 088 this.hostExpr = hostExpr; 089 } 090 091 public void invalidate() { 092 doFill = true; 093 } 094 095 public Object invoke(MethodInvocation invocation) throws Throwable { 096 return roundTripBalance((Interaction) invocation); 097 } 098 099 public Object construct(ConstructorInvocation invocation) 100 throws Throwable { 101 throw new Exception("This wrapper does not support constructor wrapping"); 102 } 103 104 /** 105 * Performs a round-trip load-balancing. */ 106 107 public Object roundTripBalance(Interaction interaction) { 108 if (doFill) { 109 replicas = 110 Topology.getPartialTopology(hostExpr).getReplicas( 111 interaction.wrappee); 112 logger.debug("filled partial topo with "+ hostExpr 113 + " on "+ Topology.get() + ": " + replicas); 114 doFill = false; 115 } 116 if (replicas.size() == 0) { 117 // none replicas where found, we perform a local call and 118 // will try to get them again on the next call 119 doFill = true; 120 logger.warn( 121 "load-balancing: no replica found, on " 122 + interaction.wrappee + ": local call performed"); 123 return proceed(interaction); 124 } 125 if (count >= replicas.size()) { 126 count = 0; 127 } 128 return ((RemoteRef) replicas.get(count++)).invoke( 129 interaction.method.getName(), 130 interaction.args); 131 } 132 133 /** 134 * Performs a random load-balancing. */ 135 136 public Object randomBalance(Interaction interaction) { 137 if (doFill) { 138 replicas = 139 Topology.getPartialTopology(hostExpr).getReplicas( 140 interaction.wrappee); 141 doFill = false; 142 } 143 if (replicas.size() == 0) { 144 // none replicas where found, we perform a local call and 145 // will try to get them again on the next call 146 doFill = true; 147 logger.warn("load-balancing: no replica found, local call performed"); 148 return proceed(interaction); 149 } 150 return ( 151 (RemoteRef) replicas.get( 152 random.nextInt(replicas.size()))).invoke( 153 interaction.method.getName(), 154 interaction.args); 155 } 156 } 157 158 }