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