1a473a7c04ea3de5f3255c2cbfabde33748db2d1
[controller.git] / opendaylight / samples / loadbalancer / src / main / java / org / opendaylight / controller / samples / loadbalancer / policies / RoundRobinLBPolicy.java
1 /*
2  * Copyright IBM Corporation, 2013.  All rights reserved.
3  *
4  * This program and the accompanying materials are made available under the
5  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6  * and is available at http://www.eclipse.org/legal/epl-v10.html
7  */
8 package org.opendaylight.controller.samples.loadbalancer.policies;
9
10 import java.util.ArrayList;
11 import java.util.HashMap;
12
13 import org.opendaylight.controller.samples.loadbalancer.ConfigManager;
14 import org.opendaylight.controller.samples.loadbalancer.entities.Client;
15 import org.opendaylight.controller.samples.loadbalancer.entities.Pool;
16 import org.opendaylight.controller.samples.loadbalancer.entities.PoolMember;
17 import org.opendaylight.controller.samples.loadbalancer.entities.VIP;
18 import org.slf4j.Logger;
19 import org.slf4j.LoggerFactory;
20
21 /**
22  * This class implements the round robin load balancing policy.
23  *
24  */
25 public class RoundRobinLBPolicy implements ILoadBalancingPolicy{
26
27     /*
28      * Logger instance
29      */
30     private static final Logger rrLogger = LoggerFactory.getLogger(RoundRobinLBPolicy.class);
31
32     /*
33      * Reference to the configuration manager. This reference is passed from load balancer
34      * class.
35      */
36     private ConfigManager cmgr;
37
38     /*
39      * Mapping between the client and the pool member that serves all traffic for that client.
40      */
41     private HashMap<Client, PoolMember> clientMemberMap;
42
43     /*
44      * Maintains the next pool member counter for the VIPs.
45      * More than one VIP can be attached to one pool, so each VIP
46      * will have its own counter for the next pool member from
47      * the same pool.
48      */
49     private HashMap<VIP,Integer> nextItemFromPool;
50
51     @SuppressWarnings("unused")
52     private RoundRobinLBPolicy(){}
53
54     public RoundRobinLBPolicy(ConfigManager cmgr){
55         this.cmgr = cmgr;
56         this.clientMemberMap = new HashMap<Client, PoolMember>();
57         this.nextItemFromPool = new HashMap<VIP, Integer>();
58     }
59
60     @Override
61     public String getPoolMemberForClient(Client source, VIP dest){
62
63         rrLogger.info("Received traffic from client : {} for VIP : {} ",source, dest);
64
65         syncWithLoadBalancerData();
66
67         PoolMember pm= null;
68
69         if(this.clientMemberMap.containsKey(source)){
70
71             pm= this.clientMemberMap.get(source);
72             rrLogger.info("Client {} had sent traffic before,new traffic will be routed to the same pool member {}",source,pm);
73         }else{
74
75             Pool pool = null;
76             if(nextItemFromPool.containsKey(dest)){
77
78                 int memberNum = nextItemFromPool.get(dest).intValue();
79                 rrLogger.debug("Packet is from new client for VIP {}",dest);
80                 pool = this.cmgr.getPool(dest.getPoolName());
81                 pm = pool.getAllMembers().get(memberNum);
82                 this.clientMemberMap.put(source, pm );
83                 rrLogger.info("New client's packet will be directed to pool member {}",pm);
84                 memberNum++;
85
86                 if(memberNum > pool.getAllMembers().size()-1){
87                     memberNum = 0;
88                 }
89                 rrLogger.debug("Next pool member for new client of VIP is set to {}",pool.getAllMembers().get(memberNum));
90
91                 this.nextItemFromPool.put(dest, memberNum);
92             }else{
93                 rrLogger.debug("Network traffic for VIP : {} has appeared first time from client {}",dest,source);
94                 pool = this.cmgr.getPool(dest.getPoolName());
95                 pm = pool.getAllMembers().get(0);
96                 this.clientMemberMap.put(source, pm);
97
98                 rrLogger.info("Network traffic from client {} will be directed to pool member {}",pm);
99                 this.nextItemFromPool.put(dest, 1);
100                 rrLogger.debug("Next pool member for new client of VIP is set to {}",pool.getAllMembers().get(1));
101             }
102         }
103         return pm.getIp();
104     }
105
106     /*
107      * This method does the clean up. Whenever a new client packet arrives with a given VIP,
108      * this method checks the current configuration to see if any pool members have been deleted and
109      * cleans up the metadata stored by this loadbalancing algorithm.
110      */
111     private void syncWithLoadBalancerData(){
112         rrLogger.debug("[Client - PoolMember] table before cleanup : {}",this.clientMemberMap.toString());
113         ArrayList<Client> removeClient = new ArrayList<Client>();
114
115         if(this.clientMemberMap.size() != 0){
116             for(Client client : this.clientMemberMap.keySet()){
117                 if(!this.cmgr.memberExists(this.clientMemberMap.get(client).getName(),
118                                             this.clientMemberMap.get(client).getPoolName())){
119
120                     removeClient.add(client);
121                 }
122             }
123         }
124
125         for(Client client : removeClient){
126             this.clientMemberMap.remove(client);
127
128             rrLogger.debug("Removed client : {} ",client);
129         }
130         rrLogger.debug("[Client - PoolMember] table after cleanup : {}",this.clientMemberMap.toString());
131
132         rrLogger.debug("[VIP- NextMember] table before cleanup : {}",this.nextItemFromPool.toString());
133
134         ArrayList<VIP> resetVIPPoolMemberCount= new ArrayList<VIP>();
135
136         if(this.nextItemFromPool.size() != 0){
137
138             for(VIP vip:this.nextItemFromPool.keySet()){
139                 if(this.nextItemFromPool.get(vip).intValue() > this.cmgr.getPool(vip.getPoolName()).getAllMembers().size()-1){
140
141                     resetVIPPoolMemberCount.add(vip);
142                 }
143             }
144         }
145
146         for(VIP vip:resetVIPPoolMemberCount){
147             rrLogger.debug("VIP next pool member counter reset to 0");
148             this.nextItemFromPool.put(vip, 0);
149         }
150
151         rrLogger.debug("[VIP- NextMember] table after cleanup : {}",this.nextItemFromPool.toString());
152     }
153 }