Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
Change interface for elements_father, and avoid to allocate a dynar.
[simgrid.git] / src / cxx / MsgProcess.cxx
1 /*
2  * Process.cxx
3  *
4  * Copyright 2006,2007 Martin Quinson, Malek Cherier           
5  * All right reserved. 
6  *
7  * This program is free software; you can redistribute 
8  * it and/or modify it under the terms of the license 
9  *(GNU LGPL) which comes with this package. 
10  *
11  */
12  
13  /* Process member functions implementation.
14   */  
15
16 #include <MsgProcess.hpp>
17
18
19 #include <MsgApplicationHandler.hpp>
20 #include <MsgHost.hpp>
21 #include <MsgTask.hpp>
22
23 #include <stdlib.h>
24 #include <stdio.h>
25
26 #include <msg/msg.h>
27 #include <msg/private.h>
28 #include <msg/mailbox.h>
29
30
31
32 namespace SimGrid
33 {
34         namespace Msg
35         {
36
37                 MSG_IMPLEMENT_DYNAMIC(Process, Object)
38
39                 // Default constructor.
40                 Process::Process()
41                 {
42                         this->nativeProcess = NULL;
43                 }
44                 
45                 Process::Process(const char* hostName, const char* name)
46                 throw(NullPointerException, HostNotFoundException, BadAllocException)
47                 {
48                         // check the parameters
49                         
50                         if(!name)
51                                 throw NullPointerException("name");
52                                 
53                         if(!hostName)
54                                 throw NullPointerException("hostName");
55                         
56                         Host host = Host::getByName(hostName);
57                                 
58                         create(host, name, 0, NULL);    
59                 }
60                 
61                 Process::Process(const Host& rHost, const char* name)
62                 throw(NullPointerException)
63                 {
64                         if(!name)
65                                 throw NullPointerException("name");
66                                 
67                         create(rHost, name, 0, NULL);   
68                 }
69                 
70                 Process::Process(const Host& rHost, const char* name, int argc, char** argv)
71                 throw(NullPointerException, InvalidArgumentException, LogicException)
72                 {
73                         
74                         // check the parameters
75                         
76                         if(!name)
77                                 throw NullPointerException("name");
78                                 
79                         if(argc < 0)
80                                 throw InvalidArgumentException("argc (must be positive)");
81                                 
82                         if(!argc && argv)
83                                 throw LogicException("argv is not NULL but argc is zero");
84                         
85                         if(argc && !argv)
86                                 throw LogicException("argv is NULL but argc is not zero");
87                         
88                         create(rHost, name, argc, argv);        
89                 }
90                 
91                 Process::Process(const char* hostName, const char* name, int argc, char** argv)
92                 throw(NullPointerException, InvalidArgumentException, LogicException, HostNotFoundException, BadAllocException)
93                 {
94                         // check the parameters
95                         
96                         if(!name)
97                                 throw NullPointerException("name");
98                                 
99                         if(!hostName)
100                                 throw NullPointerException("hostName");
101                                 
102                         if(argc < 0)
103                                 throw InvalidArgumentException("argc (must be positive)");
104                                 
105                         if(!argc && argv)
106                                 throw LogicException("argv is not NULL but argc is zero");
107                         
108                         if(argc && !argv)
109                                 throw LogicException("argv is NULL but argc is not zero");
110                                 
111                         Host host = Host::getByName(hostName);
112                                 
113                         create(host, name, argc, argv); 
114                 }
115                 
116                 int Process::killAll(int resetPID) 
117                 {
118                     return MSG_process_killall(resetPID);
119                 }
120                 
121                 void Process::suspend(void)
122                 throw(MsgException)
123                 {
124                     if(MSG_OK != MSG_process_suspend(nativeProcess)) 
125                         throw MsgException("MSG_process_suspend() failed");
126                 }
127                 
128                 void Process::resume(void) 
129                 throw(MsgException)
130                 {
131                         if(MSG_OK != MSG_process_resume(nativeProcess))
132                                 throw MsgException("MSG_process_resume() failed");
133                 }
134                 
135                 int Process::isSuspended(void)
136                 {
137                    return MSG_process_is_suspended(nativeProcess);
138                 }  
139                 
140                 Host& Process::getHost(void) 
141                 {
142                   m_host_t nativeHost = MSG_process_get_host(nativeProcess);
143                         
144                   // return the reference to the Host object
145                   return (*((Host*)nativeHost->data));
146                 }
147                 
148                 Process& Process::fromPID(int PID) 
149                 throw(ProcessNotFoundException, InvalidArgumentException, MsgException)
150                 {
151                         // check the parameters
152                         
153                         if(PID < 1)
154                                 throw InvalidArgumentException("PID (the PID of the process to retrieve is less than 1)");
155                                 
156                         Process* process = NULL;
157                         m_process_t nativeProcess = MSG_process_from_PID(PID);
158                         
159                         if(!nativeProcess) 
160                                 throw ProcessNotFoundException(PID);
161                         
162                         process = Process::fromNativeProcess(nativeProcess);
163                                 
164                         if(!process) 
165                                 throw MsgException("Process::fromNativeProcess() failed");
166                         
167                         return (*process);   
168                 } 
169                 
170                 int Process::getPID(void)
171                 {
172                     return MSG_process_get_PID(nativeProcess);
173                 }
174                 
175                 int Process::getPPID(void)
176                 {
177                         return MSG_process_get_PPID(nativeProcess);
178                 }
179                 
180                 const char* Process::getName(void) const
181                 {
182                         return nativeProcess->name;
183                 }
184                 
185                 Process& Process::currentProcess(void)
186                 throw(MsgException)
187                 {
188                         Process* currentProcess = NULL;
189                     m_process_t currentNativeProcess = MSG_process_self();
190                 
191                 
192                         if(!currentNativeProcess) 
193                                 throw MsgException("MSG_process_self() failed");
194                         
195                         currentProcess = Process::fromNativeProcess(currentNativeProcess);
196                                 
197                         if(!currentProcess) 
198                                 throw MsgException("Process::fromNativeProcess() failed");
199                         
200                         return (*currentProcess);  
201                 }
202                 
203                 int Process::currentProcessPID(void)
204                 {
205                          return MSG_process_self_PID();
206                 }
207                 
208                 
209                 int Process::currentProcessPPID(void)
210                 {
211                         return MSG_process_self_PPID();
212                 }
213                 
214                 void Process::migrate(const Host& rHost)
215                 throw(MsgException)
216                 {
217                         if(MSG_OK != MSG_process_change_host(rHost.nativeHost))
218                                 throw MsgException("MSG_process_change_host()");
219                         
220                 }
221                 
222                 void Process::sleep(double seconds)
223                 throw(InvalidArgumentException, MsgException)
224                 {
225                         // check the parameters.
226                         if(seconds <= 0)
227                                 throw InvalidArgumentException("seconds (must not be less or equals to zero");
228                                 
229                         if(MSG_OK != MSG_process_sleep(seconds))
230                                 throw MsgException("MSG_process_sleep()");
231                         
232                 }
233                 
234                 void Process::putTask(const Host& rHost, int channel, Task* task)
235                 throw(InvalidArgumentException, MsgException)
236                 {
237                         // check the parameters
238                         
239                         if(channel < 0)
240                                 throw InvalidArgumentException("channel (must not be negative)");
241                                 
242                         if(MSG_OK != MSG_task_put_with_timeout(task->nativeTask, rHost.nativeHost, channel, -1.0))
243                                 throw MsgException("MSG_task_put_with_timeout()");
244                 }
245                 
246                 void Process::putTask(const Host& rHost, int channel, Task* task, double timeout) 
247                 throw(InvalidArgumentException, MsgException)
248                 {
249                         // check the parameters
250                         if(channel < 0)
251                                 throw InvalidArgumentException("channel (must not be negative)");
252                                 
253                         if(timeout < 0 && timeout != -1.0)
254                                 throw InvalidArgumentException("timeout (must not be less than zero and different of -1.0)");
255                                 
256                         if(MSG_OK != MSG_task_put_with_timeout(task->nativeTask, rHost.nativeHost, channel, timeout))
257                                 throw MsgException("MSG_task_put_with_timeout() failed");
258                 }
259                 
260                 Task* Process::getTask(int channel) 
261                 throw(InvalidArgumentException, MsgException)
262                 {
263                         // check the parameters
264                         
265                         if(channel < 0)
266                                 throw InvalidArgumentException("channel (must not be negative)");
267                         
268                         m_task_t nativeTask = NULL;
269                         
270                         if (MSG_OK != MSG_task_get_ext(&nativeTask, channel, -1.0, NULL)) 
271                                 throw MsgException("MSG_task_get_ext() failed");
272                         
273                         return (Task*)(nativeTask->data);
274                 }
275                 
276                 Task* Process::getTask(int channel, double timeout) 
277                 throw(InvalidArgumentException, MsgException)
278                 {
279                         // check the parameters
280                         if(channel < 0)
281                                 throw InvalidArgumentException("channel (must not be negative)");
282                                 
283                         if(timeout < 0 && timeout != -1.0)
284                                 throw InvalidArgumentException("timeout (must not be less than zero and different of -1.0)");
285                         
286                         m_task_t nativeTask = NULL;
287                         
288                         if (MSG_OK != MSG_task_get_ext(&nativeTask, channel, timeout, NULL)) 
289                                 throw MsgException("MSG_task_get_ext() failed");
290                         
291                         return (Task*)(nativeTask->data);
292                 }
293                 
294                 Task* Process::getTask(int channel, const Host& rHost) 
295                 throw(InvalidArgumentException, MsgException)
296                 {
297                         // check the parameters
298                         if(channel < 0)
299                                 throw InvalidArgumentException("channel (must not be negative)");
300                                 
301                         m_task_t nativeTask = NULL;
302                         
303                         if (MSG_OK != MSG_task_get_ext(&nativeTask, channel, -1.0, rHost.nativeHost)) 
304                                 throw MsgException("MSG_task_get_ext() failed");
305                         
306                         return (Task*)(nativeTask->data);
307                 }
308                 
309                 Task* Process::getTask(int channel, double timeout, const Host& rHost)
310                 throw(InvalidArgumentException, MsgException)
311                 {
312                         // check the parameters
313                         if(channel < 0)
314                                 throw InvalidArgumentException("channel (must not be negative)");
315                                 
316                         if(timeout < 0 && timeout != -1.0)
317                                 throw InvalidArgumentException("timeout (must not be less than zero and different of -1.0)");
318                         
319                         m_task_t nativeTask = NULL;     
320                         
321                         if (MSG_OK != MSG_task_get_ext(&nativeTask, channel, timeout, rHost.nativeHost)) 
322                                 throw MsgException("MSG_task_get_ext() failed");
323                         
324                         return (Task*)(nativeTask->data);
325                 }
326                 
327                 void Process::sendTask(const char* alias, Task* task, double timeout) 
328                 throw(NullPointerException, InvalidArgumentException, MsgException)
329                 {
330                         // check the parameters
331                         
332                         if(!alias)
333                                 throw NullPointerException("alias");
334                         
335                         if(timeout < 0 && timeout !=-1.0)
336                                 throw InvalidArgumentException("timeout (the timeout value must not be negative and different than -1.0)");
337                         
338                         if(MSG_OK != MSG_task_send_with_timeout(task->nativeTask, alias ,timeout))
339                                 throw MsgException("MSG_task_send_with_timeout()");
340                                 
341                 }
342                 
343                 void Process::sendTask(const char* alias, Task* task) 
344                 throw(NullPointerException, MsgException)
345                 {
346                         // check the parameters
347                         
348                         if(!alias)
349                                 throw NullPointerException("alias");
350                                 
351                         if(MSG_OK != MSG_task_send_with_timeout(task->nativeTask, alias ,-1.0))
352                                 throw MsgException("MSG_task_send_with_timeout()");
353                 }
354                 
355                 void Process::sendTask(Task* task) 
356                 throw(BadAllocException, MsgException)
357                 {
358                         char* alias = (char*)calloc( strlen(this->getHost().getName()) + strlen(nativeProcess->name) + 2, sizeof(char));
359                                 
360                         if(!alias)
361                                 throw BadAllocException("alias");
362                                 
363                         sprintf(alias,"%s:%s", Host::currentHost().getName() ,nativeProcess->name);
364                         
365                         MSG_error_t rv = MSG_task_send_with_timeout(task->nativeTask, alias ,-1.0);
366                         
367                         free(alias);
368                         
369                         if(MSG_OK != rv)
370                                 throw MsgException("MSG_task_send_with_timeout()");
371                 }
372                 
373                 void Process::sendTask(Task* task, double timeout) 
374                 throw(BadAllocException, InvalidArgumentException, MsgException)
375                 {
376                         // check the parameters
377                         
378                         if(timeout < 0 && timeout !=-1.0)
379                                 throw InvalidArgumentException("timeout (the timeout value must not be negative and different than -1.0)");
380                         
381                         char* alias = (char*)calloc( strlen(this->getHost().getName()) + strlen(nativeProcess->name) + 2, sizeof(char));
382                                 
383                         if(!alias)
384                                 throw BadAllocException("alias");
385                                 
386                         sprintf(alias,"%s:%s", Host::currentHost().getName() ,nativeProcess->name);
387                         
388                         MSG_error_t rv = MSG_task_send_with_timeout(task->nativeTask, alias ,timeout);
389                         
390                         free(alias);
391                         
392                         if(MSG_OK != rv)
393                                 throw MsgException("MSG_task_send_with_timeout()");     
394                 }
395                 
396                 Task* Process::receiveTask(const char* alias) 
397                 throw(NullPointerException, MsgException)
398                 {
399                         // check the parameters
400                         
401                         if(!alias)
402                                 throw NullPointerException(alias);
403                                 
404                         m_task_t nativeTask = NULL;
405                         
406                         if (MSG_OK !=  MSG_task_receive_ext(&nativeTask,alias, -1.0, NULL)) 
407                                 throw MsgException("MSG_task_receive_ext() failed");
408                 
409                         return (Task*)(nativeTask->data);
410                 }
411                 
412                 
413                 Task* Process::receiveTask(void) 
414                 throw(BadAllocException, MsgException)
415                 {
416                         
417                         char* alias = (char*)calloc( strlen(this->getHost().getName()) + strlen(nativeProcess->name) + 2, sizeof(char));
418                         
419                         if(!alias)
420                                 throw BadAllocException("alias");       
421                         
422                         sprintf(alias,"%s:%s", Host::currentHost().getName() ,nativeProcess->name);
423                         
424                         m_task_t nativeTask = NULL;
425                         
426                         MSG_error_t rv = MSG_task_receive_ext(&nativeTask, alias, -1.0, NULL);
427                         
428                         free(alias);
429                         
430                         if(MSG_OK !=  rv) 
431                                 throw MsgException("MSG_task_receive_ext() failed");    
432                 
433                         return (Task*)(nativeTask->data);
434                 }
435                 
436                 
437                 Task* Process::receiveTask(const char* alias, double timeout) 
438                 throw(NullPointerException, InvalidArgumentException, MsgException)
439                 {
440                         // check the parameters
441                         
442                         if(!alias)
443                                 throw NullPointerException("alias");
444                                 
445                         if(timeout < 0 && timeout !=-1.0)
446                                 throw InvalidArgumentException("timeout (the timeout value must not be negative and different than -1.0)");
447                                 
448                         m_task_t nativeTask = NULL;
449                         
450                         if(MSG_OK !=  MSG_task_receive_ext(&nativeTask, alias, timeout, NULL)) 
451                                 throw MsgException("MSG_task_receive_ext() failed");            
452                 
453                         return (Task*)(nativeTask->data);
454                 }
455                 
456                 
457                 Task* Process::receiveTask(double timeout) 
458                 throw(InvalidArgumentException, BadAllocException, MsgException)
459                 {
460                         // check the parameters
461                         
462                         if(timeout < 0 && timeout !=-1.0)
463                                 throw InvalidArgumentException("timeout (the timeout value must not be negative and different than -1.0)");
464                                 
465                         
466                         char* alias = (char*)calloc( strlen(this->getHost().getName()) + strlen(nativeProcess->name) + 2, sizeof(char));
467                         
468                         if(!alias)
469                                 throw BadAllocException("alias");
470                         
471                         sprintf(alias,"%s:%s", Host::currentHost().getName() ,nativeProcess->name);
472                         
473                         m_task_t nativeTask = NULL;
474                         
475                         MSG_error_t rv = MSG_task_receive_ext(&nativeTask, alias, timeout, NULL);
476                         
477                         free(alias);
478                         
479                         if(MSG_OK !=  rv) 
480                                 throw MsgException("MSG_task_receive_ext() failed");    
481                 
482                         return (Task*)(nativeTask->data);
483                 }
484                 
485                 
486                 Task* Process::receiveTask(const char* alias, double timeout, const Host& rHost) 
487                 throw(NullPointerException, InvalidArgumentException, MsgException)
488                 {
489                         // check the parameters
490                         
491                         if(!alias)
492                                 throw NullPointerException("alias");
493                         
494                         if(timeout < 0 && timeout !=-1.0)
495                                 throw InvalidArgumentException("timeout (the timeout value must not be negative and different than -1.0)");
496                                 
497                         m_task_t nativeTask = NULL;
498                         
499                         if(MSG_OK !=  MSG_task_receive_ext(&nativeTask, alias, timeout, rHost.nativeHost)) 
500                                 throw MsgException("MSG_task_receive_ext() failed");
501                 
502                         return (Task*)(nativeTask->data);
503                 }
504                 
505                 
506                 Task* Process::receiveTask(double timeout, const Host& rHost) 
507                 throw(BadAllocException, InvalidArgumentException, MsgException)
508                 {
509                         // check the parameters
510                         
511                         if(timeout < 0 && timeout !=-1.0)
512                                 throw InvalidArgumentException("timeout (the timeout value must not be negative and different than -1.0)");
513                         
514                         char* alias = (char*)calloc( strlen(this->getHost().getName()) + strlen(nativeProcess->name) + 2, sizeof(char));
515                         
516                         if(!alias)
517                                 throw BadAllocException("alias");
518                                 
519                         sprintf(alias,"%s:%s", Host::currentHost().getName() ,nativeProcess->name);
520                         
521                         m_task_t nativeTask = NULL;
522                         
523                         MSG_error_t rv = MSG_task_receive_ext(&nativeTask, alias, timeout, rHost.nativeHost);
524                         
525                         free(alias);
526                         
527                         if(MSG_OK !=  rv) 
528                                 throw MsgException("MSG_task_receive_ext() failed");
529                 
530                         return (Task*)(nativeTask->data);
531                 }
532                 
533                 
534                 Task* Process::receiveTask(const char* alias, const Host& rHost) 
535                 throw(NullPointerException, MsgException)
536                 {
537                         
538                         // check the parameters
539                         
540                         if(!alias)
541                                 throw NullPointerException("alias");
542                         
543                         m_task_t nativeTask = NULL;
544                         
545                         if(MSG_OK !=   MSG_task_receive_ext(&nativeTask, alias, -1.0, rHost.nativeHost)) 
546                                 throw MsgException("MSG_task_receive_ext() failed");
547                 
548                         return (Task*)(nativeTask->data);
549                 }
550                 
551                 Task* Process::receiveTask(const Host& rHost) 
552                 throw(BadAllocException, MsgException)
553                 {
554                         char* alias = (char*)calloc( strlen(this->getHost().getName()) + strlen(nativeProcess->name) + 2, sizeof(char));
555                         
556                         if(!alias)
557                                 throw BadAllocException("alias");
558                         
559                         sprintf(alias,"%s:%s", Host::currentHost().getName() ,nativeProcess->name);
560                         
561                         m_task_t nativeTask = NULL;
562                         
563                         MSG_error_t rv = MSG_task_receive_ext(&nativeTask, alias, -1.0, rHost.nativeHost);
564                         
565                         free(alias);
566                         
567                         if(MSG_OK !=  rv) 
568                                 throw MsgException("MSG_task_receive_ext() failed");
569                 
570                         return (Task*)(nativeTask->data);
571                 }
572
573                 void Process::create(const Host& rHost, const char* name, int argc, char** argv)
574                 throw(InvalidArgumentException)
575                 {
576                         char alias[MAX_ALIAS_NAME + 1] = {0};
577                         msg_mailbox_t mailbox;
578                         
579                         
580                         // try to retrieve the host where to create the process from its name
581                         m_host_t nativeHost = rHost.nativeHost;
582                         
583                         if(!nativeHost)
584                                 throw InvalidArgumentException("rHost"); 
585                         
586                         /* allocate the data of the simulation */
587                         this->nativeProcess = xbt_new0(s_m_process_t,1);
588                         this->nativeProcess->simdata = xbt_new0(s_simdata_process_t,1);
589                         this->nativeProcess->name = _strdup(name);
590                         this->nativeProcess->simdata->m_host = nativeHost;
591                         this->nativeProcess->simdata->PID = msg_global->PID++;
592                         
593                         // realloc the list of the arguments to add the pointer to this process instance at the end
594                         if(argc)
595                         {
596                                 argv = (char**)realloc(argv , (argc + 2) * sizeof(char*));
597                         }
598                         else
599                         {
600                                 argv = (char**)calloc(2 ,sizeof(char*));
601                         }
602                         
603                         // add the pointer to this instance at the end of the list of the arguments of the process
604                         // so the static method Process::run() (passed as argument of the MSG function xbt_context_new())
605                         // can retrieve the concerned process object by the run
606                         // so Process::run() can call the method main() of the good process
607                         // for more detail see Process::run() method
608                         argv[argc] = NULL;
609                         argv[argc + 1] = (char*)this;
610
611                         this->nativeProcess->simdata->argc = argc;
612                         this->nativeProcess->simdata->argv = argv;
613                         
614                         this->nativeProcess->simdata->s_process = SIMIX_process_create(
615                                                                         this->nativeProcess->name,
616                                                                         Process::run, 
617                                                                         (void*)this->nativeProcess,
618                                                                         nativeHost->name, 
619                                                                         argc,
620                                                                         argv, 
621                                                                         NULL);
622                         
623                         if (SIMIX_process_self()) 
624                         {/* someone created me */
625                                 this->nativeProcess->simdata->PPID = MSG_process_get_PID((m_process_t)SIMIX_process_self()->data);
626                         } 
627                         else 
628                         {
629                                 this->nativeProcess->simdata->PPID = -1;
630                         }
631                         
632                         this->nativeProcess->simdata->last_errno = MSG_OK;
633                         
634                         /* add the process to the list of the processes of the simulation */
635                         xbt_fifo_unshift(msg_global->process_list, this->nativeProcess);
636                         
637                         sprintf(alias,"%s:%s",(this->nativeProcess->simdata->m_host->simdata->smx_host)->name,this->nativeProcess->name);
638                         
639                         mailbox = MSG_mailbox_new(alias);
640                         
641                         MSG_mailbox_set_hostname(mailbox, this->nativeProcess->simdata->m_host->simdata->smx_host->name);       
642                 }
643                 
644                 Process* Process::fromNativeProcess(m_process_t nativeProcess)
645                 {
646                         return ((Process*)(nativeProcess->simdata->argv[nativeProcess->simdata->argc + 1]));
647                         
648                 }
649                 
650                 int Process::run(int argc, char** argv)
651                 {
652                         
653                         // the last argument of the process is the pointer to the process to run
654                         // for more detail see Process::create() method
655                         return ((Process*)argv[argc + 1])->main(argc, argv);
656                         
657                 }
658
659                 int Process::main(int argc, char** argv)
660                 {
661                         throw LogicException("Process::main() not implemented");
662                 }
663
664                 /*void* Process::operator new(size_t size)
665                 {
666                         // TODO
667                 }
668
669                 void Process::operator delete(void* p)
670                 {
671                         // TODO
672                 }*/
673                 
674         } // namespace Msg
675
676 } // namespace SimGrid
677