1
1
package server .server ;
2
2
3
3
import java .io .File ;
4
- import java .util .Map . Entry ;
4
+ import java .util .Map ;
5
5
import java .util .Random ;
6
- import java .util .TreeMap ;
6
+ import java .util .UUID ;
7
7
8
8
import org .springframework .boot .autoconfigure .web .ErrorController ;
9
9
import org .springframework .http .HttpStatus ;
21
21
*/
22
22
@ RestController
23
23
public 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.
26
31
*/
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
+ }
28
42
29
43
public String getConfigFile () {
30
44
return configFile ;
@@ -38,14 +52,16 @@ public void setConfigFile(String configFile) {
38
52
* url example:
39
53
* http://localhost/changeXML?configFile=Configuration.xml
40
54
* 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
41
57
*/
42
58
@ RequestMapping (value = "/changeXML" ,params = {"configFile" },method = RequestMethod .GET )
43
59
public ResponseEntity <?> updateConfigFile (@ RequestParam ("configFile" ) String file ) {
44
60
45
61
File f = new File (file );
46
- System .out .println (f );
47
62
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
49
65
return new ResponseEntity <String >("XML configuration file has been updated to: " +file , HttpStatus .OK );
50
66
}
51
67
//otherwise path is not going to be updated
@@ -61,6 +77,11 @@ public ResponseEntity<?> updateConfigFile(@RequestParam("configFile") String fil
61
77
* Afterwards, the cluster is chosen by the algorithm.
62
78
* Eventually the xml is returned.
63
79
*
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
+ *
64
85
* url example:
65
86
* http://localhost/getData?accountCode=clienteA&targetDevice=XBox&pluginVersion=3.3.1
66
87
*/
@@ -71,43 +92,16 @@ public ResponseEntity<?> updateConfigFile(@RequestParam("configFile") String fil
71
92
headers = "Accept=application/xml" ,
72
93
method = RequestMethod .GET )
73
94
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
+ }
81
103
}
82
-
83
104
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
-
111
105
/*
112
106
* error handler
113
107
*/
0 commit comments