]> git.donarmstrong.com Git - mothur.git/blob - engine.cpp
added [ERROR] flag if command aborts
[mothur.git] / engine.cpp
1 /*
2  *  engine.cpp
3  *  
4  *
5  *  Created by Pat Schloss on 8/15/08.
6  *  Copyright 2008 Patrick D. Schloss. All rights reserved.
7  *
8  *  There's a TON of duplicated code between InteractEngine and BatchEngine
9  *  I couldn't figure out how to transition between ifstream (batch) and cin (interact)
10  *  Fix later, don't have time now.
11  *
12  */
13
14
15 #include "engine.hpp"
16
17 /***********************************************************************/
18 Engine::Engine(){
19         try {
20                 cFactory = CommandFactory::getInstance();
21                 mout = MothurOut::getInstance();
22         }
23         catch(exception& e) {
24                 mout->errorOut(e, "Engine", "Engine");
25                 exit(1);
26         }
27 }
28
29 /***********************************************************************/
30
31 InteractEngine::InteractEngine(string path){
32
33         globaldata = GlobalData::getInstance();
34         
35         string temppath = path.substr(0, (path.find_last_of('m')));
36         
37         //this will happen if you set the path variable to contain mothur's exe location
38         if (temppath == "") { 
39         
40                 string envPath = getenv("PATH");
41                 
42                 //delimiting path char
43                 char delim;
44                 #if defined (__APPLE__) || (__MACH__) || (linux) || (__linux)
45                         delim = ':';
46                 #else
47                         delim = ';';
48                 #endif
49                 
50                 //break apart path variable by ':'
51                 vector<string> dirs;
52                 mout->splitAtChar(envPath, dirs, delim);
53                 
54                 //get path related to mothur
55                 string mothurPath = "";
56                 for (int i = 0; i < dirs.size(); i++) {
57                         //to lower so we can find it
58                         string tempLower = "";
59                         for (int j = 0; j < dirs[i].length(); j++) {  tempLower += tolower(dirs[i][j]);  }
60                         
61                         //is this mothurs path?
62                         if (tempLower.find("mothur") != -1) {  mothurPath = dirs[i]; break;  }
63                 }
64                 
65                 //add mothur so it looks like what argv would look like
66                 #if defined (__APPLE__) || (__MACH__) || (linux) || (__linux)
67                         mothurPath += "/mothur";
68                 #else
69                         mothurPath += "\\mothur";
70                 #endif
71                 
72                 path = mothurPath;
73         }
74         
75         globaldata->argv = path;
76 }
77
78 /***********************************************************************/
79
80 InteractEngine::~InteractEngine(){}
81
82 /***********************************************************************/
83 //This function allows the user to input commands one line at a time until they quit.
84 //If the command is garbage it does nothing.
85 bool InteractEngine::getInput(){
86         try {
87                 string input = "";
88                 string commandName = "";
89                 string options = "";
90                 int quitCommandCalled = 0;
91                 
92                 while(quitCommandCalled != 1){
93
94                         #ifdef USE_MPI
95                                 int pid, processors;
96                                 MPI_Status status;
97                                 MPI_Comm_rank(MPI_COMM_WORLD, &pid); 
98                                 MPI_Comm_size(MPI_COMM_WORLD, &processors);
99                                 
100                                 if (pid == 0) {
101                                 
102                         #endif
103                         
104                         mout->mothurOutEndLine();
105                         
106                         input = getCommand();   
107                         mout->mothurOutEndLine();       
108                         
109                         if (mout->control_pressed) { input = "quit()"; }
110                         
111                         //allow user to omit the () on the quit command
112                         if (input == "quit") { input = "quit()"; }
113
114                         
115                         #ifdef USE_MPI
116                                 //send commandName
117                                 for(int i = 1; i < processors; i++) { 
118                                                 int length = input.length();
119                                                 MPI_Send(&length, 1, MPI_INT, i, 2001, MPI_COMM_WORLD);
120                                                 MPI_Send(&input[0], length, MPI_CHAR, i, 2001, MPI_COMM_WORLD);
121         
122                                         }
123                                 }else {
124                                         int length;
125                                         MPI_Recv(&length, 1, MPI_INT, 0, 2001, MPI_COMM_WORLD, &status);
126                                         //recieve container
127                                         char* tempBuf = new char[length];
128                                         MPI_Recv(&tempBuf[0], length, MPI_CHAR, 0, 2001, MPI_COMM_WORLD, &status);
129                                         
130                                         input = tempBuf;
131                                         if (input.length() > length) { input = input.substr(0, length);  }
132                                         delete tempBuf; 
133                                 }
134
135                         
136                         #endif
137                 
138                         CommandOptionParser parser(input);
139                         commandName = parser.getCommandString();
140         
141                         options = parser.getOptionString();
142                         
143                         if (commandName != "") {
144                                         mout->executing = true;
145                                         #ifdef USE_MPI
146                                                 int pid;
147                                                 MPI_Comm_rank(MPI_COMM_WORLD, &pid); 
148                                                 
149                                                 if ((cFactory->MPIEnabled(commandName)) || (pid == 0)) {
150                                         //cout << pid << " is in execute " << commandName << endl;
151                                         #endif
152                                         //executes valid command
153                                         Command* command = cFactory->getCommand(commandName, options);
154                                         quitCommandCalled = command->execute();
155                                                         
156                                         //if we aborted command
157                                         if (quitCommandCalled == 2) {  mout->mothurOut("[ERROR]: did not complete " + commandName + "."); mout->mothurOutEndLine(); }
158
159                                         mout->control_pressed = 0;
160                                         mout->executing = false;
161                                                                                 
162                                         #ifdef USE_MPI
163                                                 }
164                                         #endif
165                                 }else {         
166                                         mout->mothurOut("Invalid."); 
167                                         mout->mothurOutEndLine();
168                                 }
169                 }       
170                 return 1;
171         }
172         catch(exception& e) {
173                 mout->errorOut(e, "InteractEngine", "getInput");
174                 exit(1);
175         }
176 }
177 /***********************************************************************/
178 string Engine::getCommand()  {
179         try {
180         
181                 #if defined (__APPLE__) || (__MACH__) || (linux) || (__linux)
182                         #ifdef USE_READLINE
183                                 char* nextCommand = NULL;
184                                 nextCommand = readline("mothur > ");
185                                 
186                                 if(nextCommand != NULL) {  add_history(nextCommand);  } 
187                                 else{ //^D causes null string and we want it to quit mothur
188                                         strcpy(nextCommand, "quit"); 
189                                         mout->mothurOut(nextCommand);
190                                 }       
191                                 
192                                 mout->mothurOutJustToLog("mothur > " + toString(nextCommand));
193                                 return nextCommand;
194                         #else
195                                 string nextCommand = "";
196                                 mout->mothurOut("mothur > ");
197                                 getline(cin, nextCommand);
198                                 mout->mothurOutJustToLog("mothur > " + toString(nextCommand));
199                                 
200                                 return nextCommand;
201                         #endif
202                 #else
203                                 string nextCommand = "";
204                                 
205                                 mout->mothurOut("mothur > ");
206                                 getline(cin, nextCommand);
207                                 mout->mothurOutJustToLog(toString(nextCommand));
208                                 
209                                 return nextCommand;
210                 #endif
211         
212                                                 
213         }
214         catch(exception& e) {
215                 mout->errorOut(e, "Engine", "getCommand");
216                 exit(1);
217         }
218 }
219 /***********************************************************************/
220 //This function opens the batchfile to be used by BatchEngine::getInput.
221 BatchEngine::BatchEngine(string path, string batchFileName){
222         try {
223                 globaldata = GlobalData::getInstance();
224         
225                 openedBatch = mout->openInputFile(batchFileName, inputBatchFile);
226                 
227                 string temppath = path.substr(0, (path.find_last_of('m')));
228         
229                 //this will happen if you set the path variable to contain mothur's exe location
230                 if (temppath == "") { 
231                 
232                         string envPath = getenv("PATH");
233                         
234                         //delimiting path char
235                         char delim;
236                         #if defined (__APPLE__) || (__MACH__) || (linux) || (__linux)
237                                 delim = ':';
238                         #else
239                                 delim = ';';
240                         #endif
241                         
242                         //break apart path variable by ':'
243                         vector<string> dirs;
244                         mout->splitAtChar(envPath, dirs, delim);
245                         
246                         //get path related to mothur
247                         string mothurPath = "";
248                         for (int i = 0; i < dirs.size(); i++) {
249                                 //to lower so we can find it
250                                 string tempLower = "";
251                                 for (int j = 0; j < dirs[i].length(); j++) {  tempLower += tolower(dirs[i][j]);  }
252                                 
253                                 //is this mothurs path?
254                                 if (tempLower.find("mothur") != -1) {  mothurPath = dirs[i]; break;  }
255                         }
256                         
257                         //add mothur so it looks like what argv would look like
258                         #if defined (__APPLE__) || (__MACH__) || (linux) || (__linux)
259                                 mothurPath += "/mothur";
260                         #else
261                                 mothurPath += "\\mothur";
262                         #endif
263                         
264                         path = mothurPath;
265                 }
266
267                 globaldata->argv = path;
268                                 
269         }
270         catch(exception& e) {
271                 mout->errorOut(e, "BatchEngine", "BatchEngine");
272                 exit(1);
273         }
274 }
275
276 /***********************************************************************/
277
278 BatchEngine::~BatchEngine(){    }
279
280 /***********************************************************************/
281 //This Function allows the user to run a batchfile containing several commands on Dotur
282 bool BatchEngine::getInput(){
283         try {
284                 //check if this is a valid batchfile
285                 if (openedBatch == 1) {  
286                         mout->mothurOut("unable to open batchfile");  
287                         mout->mothurOutEndLine();
288                         return 1; 
289                 }
290         
291                 string input = "";
292                 string commandName = "";
293                 string options = "";
294                 
295                 //CommandFactory cFactory;
296                 int quitCommandCalled = 0;
297             int count = 0;
298                 while(quitCommandCalled != 1){
299                         
300                         #ifdef USE_MPI
301                                 int pid, processors;
302                                 MPI_Status status;
303                                 MPI_Comm_rank(MPI_COMM_WORLD, &pid); 
304                                 MPI_Comm_size(MPI_COMM_WORLD, &processors);
305                                 
306                                 if (pid == 0) {
307                                 
308                         #endif
309                         
310                         input = getNextCommand(inputBatchFile);
311                         count++;
312                         
313                         #ifdef USE_MPI
314                                 //send commandName
315                                 for(int i = 1; i < processors; i++) { 
316                                                 int length = input.length();
317                                                 MPI_Send(&length, 1, MPI_INT, i, 2001, MPI_COMM_WORLD);
318                                                 MPI_Send(&input[0], length, MPI_CHAR, i, 2001, MPI_COMM_WORLD);
319         
320                                         }
321                                 }else {
322                                         int length;
323                                         MPI_Recv(&length, 1, MPI_INT, 0, 2001, MPI_COMM_WORLD, &status);
324                                         //recieve container
325                                         char* tempBuf = new char[length];
326                                         MPI_Recv(&tempBuf[0], length, MPI_CHAR, 0, 2001, MPI_COMM_WORLD, &status);
327                                         
328                                         input = tempBuf;
329                                         if (input.length() > length) { input = input.substr(0, length);  }
330                                         delete tempBuf; 
331                                 }
332
333                         
334                         #endif
335
336                         
337                         
338                         if (input[0] != '#') {
339                                 
340                                 mout->mothurOutEndLine();
341                                 mout->mothurOut("mothur > " + input);
342                                 mout->mothurOutEndLine();
343                                                         
344                                 if (mout->control_pressed) { input = "quit()"; }
345                                 
346                                 //allow user to omit the () on the quit command
347                                 if (input == "quit") { input = "quit()"; }
348
349                                 CommandOptionParser parser(input);
350                                 commandName = parser.getCommandString();
351                                 options = parser.getOptionString();
352                                                                                 
353                                 if (commandName != "") {
354                                         mout->executing = true;
355                                         #ifdef USE_MPI
356                                                 int pid;
357                                                 MPI_Comm_rank(MPI_COMM_WORLD, &pid); 
358                                                 
359 //cout << pid << " is here " << commandName << '\t' << count << endl;
360                                                 if ((cFactory->MPIEnabled(commandName)) || (pid == 0)) {
361                                         #endif
362                                         //executes valid command
363                                         Command* command = cFactory->getCommand(commandName, options);
364                                         quitCommandCalled = command->execute();
365                                                         
366                                         //if we aborted command
367                                         if (quitCommandCalled == 2) {  mout->mothurOut("[ERROR]: did not complete " + commandName + "."); mout->mothurOutEndLine(); }
368
369                                         mout->control_pressed = 0;
370                                         mout->executing = false;
371                                                                                 
372                                         #ifdef USE_MPI
373                                                 }
374                                         #endif
375                                 }else {         
376                                         mout->mothurOut("Invalid."); 
377                                         mout->mothurOutEndLine();
378                                 }
379                                 
380                         }
381                         mout->gobble(inputBatchFile);
382                 }
383                 
384                 inputBatchFile.close();
385                 return 1;
386         }
387         catch(exception& e) {
388                 mout->errorOut(e, "BatchEngine", "getInput");
389                 exit(1);
390         }
391 }
392 /***********************************************************************/
393 string BatchEngine::getNextCommand(ifstream& inputBatchFile) {
394         try {
395                 
396                 string nextcommand = "";
397                 
398                 if (inputBatchFile.eof()) { nextcommand = "quit()"; }
399                 else { nextcommand = mout->getline(inputBatchFile); }
400                 
401                 return nextcommand;
402         }
403         catch(exception& e) {
404                 mout->errorOut(e, "BatchEngine", "getNextCommand");
405                 exit(1);
406         }
407 }
408
409 /***********************************************************************/
410 /***********************************************************************/
411 //This function opens the batchfile to be used by BatchEngine::getInput.
412 ScriptEngine::ScriptEngine(string path, string commandString){
413         try {
414                 globaldata = GlobalData::getInstance();
415                 
416                 //remove quotes
417                 listOfCommands = commandString.substr(1, (commandString.length()-1));
418                 
419                 string temppath = path.substr(0, (path.find_last_of('m')));
420         
421                 //this will happen if you set the path variable to contain mothur's exe location
422                 if (temppath == "") { 
423                 
424                         string envPath = getenv("PATH");
425                         
426                         //delimiting path char
427                         char delim;
428                         #if defined (__APPLE__) || (__MACH__) || (linux) || (__linux)
429                                 delim = ':';
430                         #else
431                                 delim = ';';
432                         #endif
433                         
434                         //break apart path variable by ':'
435                         vector<string> dirs;
436                         mout->splitAtChar(envPath, dirs, delim);
437                         
438                         //get path related to mothur
439                         string mothurPath = "";
440                         for (int i = 0; i < dirs.size(); i++) {
441                                 //to lower so we can find it
442                                 string tempLower = "";
443                                 for (int j = 0; j < dirs[i].length(); j++) {  tempLower += tolower(dirs[i][j]);  }
444                                 
445                                 //is this mothurs path?
446                                 if (tempLower.find("mothur") != -1) {  mothurPath = dirs[i]; break;  }
447                         }
448                         
449                         //add mothur so it looks like what argv would look like
450                         #if defined (__APPLE__) || (__MACH__) || (linux) || (__linux)
451                                 mothurPath += "/mothur";
452                         #else
453                                 mothurPath += "\\mothur";
454                         #endif
455                         
456                         path = mothurPath;
457                 }
458
459                 globaldata->argv = path;
460                                 
461         }
462         catch(exception& e) {
463                 mout->errorOut(e, "ScriptEngine", "ScriptEngine");
464                 exit(1);
465         }
466 }
467
468 /***********************************************************************/
469
470 ScriptEngine::~ScriptEngine(){  }
471
472 /***********************************************************************/
473 //This Function allows the user to run a batchfile containing several commands on mothur
474 bool ScriptEngine::getInput(){
475         try {
476                         
477                 string input = "";
478                 string commandName = "";
479                 string options = "";
480                 
481                 
482                 //CommandFactory cFactory;
483                 int quitCommandCalled = 0;
484         
485                 while(quitCommandCalled != 1){
486                         
487                         #ifdef USE_MPI
488                                 int pid, processors;
489                                 MPI_Status status;
490                                 MPI_Comm_rank(MPI_COMM_WORLD, &pid); 
491                                 MPI_Comm_size(MPI_COMM_WORLD, &processors);
492                                 
493                                 if (pid == 0) {
494                                 
495                         #endif
496                         
497                         input = getNextCommand(listOfCommands); 
498                         
499                         if (input == "") { input = "quit()"; }
500                         
501                         mout->mothurOutEndLine();
502                         mout->mothurOut("mothur > " + input);
503                         mout->mothurOutEndLine();
504                         
505                         #ifdef USE_MPI
506                                 //send commandName
507                                 for(int i = 1; i < processors; i++) { 
508                                                 int length = input.length();
509                                                 MPI_Send(&length, 1, MPI_INT, i, 2001, MPI_COMM_WORLD);
510                                                 MPI_Send(&input[0], length, MPI_CHAR, i, 2001, MPI_COMM_WORLD);
511         
512                                         }
513                                 }else {
514                                         int length;
515                                         MPI_Recv(&length, 1, MPI_INT, 0, 2001, MPI_COMM_WORLD, &status);
516                                         //recieve container
517                                         char* tempBuf = new char[length];
518                                         MPI_Recv(&tempBuf[0], length, MPI_CHAR, 0, 2001, MPI_COMM_WORLD, &status);
519                                         
520                                         input = tempBuf;
521                                         if (input.length() > length) { input = input.substr(0, length);  }
522                                         delete tempBuf; 
523                                 }
524
525                         
526                         #endif
527                         
528                         
529                         if (mout->control_pressed) { input = "quit()"; }
530                                 
531                         //allow user to omit the () on the quit command
532                         if (input == "quit") { input = "quit()"; }
533
534                         CommandOptionParser parser(input);
535                         commandName = parser.getCommandString();
536                         options = parser.getOptionString();
537                                                                                 
538                         if (commandName != "") {
539                                         mout->executing = true;
540                                         #ifdef USE_MPI
541                                                 int pid, numProcesses;
542                                                 
543                                                 MPI_Comm_rank(MPI_COMM_WORLD, &pid); 
544                                                 MPI_Comm_size(MPI_COMM_WORLD, &numProcesses); 
545                                         
546 //cout << pid << " is here " << commandName  << endl;
547                                                 if ((cFactory->MPIEnabled(commandName)) || (pid == 0)) {
548                                                         //cout << pid << " is in execute" << endl;      
549                                         #endif
550                                         //executes valid command
551                                         Command* command = cFactory->getCommand(commandName, options);
552                                         quitCommandCalled = command->execute();
553                                         
554                                         //if we aborted command
555                                         if (quitCommandCalled == 2) {  mout->mothurOut("[ERROR]: did not complete " + commandName + "."); mout->mothurOutEndLine(); }
556                                                         
557                                         mout->control_pressed = 0;
558                                         mout->executing = false;
559                                                                         
560                                         #ifdef USE_MPI
561                                         //cout << pid << " is done in execute" << endl;
562                                                 }
563                                         #endif
564                                 }else {         
565                                         mout->mothurOut("Invalid."); 
566                                         mout->mothurOutEndLine();
567                                 }
568
569                         
570                 }
571                 
572                 return 1;
573         }
574         catch(exception& e) {
575                 mout->errorOut(e, "ScriptEngine", "getInput");
576                 exit(1);
577         }
578 }
579 /***********************************************************************/
580 string ScriptEngine::getNextCommand(string& commandString) {
581         try {
582                 
583                 string nextcommand = "";
584                 int count = 0;
585                 bool ignoreSemiColons = false;
586                 
587                 //go through string until you reach ; or end
588                 while (count < commandString.length()) { 
589                         
590                          //you want to ignore any ; until you reach the next '
591                         if ((commandString[count] == '\'') && (!ignoreSemiColons)) {  ignoreSemiColons = true;  } 
592                         else if ((commandString[count] == '\'') && (ignoreSemiColons)) {  ignoreSemiColons = false;  } 
593                                 
594                         if ((commandString[count] == ';') && (!ignoreSemiColons)) {  break;   }
595                         else {          nextcommand += commandString[count];    }
596                         
597                         count++;
598                 }
599                 
600                 //if you are not at the end
601                 if (count != commandString.length())  {   commandString = commandString.substr(count+1, commandString.length());  }
602                 else { commandString = ""; }
603                                 
604                 
605                 //get rid of spaces in between commands if any
606                 if (commandString.length() > 0) {
607                         while (commandString[0] == ' ') {  
608                                 commandString = commandString.substr(1,commandString.length());
609                                 if (commandString.length() == 0) {  break;  }
610                         }
611                 }
612                 
613                 return nextcommand;
614         }
615         catch(exception& e) {
616                 mout->errorOut(e, "ScriptEngine", "getNextCommand");
617                 exit(1);
618         }
619 }
620 /***********************************************************************/