VmApps: wrapperWeir.cpp

File wrapperWeir.cpp, 21.8 kB (added by dgquintas, 8 months ago)

actual code extracted from the rtf

Line 
1 // This file is part of BOINC.
2 // http://boinc.berkeley.edu
3 // Copyright (C) 2008 University of California
4 //
5 // BOINC is free software; you can redistribute it and/or modify it
6 // under the terms of the GNU Lesser General Public License
7 // as published by the Free Software Foundation,
8 // either version 3 of the License, or (at your option) any later version.
9 //
10 // BOINC is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13 // See the GNU Lesser General Public License for more details.
14 //
15 // You should have received a copy of the GNU Lesser General Public
16 // License
17 // along with BOINC.  If not, see <http://www.gnu.org/licenses/>.
18
19 // vmwrapper.C
20 // VMWare wrapper program - lets you use BOINC to drive a VMWare Server
21 // guest OS
22
23 #include <stdio.h>
24 #include <vector>
25 #include <string>
26 #ifdef _WIN32
27 #include "boinc_win.h"
28 #include "win_util.h"
29 #else
30 #include <sys/wait.h>
31 #include <sys/types.h>
32 #include <sys/stat.h>
33 #include <unistd.h>
34 #include "procinfo.h"
35 #endif
36
37 #include "boinc_api.h"
38 #include "diagnostics.h"
39 #include "filesys.h"
40 #include "parse.h"
41 #include "str_util.h"
42 #include "util.h"
43 #include "error_numbers.h"
44
45 #include "vmware-vix/vix.h"
46
47 #define JOB_FILENAME "job.xml"
48 #define CHECKPOINT_FILENAME "checkpoint.txt"
49
50 #define POLL_PERIOD 1.0
51
52 using std::vector;
53 using std::string;
54
55 struct TASK
56 {
57         string application;
58         string stdin_filename;
59         string stdout_filename;
60         string stderr_filename;
61
62         string vm;
63         string innerjob;
64         string datadir;
65         string partial_credit;
66         string snapshots;
67         string user;
68         string password;
69
70         vector < string > data;
71         vector < string > output;
72
73         string checkpoint_filename;
74         // name of task's checkpoint file, if any
75         double checkpoint_cpu_time;
76         // CPU time at last checkpoint
77         string command_line;
78         double weight;
79         // contribution of this task to overall fraction done
80         double final_cpu_time;
81         double starting_cpu;
82         // how much CPU time was used by tasks before this in the job file
83         bool    suspended;
84         double wall_cpu_time;
85         // for estimating CPU time on Win98/ME and Mac
86
87
88         #ifdef _WIN32
89
90         HANDLE pid_handle;
91         DWORD pid;
92         HANDLE thread_handle;
93         struct _stat last_stat;                          // mod time of checkpoint file
94
95         #else
96
97         int pid;
98         struct stat last_stat;
99
100         #endif
101
102
103         bool stat_first;
104         int parse (XML_PARSER &);
105         bool poll (int &status);
106         int run (int argc, char **argv);
107         void kill ();
108         void stop ();
109         void resume ();
110         double cpu_time ();
111
112         inline bool has_checkpointed ()
113         {
114                 bool changed = false;
115
116                 if (checkpoint_filename.size () == 0)
117                         return false;
118
119                 struct stat new_stat;
120
121                 int retval = stat (checkpoint_filename.c_str (), &new_stat);
122
123                 if (retval)
124                         return false;
125
126                 if (!stat_first && new_stat.st_mtime != last_stat.st_mtime)
127                 {
128                         changed = true;
129                 }
130
131                 stat_first = false;
132
133                 last_stat.st_mtime = new_stat.st_mtime;
134                 return changed;
135         }
136 };
137
138 vector < TASK > tasks;
139 APP_INIT_DATA aid;
140 bool graphics = false;
141
142 int TASK::parse (XML_PARSER & xp)
143 {
144
145         string this_data, this_output;
146         char tag[1024], buf[8192], buf2[8192];
147
148         bool is_tag;
149
150         weight = 1;
151         final_cpu_time = 0;
152         stat_first = true;
153         while (!xp.get (tag, sizeof (tag), is_tag))
154         {
155                 if (!is_tag)
156                 {
157                         fprintf (stderr, "SCHED_CONFIG::parse(): unexpected text %s\n",
158                                 tag);
159                         continue;
160                 }
161                 if (!strcmp (tag, "/task"))
162                 {
163                         return 0;
164                 }
165                 else if (xp.parse_string (tag, "application", application))
166                         continue;
167
168                 else if (xp.parse_string (tag, "innerjob", innerjob))
169                         continue;
170                 else if (xp.parse_string (tag, "vm", vm))
171                         continue;
172                 else if (xp.parse_string (tag, "datadir", datadir))
173                         continue;
174                 else if (xp.parse_string (tag, "partial_credit", partial_credit))
175                         continue;
176                 else if (xp.parse_string (tag, "snapshots", snapshots))
177                         continue;
178
179
180                 else if (xp.parse_string (tag, "data", this_data)) {
181                         data.push_back(this_data);
182                         continue;
183                 }
184
185                 else if (xp.parse_string (tag, "output", this_output)) {
186                         output.push_back(this_output);
187                         continue;
188                 }
189
190                 else if (xp.parse_string (tag, "user", user))
191                         continue;
192                 else if (xp.parse_string (tag, "password", password))
193                         continue;
194
195                 else if (xp.parse_string (tag, "stdin_filename", stdin_filename))
196                         continue;
197                 else if (xp.parse_string (tag, "stdout_filename", stdout_filename))
198                         continue;
199                 else if (xp.parse_string (tag, "stderr_filename", stderr_filename))
200                         continue;
201                 else if (xp.parse_str (tag, "command_line", buf, sizeof (buf)))
202                 {
203                         while (1)
204                         {
205                                 char *p = strstr (buf, "$PROJECT_DIR");
206
207                                 if (!p)
208                                         break;
209                                 strcpy (buf2, p + strlen ("$PROJECT_DIR"));
210                                 strcpy (p, aid.project_dir);
211                                 strcat (p, buf2);
212                         }
213                         command_line = buf;
214                         continue;
215                 }
216                 else if (xp.
217                         parse_string (tag, "checkpoint_filename",
218                         checkpoint_filename))
219                         continue;
220                 else if (xp.parse_double (tag, "weight", weight))
221                         continue;
222         }
223         return ERR_XML_PARSE;
224 }
225
226
227 int parse_job_file ()
228 {
229         MIOFILE mf;
230         char tag[1024], buf[256];
231
232         bool is_tag;
233
234         boinc_resolve_filename (JOB_FILENAME, buf, 1024);
235         FILE *f = boinc_fopen (buf, "r");
236
237         if (!f)
238         {
239                 fprintf (stderr, "can't open job file %s\n", buf);
240                 return ERR_FOPEN;
241         }
242         mf.init_file (f);
243         XML_PARSER xp (&mf);
244
245         if (!xp.parse_start ("job_desc"))
246                 return ERR_XML_PARSE;
247         while (!xp.get (tag, sizeof (tag), is_tag))
248         {
249                 if (!is_tag)
250                 {
251                         fprintf (stderr, "SCHED_CONFIG::parse(): unexpected text %s\n",
252                                 tag);
253                         continue;
254                 }
255                 if (!strcmp (tag, "/job_desc"))
256                 {
257                         fclose (f);
258                         return 0;
259                 }
260                 if (!strcmp (tag, "task"))
261                 {
262                         TASK task;
263                         int retval = task.parse (xp);
264
265                         if (!retval)
266                         {
267                                 tasks.push_back (task);
268                         }
269                 }
270         }
271         fclose (f);
272         return ERR_XML_PARSE;
273 }
274
275
276 #ifdef _WIN32
277 // CreateProcess() takes HANDLEs for the stdin/stdout.
278 // We need to use CreateFile() to get them.  Ugh.
279 //
280 HANDLE
281 win_fopen (const char *path, const char *mode)
282 {
283         SECURITY_ATTRIBUTES sa;
284         memset (&sa, 0, sizeof (sa));
285         sa.nLength = sizeof (sa);
286         sa.bInheritHandle = TRUE;
287
288         if (!strcmp (mode, "r"))
289         {
290                 return CreateFile (path,
291                         GENERIC_READ,
292                         FILE_SHARE_READ, &sa, OPEN_EXISTING, 0, 0);
293         }
294         else if (!strcmp (mode, "w"))
295         {
296                 return CreateFile (path,
297                         GENERIC_WRITE,
298                         FILE_SHARE_WRITE, &sa, OPEN_ALWAYS, 0, 0);
299         }
300         else if (!strcmp (mode, "a"))
301         {
302                 HANDLE
303                         hAppend = CreateFile (path,
304                         GENERIC_WRITE,
305                         FILE_SHARE_WRITE, &sa, OPEN_ALWAYS, 0, 0);
306                 SetFilePointer (hAppend, 0, NULL, FILE_END);
307                 return hAppend;
308         }
309         else
310         {
311                 return 0;
312         }
313 }
314 #endif
315
316 void slash_to_backslash (char *p)
317 {
318         while (1)
319         {
320                 char *q = strchr (p, '/');
321
322                 if (!q)
323                         break;
324                 *q = '\\';
325         }
326 }
327
328
329 int TASK::run (int argct, char **argvt)
330 {
331         string stdout_path, stdin_path, stderr_path;
332         char app_path[1024], buf[256];
333
334         strcpy (buf, application.c_str ());
335         char *p = strstr (buf, "$PROJECT_DIR");
336
337         if (p)
338         {
339                 p += strlen ("$PROJECT_DIR");
340                 sprintf (app_path, "%s%s", aid.project_dir, p);
341         }
342         else
343         {
344                 boinc_resolve_filename (buf, app_path, sizeof (app_path));
345         }
346
347         // Append wrapper's command-line arguments to those in the job file.
348         //
349         for (int i = 1; i < argct; i++)
350         {
351                 command_line += argvt[i];
352                 if ((i + 1) < argct)
353                 {
354                         command_line += string (" ");
355                 }
356         }
357
358         fprintf (stderr, "wrapper: running %s (%s)\n",
359                 app_path, command_line.c_str ());
360
361         #ifdef _WIN32
362         PROCESS_INFORMATION process_info;
363         STARTUPINFO startup_info;
364         string command;
365
366         slash_to_backslash (app_path);
367         memset (&process_info, 0, sizeof (process_info));
368         memset (&startup_info, 0, sizeof (startup_info));
369         command = string ("\"") + app_path + string ("\" ") + command_line;
370
371         // pass std handles to app
372         //
373         startup_info.dwFlags = STARTF_USESTDHANDLES;
374         if (stdout_filename != "")
375         {
376                 boinc_resolve_filename_s (stdout_filename.c_str (), stdout_path);
377                 startup_info.hStdOutput = win_fopen (stdout_path.c_str (), "a");
378         }
379         if (stdin_filename != "")
380         {
381                 boinc_resolve_filename_s (stdin_filename.c_str (), stdin_path);
382                 startup_info.hStdInput = win_fopen (stdin_path.c_str (), "r");
383         }
384         if (stderr_filename != "")
385         {
386                 boinc_resolve_filename_s (stderr_filename.c_str (), stderr_path);
387                 startup_info.hStdError = win_fopen (stderr_path.c_str (), "a");
388         }
389         else
390         {
391                 startup_info.hStdError = win_fopen (STDERR_FILE, "a");
392         }
393
394                                                                  // bInheritHandles
395         if (!CreateProcess (app_path, (LPSTR) command.c_str (), NULL, NULL, TRUE,
396                 CREATE_NO_WINDOW | IDLE_PRIORITY_CLASS,
397                 NULL, NULL, &startup_info, &process_info))
398         {
399                 return ERR_EXEC;
400         }
401         pid_handle = process_info.hProcess;
402         pid = process_info.dwProcessId;
403         thread_handle = process_info.hThread;
404         SetThreadPriority (thread_handle, THREAD_PRIORITY_IDLE);
405         #else
406         int retval, argc;
407         char progname[256];
408         char *argv[256];
409         char arglist[4096];
410         FILE *stdout_file;
411         FILE *stdin_file;
412         FILE *stderr_file;
413
414         pid = fork ();
415         if (pid == -1)
416         {
417                 boinc_finish (ERR_FORK);
418         }
419         if (pid == 0)
420         {
421                 // we're in the child process here
422                 //
423                 // open stdout, stdin if file names are given
424                 // NOTE: if the application is restartable,
425                 // we should deal with atomicity somehow
426                 //
427                 if (stdout_filename != "")
428                 {
429                         boinc_resolve_filename_s (stdout_filename.c_str (), stdout_path);
430                         stdout_file = freopen (stdout_path.c_str (), "a", stdout);
431                         if (!stdout_file)
432                                 return ERR_FOPEN;
433                 }
434                 if (stdin_filename != "")
435                 {
436                         boinc_resolve_filename_s (stdin_filename.c_str (), stdin_path);
437                         stdin_file = freopen (stdin_path.c_str (), "r", stdin);
438                         if (!stdin_file)
439                                 return ERR_FOPEN;
440                 }
441                 if (stderr_filename != "")
442                 {
443                         boinc_resolve_filename_s (stderr_filename.c_str (), stderr_path);
444                         stderr_file = freopen (stderr_path.c_str (), "a", stderr);
445                         if (!stderr_file)
446                                 return ERR_FOPEN;
447                 }
448                 // construct argv
449                 // TODO: use malloc instead of stack var
450                 //
451                 argv[0] = app_path;
452                 strlcpy (arglist, command_line.c_str (), sizeof (arglist));
453                 argc = parse_command_line (arglist, argv + 1);
454                 setpriority (PRIO_PROCESS, 0, PROCESS_IDLE_PRIORITY);
455                 retval = execv (app_path, argv);
456                 exit (ERR_EXEC);
457         }
458         #endif
459         wall_cpu_time = 0;
460         suspended = false;
461         return 0;
462 }
463
464
465 bool TASK::poll (int &status)
466 {
467         if (!suspended)
468                 wall_cpu_time += POLL_PERIOD;
469         #ifdef _WIN32
470         unsigned long
471                 exit_code;
472
473         if (GetExitCodeProcess (pid_handle, &exit_code))
474         {
475                 if (exit_code != STILL_ACTIVE)
476                 {
477                         status = exit_code;
478                         final_cpu_time = cpu_time ();
479                         return true;
480                 }
481         }
482         #else
483         int
484                 wpid,
485                 stat;
486         struct rusage
487                 ru;
488
489         wpid = wait4 (pid, &status, WNOHANG, &ru);
490         if (wpid)
491         {
492                 final_cpu_time =
493                         (float) ru.ru_utime.tv_sec + ((float) ru.ru_utime.tv_usec) / 1e+6;
494                 return true;
495         }
496         #endif
497         return false;
498 }
499
500
501 void TASK::kill ()
502 {
503         #ifdef _WIN32
504         TerminateProcess (pid_handle, -1);
505         #else
506         ::kill (pid, SIGKILL);
507         #endif
508 }
509
510
511 void TASK::stop ()
512 {
513         suspended = true;
514 }
515
516
517 void TASK::resume ()
518 {
519         suspended = false;
520 }
521
522
523
524
525 double TASK::cpu_time ()
526 {
527         #ifdef _WIN32
528         FILETIME creation_time, exit_time, kernel_time, user_time;
529         ULARGE_INTEGER tKernel, tUser;
530         LONGLONG totTime;
531
532         int retval = GetProcessTimes (pid_handle, &creation_time, &exit_time,
533                 &kernel_time,
534                 &user_time);
535
536         if (retval == 0)
537         {
538                 return wall_cpu_time;
539         }
540
541         tKernel.LowPart = kernel_time.dwLowDateTime;
542         tKernel.HighPart = kernel_time.dwHighDateTime;
543         tUser.LowPart = user_time.dwLowDateTime;
544         tUser.HighPart = user_time.dwHighDateTime;
545         totTime = tKernel.QuadPart + tUser.QuadPart;
546
547         return totTime / 1.e7;
548         #elif defined(__APPLE__)
549         // There's no easy way to get another process's CPU time in Mac OS X
550         //
551         return wall_cpu_time;
552         #else
553         return linux_cpu_time (pid);
554         #endif
555 }
556
557
558
559
560 // Support for multiple tasks.
561 // We keep a checkpoint file that says how many tasks we've completed
562 // and how much CPU time has been used so far
563 //
564 void write_checkpoint (int ntasks, double cpu)
565 {
566         FILE *f = fopen (CHECKPOINT_FILENAME, "w");
567
568         if (!f)
569                 return;
570         fprintf (f, "%d %f\n", ntasks, cpu);
571         fclose (f);
572 }
573
574
575 void read_checkpoint (int &ntasks, double &cpu)
576 {
577         int nt;
578         double c;
579
580         ntasks = 0;
581         cpu = 0;
582         FILE *f = fopen (CHECKPOINT_FILENAME, "r");
583
584         if (!f)
585                 return;
586         int n = fscanf (f, "%d %lf", &nt, &c);
587
588         fclose (f);
589         if (n != 2)
590                 return;
591         ntasks = nt;
592         cpu = c;
593 }
594
595
596
597 void check_vm_result(VixError err, VixHandle hostHandle, string errorString)
598 {
599         if (VIX_OK != err)
600         {
601                 fprintf (stderr, "\n\n Error: %s\n",errorString.c_str());
602                 fprintf (stderr, "Error message: \"%s\"\n", Vix_GetErrorText (err, NULL));
603                 VixHost_Disconnect (hostHandle);
604                 boinc_finish(100);
605         }
606 }
607
608 int main (int argc, char **argv)
609 {
610
611         BOINC_OPTIONS options;
612         int retval, ntasks;
613         unsigned int i;
614         double cpu, total_weight = 0, w = 0;
615
616         for (i = 1; i < (unsigned int) argc; i++)
617         {
618                 if (!strcmp (argv[i], "--graphics"))
619                 {
620                         graphics = true;
621                 }
622         }
623
624         memset (&options, 0, sizeof (options));
625         options.main_program = true;
626         options.check_heartbeat = true;
627         options.handle_process_control = true;
628         if (graphics)
629         {
630                 options.backwards_compatible_graphics = true;
631         }
632
633         // boinc_init_options(&options);
634
635         fprintf (stderr, "vmwrapper: starting\n");
636
637         boinc_get_init_data (aid);
638
639         retval = parse_job_file ();
640         if (retval)
641         {
642                 fprintf (stderr, "can't parse job file: %d\n", retval);
643                 boinc_finish (retval);
644         }
645
646         read_checkpoint (ntasks, cpu);
647         if (ntasks > (int) tasks.size ())
648         {
649                 fprintf (stderr, "Checkpoint file: ntasks %d too large\n", ntasks);
650                 boinc_finish (1);
651         }
652
653         for (i = 0; i < tasks.size (); i++)
654         {
655                 total_weight += tasks[i].weight;
656         }
657
658
659
660
661         VixHandle hostHandle = VIX_INVALID_HANDLE;
662         VixHandle jobHandle = VIX_INVALID_HANDLE;
663         VixError err;
664         string vmxFilename;
665
666         jobHandle = VixHost_Connect (VIX_API_VERSION, VIX_SERVICEPROVIDER_VMWARE_SERVER, NULL, 0, NULL, NULL, 0, VIX_INVALID_HANDLE, NULL, NULL);
667
668         err = VixJob_Wait (jobHandle, VIX_PROPERTY_JOB_RESULT_HANDLE, &hostHandle, VIX_PROPERTY_NONE);
669
670         if (VIX_OK != err)
671         {
672                 fprintf (stderr, "Unable to connect to server!\n");
673                 fprintf (stderr, "Error message: \"%s\"\n", Vix_GetErrorText (err, NULL));
674                 VixHost_Disconnect (hostHandle);
675                 boinc_finish(1);
676         }
677
678         fprintf (stderr, "Connected to server.\n");
679
680
681         Vix_ReleaseHandle (jobHandle);
682         jobHandle = VIX_INVALID_HANDLE;
683
684
685         for (i = 0; i < tasks.size (); i++)
686         {
687
688                 fprintf(stderr,"Processing task %d.\n", i);
689
690                 TASK & task = tasks[i];
691
692                 // w += task.weight;
693
694                 // this line is to do with cpu time storage
695                 // if ((int) i < ntasks)
696                 //      continue;
697
698                 double frac_done = w / total_weight;
699
700
701                 fprintf(stderr, "Task %d.\n========\n\n", i+1);
702
703
704                 fprintf(stderr, "VM file root is %s\n", task.vm.c_str ());
705
706                 string vm_file_in_1, vm_file_in_2;
707                 char vm_file_1[1024], vm_file_2[1024];
708
709                 string pwd = get_current_dir_name ();
710
711
712                 // VMWare Server 1 requires full path
713                 vm_file_in_1 = pwd + "/" + task.vm + ".vmx";
714                 vm_file_in_2 = pwd + "/" + task.vm + ".vmdk";
715
716 //              fprintf (stderr, "Input filenames are %s, %s\n",
717 //                      vm_file_in_1.c_str (), vm_file_in_2.c_str ());
718
719                 boinc_resolve_filename (vm_file_in_1.c_str (), vm_file_1, 1024);
720                 boinc_resolve_filename (vm_file_in_2.c_str (), vm_file_2, 1024);
721
722 //              fprintf (stderr, "Resolved to %s, %s\n", vm_file_1, vm_file_2);
723
724                 if (access (vm_file_1, R_OK))
725                 {
726                         fprintf (stderr, "Unable to access VM file %s!\n",vm_file_1);
727                         boinc_finish (1);
728                 }
729
730                 if (access (vm_file_2, R_OK))
731                 {
732                         fprintf (stderr, "Unable to access VM file %s!\n",vm_file_2);
733                         boinc_finish (1);
734                 }
735
736
737                 // Register VM
738                 jobHandle = VixHost_RegisterVM (hostHandle, vm_file_1, NULL, NULL);
739                 err = VixJob_Wait (jobHandle, VIX_PROPERTY_NONE);
740                 check_vm_result(err, hostHandle, "Unable to register VM.");
741                 fprintf (stderr, "Registered virtual machine with the server.\n");
742
743                 VixHandle vmHandle = VIX_INVALID_HANDLE;
744
745                 // Open VM
746                 jobHandle = VixVM_Open (hostHandle, vm_file_1, NULL, NULL);
747                 err = VixJob_Wait (jobHandle, VIX_PROPERTY_JOB_RESULT_HANDLE, &vmHandle, VIX_PROPERTY_NONE);
748                 check_vm_result(err, hostHandle, "Unable to open VM.");
749                 fprintf (stderr, "Got handle.\n");
750
751                 // Power on VM
752                 jobHandle = VixVM_PowerOn (vmHandle, 0, VIX_INVALID_HANDLE, NULL, NULL);
753                 err = VixJob_Wait (jobHandle, VIX_PROPERTY_NONE);
754                 check_vm_result(err, hostHandle, "Unable to power on VM.");
755                 fprintf (stderr, "VM is now on (if it wasn't already).\n");
756
757                 // Wait for guest OS to start
758                 jobHandle = VixVM_WaitForToolsInGuest (vmHandle, 0, NULL, NULL);
759                 err = VixJob_Wait (jobHandle, VIX_PROPERTY_NONE);
760                 check_vm_result(err, hostHandle, "Did not get confirmation of VMWare Tools.");
761
762                 // Log in
763                 jobHandle = VixVM_LoginInGuest (vmHandle, task.user.c_str(), task.password.c_str(), 0, NULL, NULL);
764                 err = VixJob_Wait (jobHandle, VIX_PROPERTY_NONE);
765                 check_vm_result(err, hostHandle, "Unable to log in.");
766                 fprintf (stderr, "Logged in. Preparing job...\n");
767
768
769                 string guestfile = task.datadir +  "/" + task.innerjob;
770                 string st_hostfile = pwd + "/" + task.innerjob;
771                 char hostfile[1024];
772
773                 boinc_resolve_filename (st_hostfile.c_str (), hostfile, 1024);
774
775                 jobHandle = VixVM_CopyFileFromHostToGuest (vmHandle, hostfile, guestfile.c_str(), 0, VIX_INVALID_HANDLE, NULL, NULL);
776                 err = VixJob_Wait (jobHandle, VIX_PROPERTY_NONE);
777                 check_vm_result(err, hostHandle, "Unable to copy executable.");
778
779                 Vix_ReleaseHandle (jobHandle);
780
781                 // Changing permissions, do we really need to do this?
782                 jobHandle = VixVM_RunProgramInGuest (vmHandle, "/bin/chmod", ("+x " + guestfile).c_str (), 0, VIX_INVALID_HANDLE, NULL, NULL); 
783                 err = VixJob_Wait (jobHandle, VIX_PROPERTY_NONE);
784                 check_vm_result(err, hostHandle, "Unable to change permissions.");
785
786                 Vix_ReleaseHandle (jobHandle);
787
788
789                 fprintf (stderr, "Copying in input...\n");
790
791                 for(int files=0;files<task.data.size();files++)
792                 {
793                         fprintf(stderr,"Processing: %s\n",task.data[files].c_str());
794
795                         // should use boinc_resolve_filename here
796                         jobHandle = VixVM_CopyFileFromHostToGuest (vmHandle, (pwd + "/" + task.data[files]).c_str(), (task.datadir + "/" + task.data[files]).c_str(),
797                                 0, VIX_INVALID_HANDLE,  NULL, NULL);
798                         err = VixJob_Wait (jobHandle, VIX_PROPERTY_NONE);
799                         check_vm_result(err, hostHandle, "Error copying in file.");
800
801                         Vix_ReleaseHandle (jobHandle);
802
803                 }
804
805
806
807
808
809
810                 // Run the target program.
811                 fprintf (stderr, "Running main program: ");
812                 jobHandle = VixVM_RunProgramInGuest (vmHandle, guestfile.c_str (), "", 0, VIX_INVALID_HANDLE, NULL, NULL);
813
814                 Bool complete=false;
815
816                 task.starting_cpu = cpu;
817                 task.checkpoint_cpu_time = cpu;
818
819
820                 BOINC_STATUS status;
821                 VixHandle innerJobHandle;
822                 VixHandle snapshotHandle;
823
824                 while(!complete)
825                 {
826                         if(boinc_time_to_checkpoint())
827                                 fprintf(stderr,"Time to checkpoint run here...\n");
828
829
830
831                         boinc_get_status (&status);
832
833                         if (status.no_heartbeat || status.quit_request || status.abort_request)
834                         {
835                                 VixHost_Disconnect (hostHandle);
836                                 boinc_finish(0);
837                         }
838
839
840                         // contents of this control structure needs fixing, since suspend doesn't work
841                         if (status.suspended)
842                         {
843                                 if (!task.suspended)
844                                 {
845                                         // innerJobHandle = VixVM_Suspend(vmHandle,0,VIX_INVALID_HANDLE,NULL,NULL);
846                                         // err = VixJob_Wait(innerJobHandle, VIX_PROPERTY_JOB_RESULT_HANDLE, &snapshotHandle, VIX_PROPERTY_NONE);
847                                         // check_vm_result(err, hostHandle, "Error pausing VM.");
848                                         task.stop();
849                                 }
850                         }
851                         else
852                         {
853                                 if (task.suspended)
854                                 {
855                                         // innerJobHandle = VixVM_Unpause(vmHandle,0,VIX_INVALID_HANDLE,NULL,NULL);
856                                         // err = VixJob_Wait(innerJobHandle, VIX_PROPERTY_JOB_RESULT_HANDLE, &snapshotHandle, VIX_PROPERTY_NONE);
857                                         // check_vm_result(err, hostHandle, "Error unpausing VM.");
858                                         task.resume ();
859                                 }
860                         }
861
862
863                         // send_status_message (task, frac_done);
864                         // fprintf(stderr,"Partial credit check here...\n");
865
866                         // double current_cpu_time = task.starting_cpu + task.cpu_time ();
867
868                         // if (task.has_checkpointed ())
869                         // {
870                         //      task.checkpoint_cpu_time = current_cpu_time;
871                         // }
872
873                         // not sure how to do this yet
874                         // boinc_report_app_status (current_cpu_time, task.checkpoint_cpu_time, frac_done);
875
876
877                         boinc_sleep(POLL_PERIOD);
878
879
880                         if(!task.suspended) {
881                                 err = VixJob_CheckCompletion(jobHandle, &complete);
882                                 check_vm_result(err, hostHandle, "Error polling for job completion.");
883                         }
884                 }
885
886
887                 cpu += task.final_cpu_time;
888                 // write_checkpoint here is necessary to keep track of CPU time
889                 // we either use the time measured, or the time from within
890                 write_checkpoint (i + 1, cpu);
891
892                 err = VixJob_Wait (jobHandle, VIX_PROPERTY_NONE);
893                 check_vm_result(err, hostHandle, "Error running target program.");
894                 fprintf (stderr, "done.\n");
895
896
897
898
899                 Vix_ReleaseHandle (jobHandle);
900
901        
902                 fprintf(stderr, "Copying out output...\n");
903
904                 for(int files=0;files<task.output.size();files++)
905                 {
906                         fprintf(stderr,"Processing: %s\n",task.output[files].c_str());
907
908
909                         // FIXME: need to tell BOINC about these files
910                         jobHandle = VixVM_CopyFileFromGuestToHost (vmHandle, (task.datadir + "/" + task.output[0]).c_str(),
911                                 (pwd + "/" + task.output[files]).c_str (), 0, VIX_INVALID_HANDLE, NULL, NULL);
912                         err = VixJob_Wait (jobHandle, VIX_PROPERTY_NONE);
913                         check_vm_result(err, hostHandle, "Error copying out file.");
914
915                         Vix_ReleaseHandle (jobHandle);
916
917                         jobHandle = VixVM_RunProgramInGuest (vmHandle, "/bin/rm",  (task.datadir + "/" + task.output[files]).c_str(), 0, VIX_INVALID_HANDLE, NULL, NULL);       
918                         err = VixJob_Wait (jobHandle, VIX_PROPERTY_NONE);
919                         check_vm_result(err, hostHandle, "Error deleting file.");
920
921                         Vix_ReleaseHandle (jobHandle);
922                 }
923
924
925                 // now delete the executable, the output and the data
926                 fprintf(stderr, "Sanitising virtual machine...\n");
927
928                 for(int files=0;files<task.data.size();files++)
929                 {
930                         fprintf(stderr,"Removing: %s\n",task.data[files].c_str());
931
932                         jobHandle = VixVM_RunProgramInGuest (vmHandle, "/bin/rm",  (task.datadir + "/" + task.data[files]).c_str(), 0, VIX_INVALID_HANDLE, NULL, NULL);
933                         err = VixJob_Wait (jobHandle, VIX_PROPERTY_NONE);
934                         check_vm_result(err, hostHandle, "Error deleting file.");
935
936                         Vix_ReleaseHandle (jobHandle);
937                 }
938
939
940                 fprintf(stderr,"Removing executable.\n");
941                 jobHandle = VixVM_RunProgramInGuest (vmHandle, "/bin/rm",  guestfile.c_str(), 0, VIX_INVALID_HANDLE, NULL, NULL);       
942                 err = VixJob_Wait (jobHandle, VIX_PROPERTY_NONE);
943                 check_vm_result(err, hostHandle, "Error deleting file.");
944
945                 Vix_ReleaseHandle (jobHandle);
946
947        
948
949         }
950
951         boinc_finish (0);
952 }
953
954
955 #ifdef _WIN32
956
957 int WINAPI
958 WinMain (HINSTANCE hInst, HINSTANCE hPrevInst, LPSTR Args, int WinMode)
959 {
960         LPSTR command_line;
961         char *argv[100];
962         int argc;
963
964         command_line = GetCommandLine ();
965         argc = parse_command_line (command_line, argv);
966         return main (argc, argv);
967 }
968 #endif

If this page is incomplete or incorrect, please edit it or add it to the wiki to-do list. To do this, you must be logged in; click Login or Register above.