11package server .server ;
22
33import java .io .File ;
4- import java .util .Map . Entry ;
4+ import java .util .Map ;
55import java .util .Random ;
6- import java .util .TreeMap ;
6+ import java .util .UUID ;
77
88import org .springframework .boot .autoconfigure .web .ErrorController ;
99import org .springframework .http .HttpStatus ;
2121 */
2222@ RestController
2323public class ServiceController implements ErrorController {
24- /*
25- * filename of configuration file
24+
25+ private Random seed = new Random ();//random generator
26+
27+ /*This attribute is going to store all of the configuration. Its aim is to provide a preload because this way
28+ * the access to the data is going to be much quicker in the rest call
29+ *
30+ * I assumed per each technology there is a single version to avoid a one more hash entrance.
2631 */
27- private String configFile ="Configuration.xml" ;
32+ private Map <String ,Map <String ,Configuration >> info ;
33+
34+ private String configFile ="Configuration.xml" ; //filename of configuration file
35+
36+ //un cliente tiene varias plataformas
37+ //una plataforma UN UNICO PLUGIN,
38+ //plataforma y plugin sera la clave para entrar en PING TIME Y TREEMAP DE SERVERS
39+ public ServiceController () {
40+ info = XMLHandler .returnInfo (this .configFile ); //extract data considering the xml configuration
41+ }
2842
2943 public String getConfigFile () {
3044 return configFile ;
@@ -38,14 +52,16 @@ public void setConfigFile(String configFile) {
3852 * url example:
3953 * http://localhost/changeXML?configFile=Configuration.xml
4054 * http://localhost/changeXML?configFile=Configuration2.xml
55+ *
56+ * It is possible to modify the current xml configuration file and then by using the rest call reload that new configuration
4157 */
4258 @ RequestMapping (value = "/changeXML" ,params = {"configFile" },method = RequestMethod .GET )
4359 public ResponseEntity <?> updateConfigFile (@ RequestParam ("configFile" ) String file ) {
4460
4561 File f = new File (file );
46- System .out .println (f );
4762 if (f .exists () && !f .isDirectory ()) { //file is updated if and only if it exisits
48- this .configFile =file ;
63+ this .configFile =file ;
64+ info = XMLHandler .returnInfo (this .configFile ); //extract data considering the xml configuration
4965 return new ResponseEntity <String >("XML configuration file has been updated to: " +file , HttpStatus .OK );
5066 }
5167 //otherwise path is not going to be updated
@@ -61,6 +77,11 @@ public ResponseEntity<?> updateConfigFile(@RequestParam("configFile") String fil
6177 * Afterwards, the cluster is chosen by the algorithm.
6278 * Eventually the xml is returned.
6379 *
80+ *
81+ * The return, chooses a random cluster following a uniform distribution, the reason behind is to distribute more uniformly
82+ the chosen cluster according to the clusters of that technology
83+ *
84+ *
6485 * url example:
6586 * http://localhost/getData?accountCode=clienteA&targetDevice=XBox&pluginVersion=3.3.1
6687 */
@@ -71,43 +92,16 @@ public ResponseEntity<?> updateConfigFile(@RequestParam("configFile") String fil
7192 headers = "Accept=application/xml" ,
7293 method = RequestMethod .GET )
7394 public @ ResponseBody ResponseEntity <?> platformPetition (@ RequestParam ("accountCode" ) String accountCode , @ RequestParam ("targetDevice" ) String targetDevice , @ RequestParam ("pluginVersion" ) String pluginVersion ) {
74-
75- Configuracio config = XMLHandler .check_configuration (accountCode ,targetDevice ,pluginVersion ,this .configFile ); //extract data considering the xml configuration
76-
77- if (config ==null ) return new ResponseEntity <String >("" ,HttpStatus .OK );
78-
79- String cluster =chooseCluster (config );
80- return new ResponseEntity <q >(new q (cluster ,String .valueOf (config .getPingTime ()),config .getCode ()), HttpStatus .OK );
95+ try {
96+ Configuration config = info .get (accountCode ).get (targetDevice +pluginVersion );
97+ return new ResponseEntity <q >(new q (config .getClusters ().ceilingEntry (new Random ().nextInt (config .getTotalWeight ()))
98+ .getValue (),config .getPingTime (),new UUID (this .seed .nextLong (), this .seed .nextLong ()).toString ()), HttpStatus .OK );
99+ }
100+ catch (Exception e ) {
101+ return null ;
102+ }
81103 }
82-
83104
84- /*
85- * This methods decides statistically which cluster is to be returned.
86- * Roulette wheel selection algorithm
87- * There is a list of clusters stored in a structure. Then a random number is chosen between 0 and
88- * the sum of all the weights. This random number is generated with an uniform distribution.
89- * Search in the cluster list for the first server for which the sum of weights for all servers up
90- * to and including this cluster is more than the random value.
91- *
92- * I decided to use this method for three reasons:
93- * - Firstly, if the xml is modified in run time, the frequency of selections is going to be according
94- * to the xml configuration. Also if some other clusters are added, these will be taken into consideration.
95- * - Secondly, this approach allows to not count the number of requests processed in order to decide which cluster to return.
96- * - Last but not least, I believe it to be a good way to distribute the load among the clusters.
97- */
98- public String chooseCluster (Configuracio config ) {
99- TreeMap <Integer , String > pool = new TreeMap <Integer , String >();
100- Integer totalWeight =0 ;
101- for ( Entry <String , Integer > entry : config .getClusters ().entrySet () ) {
102- totalWeight += entry .getValue ();
103- pool .put (totalWeight , entry .getKey ()); //associate each server with the sum of the weights so far
104- }
105-
106- int rnd = new Random ().nextInt (totalWeight );
107-
108- return pool .ceilingEntry (rnd ).getValue ();
109- }
110-
111105 /*
112106 * error handler
113107 */
0 commit comments