Logo AND Algorithmique Numérique Distribuée

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