1 /***************************************************************************
2                           rkrinterface.h  -  description
3                              -------------------
4     begin                : Fri Nov 1 2002
5     copyright            : (C) 2002 - 2018 by Thomas Friedrichsmeier
6     email                : thomas.friedrichsmeier@kdemail.net
7  ***************************************************************************/
8 
9 /***************************************************************************
10  *                                                                         *
11  *   This program is free software; you can redistribute it and/or modify  *
12  *   it under the terms of the GNU General Public License as published by  *
13  *   the Free Software Foundation; either version 2 of the License, or     *
14  *   (at your option) any later version.                                   *
15  *                                                                         *
16  ***************************************************************************/
17 
18 #ifndef RKRINTERFACE_H
19 #define RKRINTERFACE_H
20 
21 #include <qobject.h>
22 #include <QFile>
23 
24 #include "rcommand.h"
25 #include "rcommandreceiver.h"
26 
27 class RCommand;
28 class RKWardMainWindow;
29 class RKRBackend;
30 class RBackendRequest;
31 
32 /** This class provides the main interface to the R-processor.
33 
34 	Note that since communication with R is asynchronous, there is no way to get
35 	R-output within the same function, the request is submitted. You have to
36 	provide an RCommandReceiver object, if you're interested in the output.
37 
38 	For a detailed explanation see \ref UsingTheInterfaceToR .
39 
40 	@see RCommand
41 	*@author Thomas Friedrichsmeier
42 */
43 
44 class RInterface : public QObject, public RCommandReceiver {
45 	Q_OBJECT
46 public:
47 /** constructor */
48 	RInterface();
49 /** destructor */
50 	~RInterface();
51 
52 /** issues the given command in the given chain */
53 	void issueCommand (RCommand *command, RCommandChain *chain=0);
54 /** convenience function to create a new command and issue it. See documentation on RCommand::RCommand () and RInterface::issueCommand () */
55 	void issueCommand (const QString &command, int type = 0, const QString &rk_equiv = QString (), RCommandReceiver *receiver=0, int flags=0, RCommandChain *chain=0);
56 
57 /** opens a new command chain. Returns a pointer to the new chain. If you specify a parent, the new chain will be a sub-chain of that chain. */
58 	RCommandChain *startChain (RCommandChain *parent=0);
59 /** closes the command chain. The chain (and even its parent, if it is already closed) may be deleted right afterwards! */
60 	void closeChain (RCommandChain *chain);
61 
62 /** Ensures that the given command will not be executed, or, if it is already running, interrupts it. Note that commands marked RCommand::Sync can
63 not be interrupted. */
64 	void cancelCommand (RCommand *command);
65 /** Cancels the given command, unless it has already been submitted to the backend. Returns true, if command was cancelled, false otherwise. */
66 	bool softCancelCommand (RCommand *command);
67 /** Cancels all running or outstanding commands. @See cancelCommand() */
68 	void cancelAll ();
69 
70 /** Pauses process. The current command will continue to run, but no new command will be */
71 	void pauseProcessing (bool pause);
72 
73 /** returns the command currently running in the thread. Be careful when using the returned pointer! */
runningCommand()74 	RCommand *runningCommand () const { return (all_current_commands.isEmpty () ? 0 : all_current_commands.last ()); };
75 
backendIsDead()76 	bool backendIsDead () { return backend_dead; };
77 	bool backendIsIdle ();
isNaReal(double value)78 	static bool isNaReal (double value) { return na_real == value; };
isNaInt(int value)79 	static bool isNaInt (int value) { return na_int == value; };
80 private:
81 	void timerEvent (QTimerEvent *) override;
82 	int flush_timer_id;
83 /** Calls RThread::flushOutput(), and takes care of adding the output to all applicable commands */
84 	void flushOutput (bool forced);
85 /** pointer to the RThread */
86 	RKRBackend *r_thread;
87 /** Used by the testing framework. see R function rk.record.commands(). */
88 	QFile command_logfile;
89 	enum {
90 		NotRecordingCommands,
91 		RecordingCommands,
92 		RecordingCommandsUnfiltered
93 	} command_logfile_mode;
94 
95 	void processHistoricalSubstackRequest (const QStringList &calllist, RCommand *parent_command);
96 	QStringList processPlainGenericRequest (const QStringList &calllist);
97 	void processRBackendRequest (RBackendRequest *request);
98 
99 /** A list of all commands that have entered, and not yet left, the backend thread */
100 	QList<RCommand*> all_current_commands;
101 /** NOTE: processing R events while waiting for the next command may, conceivably, lead to new requests, which may also wait for sub-commands! Thus we keep a simple stack of requests. */
102 	QList<RBackendRequest*> command_requests;
currentCommandRequest()103 	RBackendRequest* currentCommandRequest () const { return (command_requests.isEmpty () ? 0 : command_requests.last ()); };
104 	void tryNextCommand ();
105 	void doNextCommand (RCommand *command);
106 	RCommand *popPreviousCommand (int id);
107 	void handleCommandOut (RCommand *command);
108 	bool previously_idle;
109 
110 	RCommandChain* openSubcommandChain (RCommand *parent_command);
111 	QList<RCommand *> current_commands_with_subcommands;
112 	void closeSubcommandChain (RCommand *parent_command);
113 
114 /** @see locked */
115 	enum LockType {
116 		User=1		/**< locked on user request */
117 	};
118 
119 /** Used for locking the backend, meaning not further commands will be given to the backend. It is called, if the RThread is paused on User request.
120  * @see RInterface::pauseProcessing
121  * May be an OR'ed combination of several LockType s, but currently, there is only one LockType */
122 	int locked;
123 
124 	QString startup_errors;
125 	bool startup_phase2_error;
126 	RCommand *dummy_command_on_stack;
127 friend class RKRBackendProtocolFrontend;
128 	bool backend_dead;
129 	static double na_real;
130 	static int na_int;
131 friend class RKWardMainWindow;
132 friend class RCommand;
133 protected:
134 	void handleRequest (RBackendRequest *request);
135 	void rCommandDone (RCommand *command) override;
136 signals:
137 	void backendWorkdirChanged();
138 };
139 
140 /**
141 \page UsingTheInterfaceToR Using the Interface to R
142 \brief An Introduction to using the R-backend: Running commands in R and handling the results
143 
144 This page tries to give you an introduction into using the RInterface and related classes. You'll learn how to submit a command for evaluation
145 by R and how you can get and handle the results. Note that this is fairly low-level. You do not need to read this documentation in order to develop
146 plugins. You'll only need to know this in order to do C++-hacking in rkward.
147 The page is divided into several sections on special problems, but if you're new to rkward, you will probably want to read it as a whole instead of
148 jumping right to those sections.
149 
150 \section UsingTheInterfaceToRTheSimpleCase The simple case: Fire and forget
151 
152 In the most simple case, all you want to do is to send a command to be evaluated executed in the R backend, and you are not interested in what
153 happens (whether the command runs successfully, or what the output is). For this, all you need is the following
154 code:
155 
156 \code
157 #include "rkglobals.h"
158 #include "rbackend/rinterface.h"
159 
160 RKGlobals::rInterface ()->issueCommand ("print (\"hello world!\")", RCommand::User);
161 \endcode
162 
163 You will note, that actually there are two RInterface::issueCommand functions, this one is obviously the one taking a QString and several further
164 parameters as argument. It is actually quite similar to the other RInterface::issueCommand function which takes an RCommand as a parameter. This convenience class basically just creates an RCommand with the same parameters as the constructor of RCommand (RCommand::RCommand), and then submits this RCommand. We'll discuss what an RCommand really is further down below. For now a good enough explanations is, that it's simply a container for a command.
165 
166 The first parameter here is fairly obvious, the command-string the R backend should evaluate.
167 
168 The second parameter (RCommand::User) is an integer, which can be a bit-wise or-able combination of the values in the RCommand::CommandTypes enum. We'll deal with the more specific values in that enum later. Here, we're just using RCommand::User, which signifies, that the command came
169 directly from the user. This information is fairly important, as it affects the handling of the command at several places: Which color it will be given in
170 the R-command log (currently class RKwatch), whether the command can be cancelled (RCommand::User commands can be cancelled, but some other types of commands can not be cancelled), etc. See the documentation on RCommand::CommandTypes (not yet complete) for more information.
171 
172 \section UsingTheInterfaceToRHandlingReturns A slightly more realistic example: Handling the result of an RCommand
173 
174 Most of the time you don't just want to run a command, but you also want to know the result. Now, this is a tad bit more difficult than one might expect at first glance. The reason for this is that the R backend runs in a separate thread. Hence, whenever you submit a command, it generally does not get executed right away - or at least you just don't know, when exactly it gets executed, and when the result is available. This is necessary, so (expensive) commands running in the backend do not block operations in the GUI/frontend.
175 
176 Ok, so how do you get informed, when your command was completed? Using RCommandReceiver. What you will want to do is inherit the class you
177 want to handle the results of RCommands from RCommandReceiver. When finished, the RCommand will be submitted to the (pure virtual) RCommandReceiver::rCommandDone function, which of course you'll have to implement in a meaningful way in your derived class.
178 
179 The corresponding code would look something like this:
180 
181 \code
182 #include "rkglobals.h"
183 #include "rbackend/rinterface.h"
184 #include "rbackend/rcommandreceiver.h"
185 
186 class MyReceiver : public RCommandReceiver {
187 //...
188 protected:
189 /// receives finished RCommands and processes them
190 	void rCommandDone (RCommand *command);
191 //...
192 private:
193 /// does something by submitting an RCommand
194 	void someFunction ();
195 //...
196 };
197 
198 
199 void MyReceiver::someFunction () {
200 	RKGlobals::rInterface ()->issueCommand ("print (1+1)", RCommand::App, QString (), this);
201 }
202 
203 void MyReceiver::rCommandDone (RCommand *command) {
204 	if (command->successful ()) {
205 		qDebug ("Result was %s", command->output ()->utf8 ());
206 	}
207 }
208 \endcode
209 
210 First thing to note is, that this time we're passing two additional parameters to RInterface::issueCommand. The first (or rather third) is really not used as of the time of this writing. What it's meant to become is a short descriptive string attached to the RCommand, that allows the user to make some sense of what this command is all about. The other (fourth) is a pointer to an RCommandReceiver that should be informed of the result. In this case, we'll handle the result in the same object that we issued the command from, so we use "this".
211 
212 So next the RCommand created with RInterface::issueCommand goes on its way to/through the backend (we'll discuss what happens there further down below). Then later, when it has completed its journey, rCommandDone will be called with a pointer to the command as parameter. Now we can use this pointer to retrieve the information we need to know. RCommand::successful and some further simple functions give information about whether the command had any errors and what kind of errors (see RCommand for details). RCommand::output contains the output of the command as a QString (provided the command was successful and had any output). In this case that should be "[1] 2".
213 
214 \section UsingTheInterfaceToRMultipleCommands Dealing with several RCommands in the same object
215 
216 In many cases you don't just want to deal with a single RCommand in an RCommandReceiver, but rather you might submit a bunch of different commands (for instance to find out about several different properties of an object in R-space), and then use some special handling for each of those commands. So the problem is, how to find out, which of your commands you're currently dealing with in rCommandDone.
217 
218 There are several ways to deal with this:
219 
220 	- storing the RCommand::id () (each command is automatically assigned a unique id, TODO: do we need this functionality? Maybe remove it for redundancy)
221 	- passing appropriate flags to know how to handle the command
222 	- keeping the pointer (CAUTION: don't use that pointer except to compare it with the pointer of an incoming command. Commands get deleted when they are finished, and maybe (in the future) if they become obsolete etc. Hence the pointers you keep may be invalid!)
223 
224 To illustrate the option of using "FLAGS", here is a reduced example of how RKVariable updates information about the dimensions and class of the corresponding object in R-space using two different RCommand s:
225 
226 \code
227 #define UPDATE_DIM_COMMAND 1
228 #define UPDATE_CLASS_COMMAND 2
229 
230 void RKVariable::updateFromR () {
231 	//...
232 	RCommand *command = new RCommand ("length (" + getFullName () + ")", RCommand::App | RCommand::Sync | RCommand::GetIntVector, QString (), this, UPDATE_DIM_COMMAND);
233 	RKGlobals::rInterface ()->issueCommand (command, RKGlobals::rObjectList()->getUpdateCommandChain ());
234 }
235 
236 void RKVariable::rCommandDone (RCommand *command) {
237 	//...
238 	if (command->getFlags () == UPDATE_DIM_COMMAND) {
239 		// ...
240 		RCommand *ncommand = new RCommand ("class (" + getFullName () + ")", RCommand::App | RCommand::Sync | RCommand::GetStringVector, QString (), this, UPDATE_CLASS_COMMAND);
241 		RKGlobals::rInterface ()->issueCommand (ncommand, RKGlobals::rObjectList()->getUpdateCommandChain ());
242 	} else if (command->getFlags () == UPDATE_CLASS_COMMAND) {
243 		//...
244 	}
245 }
246 \endcode
247 
248 Note that you can freely assign whatever flags you like. Only your own class will need to know how to interpret the flags.
249 
250 Now what about that RKGlobals::rObjectList()->getUpdateCommandChain ()? We'll talk about RCommandChain and what you need it for further down below. But first we'll have a look at how an RCommand is handled internally.
251 
252 \section UsingTheInterfaceToRInternalHandling What happens with an RCommand internally?
253 
254 So far we've discussed RInterface:issueCommand () and RCommandReceiver::rCommandDone (). But what happens in between?
255 
256 First the RCommand is placed in a first-in-first-out stack. This stack is needed, since - as discussed - the commands get executed in a separate thread, so several command may get stacked up, before the first one gets run.
257 
258 Then, in the backend thread (RThread) there is a loop running, which fetches those commands from the stack and executes them one by one. Whenver a command has been executed in this thread, it gets updated with information on any errors that occurred and of course also with the result of running the command. Next, a QCustomEvent is being posted. What this does is - rougly speaking -, transfer the pointer to the command back to the main thread in a safe way.
259 
260 Whenever the main thread becomes active again, it will find that QCustomEvent and handle it in RInterface::customEvent.
261 
262 The most important thing happening there, is a call to RCommand::finished (RCommand::finished basically just calls the responsible RCommandReceiver::rCommandDone), and right after that the RCommand gets deleted.
263 
264 \section UsingTheInterfaceToRThreadingIssues Threading issues
265 
266 The above description sounds simple enough, but there may be some threading issues to keep in mind. Consider what needs to happen when RKVariable is trying to update the information on the corresponding object in R-space (see code example above):
267 
268 - RKVariable will first run a command to determine the dimensionality of the object.
269 
270 Now this is more significant than you may think, as RKVariable is a special kind of RObject, which only handles one-dimensional data. Hence, if you create an object in R with
271 
272 \code
273 myobject <- c (1, 2, 3)
274 \endcode
275 
276 In RKWard an RKVariable will be responsible for "myobject".
277 
278 However, if next, you assign something different to myobject:
279 
280 \code
281 myobject <- data.frame (x=c (1, 2, 3), y=c (2, 3, 4))
282 \endcode
283 
284 the object "myobject" can no longer be handled by RKVariable, but instead by RContainerObject.
285 
286 What this means practically is that if RKVariable finds out its corresponding object in R-space has more than a single dimension, the RKVariable will have to be deleted and an RContainerObject needs to be created instead.
287 
288 So what's the problem?
289 
290 Consider this hypothetical example:
291 
292 - RKVariable for object "myobject" runs a command to determine the dimensionality of "myobject"
293 - Before that command has finished, the user assigns a data.frame to "myobject" (or deletes the object, or whatever)
294 - The command to determine the dimensionality gets run and returns "1 dimension". RKVariable will assume it knows how to handle the object, and tries to do something with "myobject" which is only applicable for one-dimensional objects (e.g. trying to get the data as a one-dimensional array)
295 - The user command assigning a data.frame gets run
296 - RKVariables command to get the data fails
297 
298 Now, you may argue this does not sound all that likely, and probably it isn't, but the point to see is that there are cases in which the threaded nature of R access can pose some problems. More generally, that is the case, if you want a sequence of commands to run in exactly that order without being disturbed by intervening commands.
299 
300 To cope with this, it is sometimes desirable to keep closer control over the order in which commands get run in the backend.
301 
302 \section UsingTheInterfaceToRCommandChains How to ensure commands get executed in the correct order: RCommandChain
303 
304 The way to do this is to use RCommandChain. Basically, when you want commands to be executed in a sequence being sure that no other commands intervene, you do this:
305 
306 \code
307 	RCommandChain *chain = RKGlobals::rInterface ()->startChain ();
308 
309 	// create first command
310 	RKGlobals::rInterface ()->issueCommand (first_command, chain);
311 
312 	// wait for command to return, potentially allows further calls to RInterface::issueCommand () from other places in the code
313 
314 	// create second command
315 	RKGlobals::rInterface ()->issueCommand (second_command, chain);
316 
317 	RKGlobals::rInterface ()->closeChain (chain);
318 \endcode
319 
320 Now the point is that you place both of your commands in a dedicated "chain", telling RKWard that those two commands will have to be run in direct succession. If between the first and the second command, another section of the code issues a different command, this command will never be run until all commands in the chain have been run and the chain has been marked as closed.
321 
322 To illustrate, consider this series of events:
323 
324 \code
325 1) RCommandChain *chain = RKGlobals::rInterface ()->startChain ();
326 2) RKGlobals::rInterface ()->issueCommand (first_command, chain);
327 3) RKGlobals::rInterface ()->issueCommand (some_command);
328 4) RKGlobals::rInterface ()->issueCommand (second_command, chain);
329 5) RKGlobals::rInterface ()->issueCommand (some_command2);
330 6) RKGlobals::rInterface ()->closeChain (chain);
331 \endcode
332 
333 Now let's assume for a second, the R backend has been busy doing other stuff and has not executed any of the commands so far, then the execution stack will now look like this:
334 
335 - top level
336 	- chain
337 		- first_command
338 		- second_command
339 		- chain is marked as closed: after executing second_command, we may proceed with the top level
340 	- some_command
341 	- some_command2
342 
343 So the order of execution will be guaranteed to be first_command, second_command, some_command, some_command2, although they were issued ina different order. You can also open sub chains, using
344 
345 \code
346 RCommandChain *sub_chain = RKGlobals::rInterface ()->startChain (parent_chain);
347 \endcode
348 
349 Remember to close chains when you placed all the commands you needed to. If you don't close the chain, RKWard will continue to wait for new commands in that chain, and never proceed with commands outside of the chain.
350 
351 \section UsingTheInterfaceToROutputOptions Sending results to the output and retrieving low-level data from the backend
352 
353 There are a few special type-modifiers you can specify when creating an RCommand (as part of the second parameter to RCommand::RCommand or RInterface::issueCommand), that determine what will be done with the result:
354 
355 - RCommand::EmptyCommand
356 This one tells the backend, that the command does not really need to be executed, and does not contain anything. You'll rarely need this flag, but sometimes it is useful to submit an empty command simply to find out when it is finished.
357 
358 - RCommand::DirectToOutput
359 This is typically used in plugins: When you specify this modifier, the plain text result of this command (i.e. whatever R prints out when evaluating the command) will be added to the HTML output file. Remember to call RKWardMainWindow::newOutput in order to refresh the output-window once the command has finished.
360 
361 - RCommand::GetIntVector, RCommand::GetStringVector, RCommand::GetRealVector
362 These are special modifiers helpful when transferring data from R to RKWard (used primarily in the editor classes and in conjunction with RCommand::Sync): They tell the backend to try to fetch the result as an array of int, char*, or double, respectively. For instance, if you know object "myobject" is an integer vector, you may get the data using
363 
364 \code
365 RKGlobals::rInterface ()->issueCommand ("myobject", RCommand::Sync | RCommand::GetIntVector, QString (), this);
366 \endcode
367 
368 Assuming the data can in fact be converted to a vector of integers, you can then access the data using these members in RCommand:
369 
370 - RCommand::intVectorLength (): size of int array
371 - RCommand::getIntVector (): a pointer to the int array. Warning: The array is owned by the RCommand and will be deleted together with the RCommand, so don't just store the pointer
372 - RCommand::detachIntVector (): If you do want to keep the array, use this call to transfer ownership to your class. You are now responsible for freeing up the data yourself.
373 
374 Obviously, whenever trying to transfer data from the backend, this approach is highly superior to parsing the QString RCommand::output ().
375 
376 \section UsingTheInterfaceToRFurtherReading Where to find more detailed information on these topics
377 
378 The following classes contain (or should contain) further important documentation:
379 
380 - \ref RInterface
381 - \ref RCommand
382 - \ref RCommandReceiver
383 - \ref RCommandStack
384 
385 Even lower level API:
386 
387 - \ref RRBackendProtcolFrontend
388 - \ref RBackend
389 - \ref RRBackendProtcolBackend
390 
391 */
392 
393 #endif
394