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