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