Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
Correction of some bugs and performance enhancement.
[jaceP2P.git] / src / jaceP2P / JaceSuperNodeServer.java
1 package jaceP2P;
2
3 import java.rmi.RemoteException;
4 import java.rmi.server.UnicastRemoteObject;
5 import java.util.ArrayList;
6
7 import and.Mapping.Algo;
8 import and.Mapping.DefaultMapping;
9 import and.Mapping.FT_AIAC_QM;
10 import and.Mapping.FT_FEC;
11 import and.Mapping.GNode;
12 import and.Mapping.GTask;
13 import and.Mapping.Graph;
14 import and.Mapping.Grid;
15 import and.Mapping.Maheve;
16 import and.Mapping.Simple;
17
18
19 public class JaceSuperNodeServer extends UnicastRemoteObject implements
20                 JaceSuperNodeInterface {
21         private static final long serialVersionUID = 1L;
22
23         // Attributes
24         private int beat;
25         private ArrayList<GNode> gnodes = null;
26         private ArrayList<Algo> algos = null ;
27         private boolean inDemand = false, operating = false, authorized = false ;
28         
29         // Constructors
30
31         public JaceSuperNodeServer(int timeBeat) throws RemoteException {
32                 super() ;
33                 beat = timeBeat ;
34                 gnodes = new ArrayList<GNode>() ;
35                 algos = new ArrayList<Algo>() ;
36         }
37
38         public int getSuperNodeBeat() throws RemoteException {
39                 return beat;
40         }
41
42         public ArrayList<Object> sendStub(String IP, int port, JaceSuperNodeInterface stub)
43                         throws RemoteException {
44                 SuperNodeListe.Instance().addStubOf(IP, port, stub);
45                 System.out.println("Added new superNode (" + IP
46                                 + ") to list and return List");
47                 return SuperNodeListe.Instance().getListe() ;
48         }
49
50         public void updateCountNode(String IP, int nb) throws RemoteException {
51                 SuperNodeListe.Instance().modifCountNode(IP, nb);
52                 // System.out.println( "SuperNode " + IP + " has registered " + nb +
53                 // " Daemons" ) ;
54                 SuperNodeListe.Instance().viewAll();
55         }
56
57         public void sendSurplus(ArrayList<Node> nodes, ArrayList<GNode> _gnodes) throws RemoteException {
58                 System.out.println("Recieved " + nodes.size() + " nodes");
59
60                 for (int i = 0; i < nodes.size(); i++) {
61                         Register.Instance().getListe().add((Node) nodes.get(i));
62
63                         System.out.println("Adding "
64                                         + ((Node) nodes.get(i)).getName());
65
66                         try {
67                                 ((Node) nodes.get(i)).getStub().updateHeart(
68                                                 LocalHost.Instance().getSuperNodeStub());
69                                 int index = SuperNodeListe.Instance().existSuperNode(
70                                                 LocalHost.Instance().getIP());
71                                 ((SuperNodeData) SuperNodeListe.Instance().getListe()
72                                                 .get(index))
73                                                 .setNbOfNodes(Register.Instance().getSize());
74                                 new ForwardCount().start();
75                         } catch (Exception e) {
76                                 System.err.println("Error changing Server in SendSurplus : "
77                                                 + e);
78                         }
79                 }
80                 
81                 /** Updating gnodes **/
82                 if( _gnodes != null )
83                 {
84                         gnodes = _gnodes ;
85                 }
86         }
87
88         public void setToken() throws RemoteException {
89                 System.out.println("I got Token");
90
91                 TokenThread.Instance().setToken();
92
93                 try {
94                         HeartBeatSNode.Instance().getServer().beating(true);
95
96                         System.out.println("Put token to true");
97                 } catch (Exception e) {
98                         System.err
99                                         .println("Unable to heartBeat the next SuperNode with the new Token : "
100                                                         + e);
101                 }
102         }
103
104         public void updateHeart(JaceSuperNodeInterface stub) throws RemoteException {
105                 System.out.println("I change to ping a superNode");
106
107                 HeartBeatSNode.Instance().setServer(stub);
108         }
109
110         public synchronized void removeSuperNode(SuperNodeData d)
111                         throws RemoteException {
112                 SuperNodeListe.Instance().removeSuperNode(d);
113         }
114
115         /****************************************************/
116         /****************************************************/
117
118         // Register a Daemon in the Register.Instance() of the SuperNode
119         public synchronized void workerRegistering(JaceInterface workerStub,
120                         String workerIP, String workerName, int port, GNode g)
121                         throws RemoteException {
122                 System.out.println("CONNECTION of " + workerName);
123
124                 // Create the node
125                 Node noeud = new Node(workerStub);
126                 noeud.setName(workerName);
127                 noeud.setIP(g.getIP());
128                 noeud.setAliveFlag(true);
129                 noeud.setAliveTime();
130                 noeud.setPort(port);
131                 noeud.setAppliName(null);
132                 noeud.setNbOfBeats(0);
133                 
134                 String sid = workerIP.replace( ".", "" ) + port ;
135                 Long id = Long.parseLong( sid ) ;
136                 noeud.setId( id ) ;
137
138                 g.setNode( noeud ) ;
139                 g.setId( id ) ;
140                 g.setMapped( false ) ;
141                 
142                 workingOnGnodes() ;
143                 
144                 gnodes.add( g ) ;
145                 updateGrids( g ) ;
146                 
147
148                 // Insert the node in the Register.Instance() of the Super Node
149                 Register.Instance().addNode(noeud);
150
151                 // Register.Instance().viewAll() ;
152                 // SuperNodeListe.Instance().viewAll() ;
153
154                 // Inform the other superNode and tell them the nb of Daemon I have
155                 // registered
156                 int index = SuperNodeListe.Instance().existSuperNode(
157                                 LocalHost.Instance().getIP());
158
159                 ((SuperNodeData) SuperNodeListe.Instance().getListe().get(index))
160                                 .setNbOfNodes(Register.Instance().getSize());
161                 SuperNodeListe.Instance().forwardCountNode();
162                 
163                 authorized = true ;
164                 SuperNodeListe.Instance().addGNode( g ) ;
165                 authorized = false ;
166                 
167                 operating = false ;
168         }
169
170         
171         /**
172          * Update all mapping algorithms with a new node.
173          * @param _g The new node
174          * 
175          * @author S&eacute;bastien Miqu&eacute;e
176          */
177         private synchronized void updateGrids( GNode _g )
178         {
179                 if( _g != null )
180                 {
181                         for( int i = 0 ; i < algos.size() ; i++ )
182                         {
183                                 algos.get( i ).getGrid().addGNode( _g ) ;
184                         }
185                 }
186                 
187         }
188
189         /****************************************************/
190         /****************************************************/
191
192         // HeartBeat that detects if a Daemon is dead or alive
193         public void beating(JaceInterface stub) throws RemoteException {
194                 Node noeud = Register.Instance().getNodeOfStub(stub);
195
196                 if (noeud != null) {
197                         noeud.setAliveFlag(true);
198                         noeud.setAliveTime();
199                         noeud.incrementNbOfBeats();
200                         // -- sm modif
201                         // System.out.println( noeud.getName() + " is pinging me" ) ;
202                 } else {
203                         // System.out.println( noeud.getName() +
204                         // ".................. is not in my list" ) ;
205                 }
206         }
207
208         // HeartBeat that detects if a Super Node is dead or alive
209         public void beating(boolean token) throws RemoteException {
210                 ScanThreadSuperNode.Instance().setAliveTime();
211                 ScanThreadSuperNode.Instance().setToken(token);
212                 // -- sm modif
213                 // System.out.println( "Super Node is pinging me" ) ;
214         }
215
216
217         /*********************************/
218         /** Mapping !! Sébastien Miquée **/
219         /*********************************/
220
221         /**
222          * Search and return to the requester spawner a register containing
223          * computation nodes plus some extra nodes if needed. This method requires
224          * as parameters the mapping algorithm choice and its parameters, and the
225          * amount of requested nodes and the task to be used, in order to 
226          * construct the tasks graph.
227          * @param spawnerIP IP of the requester
228          * @param nbTasks Amount of tasks
229          * @param t Tasks to be executed
230          * @param nbNoeuds Total amount of requested nodes
231          * @param algo Identifier of the mapping algorithm
232          * @param paramAlgo Parameter of the mapping algorithm 
233          * 
234          * @author S&eacute;bastien Miqu&eacute;e        
235          */
236         @Override
237         public synchronized Register getRegisterSpawner(String spawnerIP, int nbTasks, Task t,
238                         int nbNoeuds, int algo, double paramAlgo) throws RemoteException {
239
240                 // Have we the correct application ?
241                 if( t == null ) {
242                         System.err.println( "Problem of class transmission!" ) ;
243                         return null ;
244                 }
245                 
246                 if( t.getDependencies( 0 ) == null )
247                 {
248                         System.err.println( "No redifinition of getDependencies() function!" ) ;
249                         return null ;
250                 }
251                 
252
253                 /** Creation of an empty new Register **/
254                 Register reg = new Register() ;
255
256                 workingOnGnodes() ;
257                 
258                 /** Initialization of Grid architecture (G5K for now) **/
259                 Grid grid = new Grid() ;
260
261                 for( int i = 0 ; i < gnodes.size() ; i++ )
262                 {
263                         grid.addGNode( gnodes.get( i ) ) ;
264                 }
265                 
266                 
267                 /** Informing about the grid heterogeneity **/
268                 System.out.println( "\nHeterogeneity degree of the grid: " + grid.getHeterogenityDegre() + "\n" ) ;
269                 
270
271                 /** Creation of tasks GTask **/
272                 ArrayList<GTask> ts = new ArrayList<GTask>();
273                 for( int i = 0; i < nbTasks; i++ ) {
274                         ts.add( new GTask( i ) ) ;
275                 }
276
277                 /** Research of dependencies **/
278                 for( int i = 0; i < nbTasks; i++ ) {
279                         int dep[] = null ;
280                         dep = t.getDependencies( i ) ;
281
282                         /** Adding dependencies to tasks **/
283                         for( int j = 0; j < dep.length; j++ ) {
284                                 if( dep[j] != -1 ) {
285                                         ts.get( i ).addDependance( ts.get( dep[ j ] ) ) ;
286                                 } else {
287                                         break ;
288                                 }
289                         }
290                 }
291                 
292                 /** Creation of the application interaction graph **/
293                 Graph graph = new Graph();
294
295                 for( int i = 0 ; i < ts.size() ; i++) 
296                 {
297                         graph.addGTask(ts.get(i));
298                 }
299
300                 /** TODO Loading algorithm class with parameters in a configuration file **/
301                 /** Selection of the mapping algorithm **/
302                 Algo al = null ;
303
304                 switch( algo ) {
305                 case 0:
306                         al = new Simple(graph, grid);
307                         break;
308                 case 1:
309                         al = new FT_AIAC_QM(graph, grid, paramAlgo);
310                         break;
311                 case 2:
312                         al = new FT_FEC(graph, grid, paramAlgo);
313                         break;
314                 case 3:
315                         al = new Maheve( graph, grid ) ;
316                         ((Maheve) al).setNbSave((int)paramAlgo);
317                         break ;
318                 default:
319                         al = new DefaultMapping( graph, grid ) ;
320                 }
321
322                 if (al != null) 
323                 {
324                         /** Launching the Mapping **/
325                         al.map();
326
327
328                         /** Creating the register **/
329                         ArrayList<GNode> ag = al.getMapping().getMappedGNodes();
330                         
331                         System.out.println("NB returned nodes : "+ag.size());
332
333                         
334                         /** Setting the algorithm's identifier **/
335                         al.setIdS( spawnerIP ) ;
336                         
337                         /** Adding the algorithm in the list **/
338                         algos.add( al ) ;
339                         
340                         int idAlgo = searchAlgo( spawnerIP ) ;
341                         
342                         /** Mapping distribution over other SuperNodes */
343                         SuperNodeListe.Instance().setMapping( al ) ;
344                         
345                         
346                         
347                         authorized = true ;
348                         
349                         for( int i = 0; i < ag.size(); i++ ) {
350                                 reg.addNode((Node) ag.get(i).getNode());
351                                 
352                                 ag.get(i).setMapped( true ) ;
353                                 setMapped( ag.get(i), 1 ) ;
354                                 Register.Instance().removeNode((Node) ag.get(i).getNode());
355                         }
356                         
357                         
358                         /** Searching extra nodes if any **/
359                         if( nbNoeuds > nbTasks )
360                         {
361                                 int nb = nbNoeuds - nbTasks ;
362                                 GNode sup = null ;
363                                 
364                                 for( int i = 0 ; i < nb ; i ++ )
365                                 {
366                                         sup = algos.get(idAlgo).getOtherGNode( gnodes ) ;
367                                         algos.get(idAlgo).getMapping().addOtherNode( sup ) ;
368                                         reg.addNodeBeg( (Node) sup.getNode() ) ;
369                                         setMapped( sup, 1 ) ;
370                                         Register.Instance().removeNode((Node) sup.getNode());
371                                 }
372                         }
373                         
374                         authorized = false ;
375
376                         if (ag.size() != 0) {
377                                 SuperNodeListe.Instance().forwardCountNode();
378                         }
379
380                 } 
381                 
382                 operating = false ;
383                 
384                 /** Returning result **/
385                 return reg ;
386         }
387
388         
389         public synchronized void setMapped( GNode _g, int _mode ) throws RemoteException 
390         {
391                 if( _g != null )
392                 {
393                         _g.setMapped( true ) ;
394                         
395                         for( int i = 0 ; i < gnodes.size() ; i++ )
396                         {
397                                 if( _g.getId() == gnodes.get( i ).getId() )
398                                 {
399                                         gnodes.remove( i ) ;
400                                         break ;
401                                 }
402                         }
403                         
404                         for( int i = 0 ; i < algos.size() ; i++ )
405                         {
406                                 algos.get( i ).getGrid().setMappedStatus( _g, true ) ;
407                         }
408                         
409                         if( _mode == 1 )
410                         {
411                                 authorized = true ;
412                         
413                                 SuperNodeListe.Instance().setMappedGNode( _g, 0 ) ;
414                         
415                                 authorized = false ;
416                         }
417                 } else {
418                         System.err.println( "GNode is null is setMapped!" ) ;
419                 }
420         }
421
422         /**
423          * Suppress a node from the gnodes list if this node is free, or remove
424          * it from the Mapping class of the mapping algorithm if this node is
425          * a computation node. After having done the local suppression of the node
426          * it propagates the suppression to other SuperNodes.
427          * @param _n The fallen node
428          * @param _mode Choice of the list (0: gnodes, 1: mapping, 2:just mapped)
429          * 
430          * @author S&eacute;bastien Miqu&eacute;e        
431          */
432         @Override
433         public synchronized GNode delGNodeFromList( Node _n, int _mode, String _spawnerIp ) throws RemoteException
434         {
435                 GNode removedGNode = null ;
436                 
437                 if( _n != null )
438                 {       
439                         boolean free = false ;
440                         
441                         if( ! operating )
442                         {
443                                 workingOnGnodes() ;
444                                 free = true ;
445                         }
446
447                         if( _mode == 0 )
448                         {
449                                 GNode dead = null ;
450                                 
451                                 for( int i = 0 ; i < gnodes.size() ; i++ )
452                                 {
453                                         if( _n.getId() == ((Node) gnodes.get(i).getNode()).getId() )
454                                         {
455                                                 dead = gnodes.remove( i ) ;
456                                                 break ;
457                                         }
458                                 }
459                                 
460                                 if( dead != null )
461                                 {
462                                         for( int i = 0 ; i < algos.size() ; i++ )
463                                         {
464                                                 algos.get( i ).getGrid().removeGNode( dead ) ;
465                                                 Register.Instance().removeNodeOfName( dead.getName() ) ;
466                                                 SuperNodeListe.Instance().removeGNode( dead, _mode, _spawnerIp ) ;
467                                                 
468                                                 // trying to reboot the node
469                                                 try {
470                                                         _n.getStub().suicide2( "Reboot!" ) ;
471                                                 } catch( Exception e ) {
472                                                         System.err.println( "(SN) Unable to reboot the node:" ) ;
473                                                         e.printStackTrace() ;
474                                                 }
475                                         }
476                                 } else {
477                                         System.err.println( "The dead node signaled does not exist!" ) ;
478                                 }
479                         }
480                         
481                         if( free )
482                         {
483                                 operating = false ;
484                         }
485                 
486                 }
487                 
488                 return removedGNode ;
489         }
490         
491         
492         /**
493          * Search the position of the mapping algorithm in the list.
494          * @param _id Identifier of the algorithm
495          * @return The position in the list
496          */
497         private int searchAlgo( String _id ) 
498         {
499                 int id = -1 ;
500                 
501                 for( int i = 0 ; i < algos.size() ; i++ )
502                 {
503                         if( algos.get( i ).getIdS().equals( _id ) )
504                         {
505                                 id = i ; 
506                                 break ;
507                         }
508                 }
509                 
510                 return id ;
511         }
512
513         /**
514          * Determine if this SuperNode can operate on the gnodes list.
515          * It asks other SuperNodes to know if their are working on this list
516          * and set the authorization, or not.
517          * 
518          * @author S&eacute;bastien Miqu&eacute;e        
519          */
520         private synchronized void workingOnGnodes()
521         {
522                 boolean tmp = true ;    
523                 
524                 inDemand = false ; 
525                 operating = false ;
526             
527                 while( ! operating )
528                 {
529                         inDemand = true ;
530                         tmp = true ;
531                         
532                         tmp = tmp && SuperNodeListe.Instance().workingOnGnodes() ;
533
534                         operating = tmp ;
535                         
536                         if( ! tmp )
537                         {
538                                 inDemand = false ;
539                                 
540                                 try {
541                                         Thread.sleep( 10 ) ;
542                                 } catch (InterruptedException e) {
543                                         e.printStackTrace();
544                                 }
545                         }
546                 }
547                 
548                 inDemand = false ;
549         }
550         
551         /**
552          * Search and return a new node when one failed or when JaceP2P needs another
553          * one. For the first case, the given failed node should not be null, and
554          * null in the other case.
555          * @param _spawnerIP IP of the requester
556          * @param _rank The task number number of the dead node
557          * 
558          * @author S&eacute;bastien Miqu&eacute;e
559          */
560         @Override
561         public synchronized Node getNewNode( String _spawnerIP, int _rank ) throws RemoteException
562         {
563                 int idNode = -1 ;
564                 int idAlgo = searchAlgo( _spawnerIP ) ;
565                 
566                 if( idAlgo == -1 )
567                 {
568                         System.err.println( "No algorithm found for this Spawner!" ) ;
569                         return null ;
570                 }
571                 
572                 /** We have to replace a Spawner **/
573                 if( _rank == -2 )
574                 {
575                         idNode = -2 ;
576                 } else {
577                 /** We have to replace a computing node **/
578                         idNode = algos.get( idAlgo ).getMapping().getIdOfAssociation( _rank ) ;
579                 }
580                 
581                 if( idNode == -1 )
582                 {
583                         System.err.println( "No tasks corresponds to rank "+_rank+"!" ) ;
584                         return null ;
585                 }
586                 
587                 GNode dead = null ;
588                 
589                 if( idNode >= 0 ) 
590                 {
591                         dead = algos.get( idAlgo ).getMapping().getAssociation( idNode ).getGNode() ;
592                 }
593                 
594                 if( dead == null && idNode >= 0 )
595                 {
596                         System.err.println( "The GNode corresponding to the task "+_rank+" is null!" ) ;
597                         System.err.println( "Trying to find a new node for this task (not optimal)..." ) ;
598                 }
599                 
600                 return getNewNode( _spawnerIP, dead ) ;
601         }
602
603         /**
604          * Search and return a new node when one failed or when JaceP2P needs another
605          * one. For the first case, the given failed node should not be null, and
606          * null in the other case.
607          * @param _spawnerIP IP of the requester
608          * @param _deadNode The failed node
609          * 
610          * @author S&eacute;bastien Miqu&eacute;e
611          */
612         @Override
613         public synchronized Node getNewNode( String _spawnerIP, GNode _deadNode ) throws RemoteException
614         {
615                 Node node = null ;
616                 GNode remp = null ;
617
618                 int idAlgo = searchAlgo( _spawnerIP ) ;
619                 
620                 if( idAlgo == -1 )
621                 {
622                         System.err.println( "No algorithm found for this Spawner!" ) ;
623                         return null ;
624                 }
625                 
626                 
627                 /** Can we use gnodes ?**/
628                 workingOnGnodes() ;
629                 
630                 if( _deadNode != null )         
631                 {
632                         authorized = true ;
633                         
634                         removeMappedGNode( _deadNode, 1 ) ;
635                         
636                         authorized = false ;
637
638                         remp = algos.get( idAlgo ).replaceNode( _deadNode, gnodes ) ;
639                 
640                         if( remp != null )
641                         {
642                                 System.out.println( "Replacing node found." ) ;
643                                 
644                                 authorized = true ;
645                                 
646                                 remp.setMapped( true ) ;
647                                 
648                                 setMapped( remp, 1 ) ;
649                                 Register.Instance().removeNodeOfName( remp.getName() ) ;
650                                 
651                                 
652                                 /** Updating all mapping **/
653                                 updateMappedNode( _deadNode, remp, _spawnerIP ) ;
654                                 propagateReplaceNode( _deadNode, remp, _spawnerIP ) ;
655                                 
656                                 authorized = false ;
657                                 
658                                 SuperNodeListe.Instance().forwardCountNode();
659                         } else {
660                                 System.err.println( "Replacing node not found !!" ) ;
661                         }
662                 } else {
663                         remp = algos.get( idAlgo ).getOtherGNode( gnodes ) ;
664                         
665                         if( remp != null )
666                         {
667                                 System.out.println( "Other new node found." ) ;
668
669                                 remp.setMapped( true ) ;
670                                 
671                                 authorized = true ;
672                                 
673                                 setMapped( remp, 1 ) ;
674                                 Register.Instance().removeNodeOfName( remp.getName() ) ;
675                                 
676                                 authorized = false ;
677                                 
678                                 SuperNodeListe.Instance().forwardCountNode();
679                         } else {
680                                 System.err.println( "Other new node not found !!" ) ;
681                         }
682                 }
683                 
684                 if( remp != null )
685                 {
686                         node = (Node) remp.getNode() ;
687                 } else {
688                         System.err.println( "SuperNode: No new node found!" ) ;
689                 }
690                 
691                 
692                 /** Free the gnodes use **/
693                 operating = false ;
694                 
695                 return node ;
696         }
697         
698         
699         public synchronized void removeMappedGNode( GNode _g, int _mode ) throws RemoteException
700         {
701                 if( _g != null )
702                 {
703                         for( int i = 0 ; i < algos.size() ; i++ )
704                         {
705                                 algos.get( i ).getGrid().removeGNode( _g ) ;
706                         }
707                         
708                         if( _mode == 1 )
709                         {
710                                 SuperNodeListe.Instance().removeGNode( _g, 0 ) ;
711                         }
712                 } else {
713                         System.err.println( "GNode to be deleted is null!" ) ;
714                 }
715         }
716         
717         /**
718          * Replace a failed GNode in the mapping by another one.
719          * This method is called by the SuperNodeList, to broadcast the modification.
720          * @param _dead The failed node
721          * @param _remp The replacing node
722          * 
723          * @author S&eacute;bastien Miqu&eacute;e
724          */
725         @Override
726         public synchronized void updateMappedNode( GNode _dead, GNode _remp, String _spawnerIP ) 
727         {
728                 if( _remp != null )
729                 {
730                         int pos = 0 ;
731                         
732                         int idAlgo = searchAlgo( _spawnerIP ) ;
733                         
734                         if( idAlgo == -1 )
735                         {
736                                 System.err.println( "No algorithm found for this Spawner!" ) ;
737                                 return ;
738                         }
739                 
740                         pos = algos.get( idAlgo ).getMapping().getIdOfAssociation( _dead ) ;
741                 
742                         if( pos != -1 )
743                         {
744                                 /** Changing the node in the mapping **/
745                                 if( algos.get( idAlgo ).getMapping().getMapping().get( pos ).setGNode( _remp ) )
746                                 {
747                                         System.out.println( "Succesfully replacing the fallen node in the mapping." ) ;
748                                 } else {
749                                         System.err.println( "Failed in replacing the fallen node in the mapping!" ) ;
750                                 }
751                         } else {
752                                 System.err.println( "The dead node was not found in the mapping!" ) ;
753                         }
754                         
755                 } else {
756                         System.err.println( "The new GNode is null!" ) ;
757                 }       
758         }
759
760         
761         /**
762          * Inform all SuperNodes of the replacement of a failed computing node.
763          * @param _dead The failed node
764          * @param _remp The replacing node
765          * 
766          * @author S&eacute;bastien Miqu&eacute;e        
767          */
768         private synchronized void propagateReplaceNode( GNode _dead, GNode _remp, String _spawnerIP ) throws RemoteException
769         {
770                 if( _remp != null )
771                 {       
772                         SuperNodeListe.Instance().propagateReplaceNode( _dead, _remp, _spawnerIP ) ;
773                 } else {
774                         System.err.println( "The replacement node is null!" ) ;
775                 }
776         }
777
778         /**********************************************************/
779         /**********************************************************/
780
781         
782         @Override
783         /**
784          * Add a new node in the list.
785          * @param _g The new node
786          *
787          * @author S&eacute;bastien Miqu&eacute;e        
788          */
789         public void addGNode( GNode _g ) throws RemoteException 
790         {
791                 if( _g != null )
792                 {
793                         boolean free = false ;
794                         
795                         if( ! operating )
796                         {
797                                 workingOnGnodes() ;
798                                 free = true ;
799                         }       
800                         
801                         gnodes.add( _g ) ;
802                         
803                         updateGrids( _g ) ;
804                         
805                         if( free )
806                                 operating = false ;
807                 }
808         }
809         
810
811         /**
812          * Set the local mapping with another done on an other SuperNode.
813          * @param _al The new mapping
814          * 
815          * @author S&eacute;bastien Miqu&eacute;e
816          */
817         @Override
818         public synchronized void setMapping( Algo _al ) throws RemoteException 
819         {
820                 if( searchAlgo( _al.getIdS() ) == -1 )
821                 {
822                         algos.add( _al ) ;
823                 } else {
824                         System.err.println( "I already have this mapping algorithm!" ) ;
825                 }
826         }
827
828         
829         @Override
830         /**
831          * Allow or deny the use of operations on the gnodes list, in order to
832          * do a mapping operation.
833          * @return The authorization or not to block gnodes
834          * 
835          * @author S&eacute;bastien Miqu&eacute;e
836          */
837         public boolean blockForMapping() throws RemoteException
838         {
839                 while( inDemand )
840                 {
841                         try {
842                                 Thread.sleep( 10 ) ;
843                         } catch (InterruptedException e) {
844                                 e.printStackTrace();
845                         }
846                 }
847                 
848                 if( operating && ! authorized )
849                 {
850                         return false ;
851                 } else {
852                         return true ;
853                 }
854         }
855
856         /**
857          * Return the array containing the current not mapped nodes available.
858          * @return The array of available nodes
859          * 
860          * @author S&eacute;bastien Miqu&eacute;e 
861          */
862         @Override
863         public ArrayList<GNode> getGNodes() throws RemoteException 
864         {
865                 return gnodes ;
866         }
867         
868         
869         /**
870          * Remove a mapping algorithm of the algorithms list.
871          * @param _id The algorithm identifier
872          * @param _mode Indicate if the information should be transmitted
873          * 
874          * @author S&eacute;bastien Miqu&eacute;e
875          */
876         public void removeAlgo( String _id, int _mode ) throws RemoteException
877         {
878                 int pos ;
879                 
880                 pos = searchAlgo( _id ) ;
881                 
882                 if( pos != -1 )
883                 {
884                         algos.remove( pos ) ;
885                         
886                         if( _mode == 0 )
887                         {
888                                 SuperNodeListe.Instance().removeAlgo( _id ) ;
889                         }
890                 } else {
891                         System.err.println( "The mapping algorithm requested for deletion does not exist!" ) ;
892                 }
893         }
894         
895         
896         // ** Tests ** //
897         public Algo getAlgo( String _spID ) throws RemoteException
898         {
899                 int pos ;
900                 Algo ret = null ;
901                 
902                 pos = searchAlgo( _spID ) ;
903                 
904                 if( pos != -1 )
905                 {
906                         ret = algos.get( pos ) ;
907                 }
908                 
909                 return ret ;
910         }       
911         
912 }
913
914 /** ! **/