]> git.donarmstrong.com Git - mothur.git/blob - engine.cpp
moved utilities out of mothur.h and into mothurOut class.
[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                                         mout->control_pressed = 0;
156                                         mout->executing = false;
157                                                                                 
158                                         #ifdef USE_MPI
159                                                 }
160                                         #endif
161                                 }else {         
162                                         mout->mothurOut("Invalid."); 
163                                         mout->mothurOutEndLine();
164                                 }
165                 }       
166                 return 1;
167         }
168         catch(exception& e) {
169                 mout->errorOut(e, "InteractEngine", "getInput");
170                 exit(1);
171         }
172 }
173 /***********************************************************************/
174 string Engine::getCommand()  {
175         try {
176         
177                 #if defined (__APPLE__) || (__MACH__) || (linux) || (__linux)
178                         #ifdef USE_READLINE
179                                 char* nextCommand = NULL;
180                                 nextCommand = readline("mothur > ");
181                                 
182                                 if(nextCommand != NULL) {  add_history(nextCommand);  } 
183                                 else{ //^D causes null string and we want it to quit mothur
184                                         nextCommand = "quit"; 
185                                         mout->mothurOut(nextCommand);
186                                 }       
187                                 
188                                 mout->mothurOutJustToLog("mothur > " + toString(nextCommand));
189                                 return nextCommand;
190                         #else
191                                 string nextCommand = "";
192                                 mout->mothurOut("mothur > ");
193                                 getline(cin, nextCommand);
194                                 mout->mothurOutJustToLog("mothur > " + toString(nextCommand));
195                                 
196                                 return nextCommand;
197                         #endif
198                 #else
199                                 string nextCommand = "";
200                                 
201                                 mout->mothurOut("mothur > ");
202                                 m->getline(cin, nextCommand);
203                                 mout->mothurOutJustToLog(toString(nextCommand));
204                                 
205                                 return nextCommand;
206                 #endif
207         
208                                                 
209         }
210         catch(exception& e) {
211                 mout->errorOut(e, "Engine", "getCommand");
212                 exit(1);
213         }
214 }
215 /***********************************************************************/
216 //This function opens the batchfile to be used by BatchEngine::getInput.
217 BatchEngine::BatchEngine(string path, string batchFileName){
218         try {
219                 globaldata = GlobalData::getInstance();
220         
221                 openedBatch = mout->openInputFile(batchFileName, inputBatchFile);
222                 
223                 string temppath = path.substr(0, (path.find_last_of('m')));
224         
225                 //this will happen if you set the path variable to contain mothur's exe location
226                 if (temppath == "") { 
227                 
228                         string envPath = getenv("PATH");
229                         
230                         //delimiting path char
231                         char delim;
232                         #if defined (__APPLE__) || (__MACH__) || (linux) || (__linux)
233                                 delim = ':';
234                         #else
235                                 delim = ';';
236                         #endif
237                         
238                         //break apart path variable by ':'
239                         vector<string> dirs;
240                         mout->splitAtChar(envPath, dirs, delim);
241                         
242                         //get path related to mothur
243                         string mothurPath = "";
244                         for (int i = 0; i < dirs.size(); i++) {
245                                 //to lower so we can find it
246                                 string tempLower = "";
247                                 for (int j = 0; j < dirs[i].length(); j++) {  tempLower += tolower(dirs[i][j]);  }
248                                 
249                                 //is this mothurs path?
250                                 if (tempLower.find("mothur") != -1) {  mothurPath = dirs[i]; break;  }
251                         }
252                         
253                         //add mothur so it looks like what argv would look like
254                         #if defined (__APPLE__) || (__MACH__) || (linux) || (__linux)
255                                 mothurPath += "/mothur";
256                         #else
257                                 mothurPath += "\\mothur";
258                         #endif
259                         
260                         path = mothurPath;
261                 }
262
263                 globaldata->argv = path;
264                                 
265         }
266         catch(exception& e) {
267                 mout->errorOut(e, "BatchEngine", "BatchEngine");
268                 exit(1);
269         }
270 }
271
272 /***********************************************************************/
273
274 BatchEngine::~BatchEngine(){    }
275
276 /***********************************************************************/
277 //This Function allows the user to run a batchfile containing several commands on Dotur
278 bool BatchEngine::getInput(){
279         try {
280                 //check if this is a valid batchfile
281                 if (openedBatch == 1) {  
282                         mout->mothurOut("unable to open batchfile");  
283                         mout->mothurOutEndLine();
284                         return 1; 
285                 }
286         
287                 string input = "";
288                 string commandName = "";
289                 string options = "";
290                 
291                 //CommandFactory cFactory;
292                 int quitCommandCalled = 0;
293             int count = 0;
294                 while(quitCommandCalled == 0){
295                         
296                         #ifdef USE_MPI
297                                 int pid, processors;
298                                 MPI_Status status;
299                                 MPI_Comm_rank(MPI_COMM_WORLD, &pid); 
300                                 MPI_Comm_size(MPI_COMM_WORLD, &processors);
301                                 
302                                 if (pid == 0) {
303                                 
304                         #endif
305                         
306                         input = getNextCommand(inputBatchFile);
307                         count++;
308                         
309                         #ifdef USE_MPI
310                                 //send commandName
311                                 for(int i = 1; i < processors; i++) { 
312                                                 int length = input.length();
313                                                 MPI_Send(&length, 1, MPI_INT, i, 2001, MPI_COMM_WORLD);
314                                                 MPI_Send(&input[0], length, MPI_CHAR, i, 2001, MPI_COMM_WORLD);
315         
316                                         }
317                                 }else {
318                                         int length;
319                                         MPI_Recv(&length, 1, MPI_INT, 0, 2001, MPI_COMM_WORLD, &status);
320                                         //recieve container
321                                         char* tempBuf = new char[length];
322                                         MPI_Recv(&tempBuf[0], length, MPI_CHAR, 0, 2001, MPI_COMM_WORLD, &status);
323                                         
324                                         input = tempBuf;
325                                         if (input.length() > length) { input = input.substr(0, length);  }
326                                         delete tempBuf; 
327                                 }
328
329                         
330                         #endif
331
332                         
333                         
334                         if (input[0] != '#') {
335                                 
336                                 mout->mothurOutEndLine();
337                                 mout->mothurOut("mothur > " + input);
338                                 mout->mothurOutEndLine();
339                                                         
340                                 if (mout->control_pressed) { input = "quit()"; }
341                                 
342                                 //allow user to omit the () on the quit command
343                                 if (input == "quit") { input = "quit()"; }
344
345                                 CommandOptionParser parser(input);
346                                 commandName = parser.getCommandString();
347                                 options = parser.getOptionString();
348                                                                                 
349                                 if (commandName != "") {
350                                         mout->executing = true;
351                                         #ifdef USE_MPI
352                                                 int pid;
353                                                 MPI_Comm_rank(MPI_COMM_WORLD, &pid); 
354                                                 
355 //cout << pid << " is here " << commandName << '\t' << count << endl;
356                                                 if ((cFactory->MPIEnabled(commandName)) || (pid == 0)) {
357                                         #endif
358                                         //executes valid command
359                                         Command* command = cFactory->getCommand(commandName, options);
360                                         quitCommandCalled = command->execute();
361                                         mout->control_pressed = 0;
362                                         mout->executing = false;
363                                                                                 
364                                         #ifdef USE_MPI
365                                                 }
366                                         #endif
367                                 }else {         
368                                         mout->mothurOut("Invalid."); 
369                                         mout->mothurOutEndLine();
370                                 }
371                                 
372                         }
373                         mout->gobble(inputBatchFile);
374                 }
375                 
376                 inputBatchFile.close();
377                 return 1;
378         }
379         catch(exception& e) {
380                 mout->errorOut(e, "BatchEngine", "getInput");
381                 exit(1);
382         }
383 }
384 /***********************************************************************/
385 string BatchEngine::getNextCommand(ifstream& inputBatchFile) {
386         try {
387                 
388                 string nextcommand = "";
389                 
390                 if (inputBatchFile.eof()) { nextcommand = "quit()"; }
391                 else { nextcommand = mout->getline(inputBatchFile); }
392                 
393                 return nextcommand;
394         }
395         catch(exception& e) {
396                 mout->errorOut(e, "BatchEngine", "getNextCommand");
397                 exit(1);
398         }
399 }
400
401 /***********************************************************************/
402 /***********************************************************************/
403 //This function opens the batchfile to be used by BatchEngine::getInput.
404 ScriptEngine::ScriptEngine(string path, string commandString){
405         try {
406                 globaldata = GlobalData::getInstance();
407                 
408                 //remove quotes
409                 listOfCommands = commandString.substr(1, (commandString.length()-1));
410                 
411                 string temppath = path.substr(0, (path.find_last_of('m')));
412         
413                 //this will happen if you set the path variable to contain mothur's exe location
414                 if (temppath == "") { 
415                 
416                         string envPath = getenv("PATH");
417                         
418                         //delimiting path char
419                         char delim;
420                         #if defined (__APPLE__) || (__MACH__) || (linux) || (__linux)
421                                 delim = ':';
422                         #else
423                                 delim = ';';
424                         #endif
425                         
426                         //break apart path variable by ':'
427                         vector<string> dirs;
428                         mout->splitAtChar(envPath, dirs, delim);
429                         
430                         //get path related to mothur
431                         string mothurPath = "";
432                         for (int i = 0; i < dirs.size(); i++) {
433                                 //to lower so we can find it
434                                 string tempLower = "";
435                                 for (int j = 0; j < dirs[i].length(); j++) {  tempLower += tolower(dirs[i][j]);  }
436                                 
437                                 //is this mothurs path?
438                                 if (tempLower.find("mothur") != -1) {  mothurPath = dirs[i]; break;  }
439                         }
440                         
441                         //add mothur so it looks like what argv would look like
442                         #if defined (__APPLE__) || (__MACH__) || (linux) || (__linux)
443                                 mothurPath += "/mothur";
444                         #else
445                                 mothurPath += "\\mothur";
446                         #endif
447                         
448                         path = mothurPath;
449                 }
450
451                 globaldata->argv = path;
452                                 
453         }
454         catch(exception& e) {
455                 mout->errorOut(e, "ScriptEngine", "ScriptEngine");
456                 exit(1);
457         }
458 }
459
460 /***********************************************************************/
461
462 ScriptEngine::~ScriptEngine(){  }
463
464 /***********************************************************************/
465 //This Function allows the user to run a batchfile containing several commands on mothur
466 bool ScriptEngine::getInput(){
467         try {
468                         
469                 string input = "";
470                 string commandName = "";
471                 string options = "";
472                 
473                 
474                 //CommandFactory cFactory;
475                 int quitCommandCalled = 0;
476         
477                 while(quitCommandCalled == 0){
478                         
479                         #ifdef USE_MPI
480                                 int pid, processors;
481                                 MPI_Status status;
482                                 MPI_Comm_rank(MPI_COMM_WORLD, &pid); 
483                                 MPI_Comm_size(MPI_COMM_WORLD, &processors);
484                                 
485                                 if (pid == 0) {
486                                 
487                         #endif
488                         
489                         input = getNextCommand(listOfCommands); 
490                         
491                         if (input == "") { input = "quit()"; }
492                         
493                         mout->mothurOutEndLine();
494                         mout->mothurOut("mothur > " + input);
495                         mout->mothurOutEndLine();
496                         
497                         #ifdef USE_MPI
498                                 //send commandName
499                                 for(int i = 1; i < processors; i++) { 
500                                                 int length = input.length();
501                                                 MPI_Send(&length, 1, MPI_INT, i, 2001, MPI_COMM_WORLD);
502                                                 MPI_Send(&input[0], length, MPI_CHAR, i, 2001, MPI_COMM_WORLD);
503         
504                                         }
505                                 }else {
506                                         int length;
507                                         MPI_Recv(&length, 1, MPI_INT, 0, 2001, MPI_COMM_WORLD, &status);
508                                         //recieve container
509                                         char* tempBuf = new char[length];
510                                         MPI_Recv(&tempBuf[0], length, MPI_CHAR, 0, 2001, MPI_COMM_WORLD, &status);
511                                         
512                                         input = tempBuf;
513                                         if (input.length() > length) { input = input.substr(0, length);  }
514                                         delete tempBuf; 
515                                 }
516
517                         
518                         #endif
519                         
520                         
521                         if (mout->control_pressed) { input = "quit()"; }
522                                 
523                         //allow user to omit the () on the quit command
524                         if (input == "quit") { input = "quit()"; }
525
526                         CommandOptionParser parser(input);
527                         commandName = parser.getCommandString();
528                         options = parser.getOptionString();
529                                                                                 
530                         if (commandName != "") {
531                                         mout->executing = true;
532                                         #ifdef USE_MPI
533                                                 int pid, numProcesses;
534                                                 MPI_Status status; 
535                                                 
536                                                 MPI_Comm_rank(MPI_COMM_WORLD, &pid); 
537                                                 MPI_Comm_size(MPI_COMM_WORLD, &numProcesses); 
538                                         
539 //cout << pid << " is here " << commandName  << endl;
540                                                 if ((cFactory->MPIEnabled(commandName)) || (pid == 0)) {
541                                                         //cout << pid << " is in execute" << endl;      
542                                         #endif
543                                         //executes valid command
544                                         Command* command = cFactory->getCommand(commandName, options);
545                                         quitCommandCalled = command->execute();
546                                         mout->control_pressed = 0;
547                                         mout->executing = false;
548                                                                         
549                                         #ifdef USE_MPI
550                                         //cout << pid << " is done in execute" << endl;
551                                                 }
552                                         #endif
553                                 }else {         
554                                         mout->mothurOut("Invalid."); 
555                                         mout->mothurOutEndLine();
556                                 }
557
558                         
559                 }
560                 
561                 return 1;
562         }
563         catch(exception& e) {
564                 mout->errorOut(e, "ScriptEngine", "getInput");
565                 exit(1);
566         }
567 }
568 /***********************************************************************/
569 string ScriptEngine::getNextCommand(string& commandString) {
570         try {
571                 
572                 string nextcommand = "";
573                 int count = 0;
574                 
575                 //go through string until you reach ; or end
576                 while (count < commandString.length()) { 
577                         
578                         if (commandString[count] == ';') {  break;   }
579                         else {          nextcommand += commandString[count];    }
580                         
581                         count++;
582                 }
583                 
584                 //if you are not at the end
585                 if (count != commandString.length())  {   commandString = commandString.substr(count+1, commandString.length());  }
586                 else { commandString = ""; }
587                                 
588                 
589                 //get rid of spaces in between commands if any
590                 if (commandString.length() > 0) {
591                         while (commandString[0] == ' ') {  
592                                 commandString = commandString.substr(1,commandString.length());
593                                 if (commandString.length() == 0) {  break;  }
594                         }
595                 }
596                 
597                 return nextcommand;
598         }
599         catch(exception& e) {
600                 mout->errorOut(e, "ScriptEngine", "getNextCommand");
601                 exit(1);
602         }
603 }
604 /***********************************************************************/