File Exception Handling and wait for a process in SWI Prolog - windows-7

I am running my code on SWI Prolog and Windows 7. In my code, I call another application using 'win_exec()' (I tried using the method 'shell()', but it won't work.), and at the end produces its output in a text file. However sometimes it runs for times like 30 minutes. Now my prolog code uses this output text file, to further parse it and process it.
This is the code I use to call the other application and then use its output file:
main(Value,X) :- win_exec('C:\\myfolder\\external_app.bat C:\\myfolder\\outputfile.txt', normal),
open('C:\\myfolder\\outputfile.txt', read, Mf),
read_file(Mf, X), % PROCEDURE TO READ FILE CONTENTS
close(Mf),
statistics(cputime, Value). % CALCULATE HOW LONG IT TOOK
However, since the file has not been outputted by that another application, it gives the error:
ERROR: open/4: source_sink `C:\myfolder\outputfile.txt' does not exist (No such file or directory)
So, as a workaround, I try to catch the error, handle it by comparing with 'existence_error' and then recursively call the open procedure, until it finally succeeds i.e. the other application has completed its processing and the output file is produced. This is my workaround code for this:
main(Value,X) :- win_exec('C:\\myfolder\\external_app.bat C:\\myfolder\\outputfile.txt', normal),
open_output(X), % PROCEDURE FOR FILE EXCEPTION HANDLING
statistics(cputime,Value).
open_output(X) :- catch((open('C:\\myfolder\\outputfile.txt', read, Mf), read_file(Mf,X), close(Mf)),
error(Err,Context),
open_output_aux(Err,X)). % AUX PROCEDURE TO RECOVER
% Write some code here
% open_output_aux code matches the error code with 'existence_error';
% if true, calls open_aux_wait procedure; else throw the error.
open_aux_wait(Z):- catch((open('C:\\myfolder\\outputfile.txt', read, Mf), read_file(Mf,Z), close(Mf)),
error(Err,Context),
open_aux_wait(Z)).
However this seems to be very inefficient of way doing this. I wanted to know if there's any better way to do this, like in java, you could simply call wait() while handling file exception. In the documentation, there's a method 'wait_for_input\3' but it says 'wait_for_input()' cannot be used for File Streams in Windows. I tried using it, but it gives error.
Any help or guidelines is greatly appreciated.

You have several options to solve this:
You can totally reconsider the way that these processes communicate. For example, SWI-Prolog ships with very powerful HTTP libraries, and you can set up the communication between the two processes to work over HTTP, using a client/server architecture. In this case, you avoid the busy waiting that currently uses many CPU cycles unnecessarily.
A much more trivial solution is to simply insert a call of the built-in sleep/1 predicate to put the process to sleep before trying to open the file again. Use for example sleep(1) to put the process to sleep for 1 second.
Use for example process_wait/2 to wait until the called process has finished and generated the file.
From what you are describing, it looks like (2) will do, (3) is slightly more elegant, and (1) may be good to know in general, for more difficult cases.

Related

Prolog does not stop accepting data in read

This is my code in Prolog.
do(cinema):- parents(yes); (parents(no),weather(windy),money(less)).
do(play):- parents(no),weather(sunny).
do(stay):- parents(no),weather(rainy).
do(shopping):- parents(no),weather(windy),money(more).
start:- write('Parents: '),read(X),assert(parents(X)), write('Weather: '),read(Y),assert(weather(Y)), write('Money: '),read(Z),assert(money(Z)).
clear:- retract(parents(X));retract(weather(X));retract(money(X)).
I'm trying to accept data from user and then use decision tree to find out what task will be done.
I'm running the code as:
?-start, do(X).
But it does not write Weather after reading input for parents and keeps reading data.
There is nothing really wrong with your program. See http://swish.swi-prolog.org/p/JDAJcUhq.pl. The most likely cause is already mentioned: not finishing your term with a ".". clear/0 is indeed wrong, but not needed in the web version as each new query is executed in a fresh environment.
At least in SWI-Prolog there is no need to flush before a read operation from the terminal as flushing the console output streams is always done before the read.
Try putting some flush goals after the write goals and then remember to add a full stop on your input as you are using read/1 which wants a term.

How to get return value from startcmd.sh OdiStarScen

I am triggering scenarios by calling startcmd.sh OdiStartscen it executes the scenario, but I would like to know if this execution failed or successed without checking the ODI.
Is there a way to elevate return code from OdiStartScen to startcmd.sh
Thanks,
Isn't it as simple as in case of any other OS command?
Once successful any OS should internally return success code (0 in linux) back to the parent process. Otherwise it would be error code (non-zero).
That means you simply need to handle 'success' and 'failure' paths in your ODI package (green and red lines). Simply put some nonsense in the startcmd.sh OdiStartScen call for some quick test so see if it behaves as expected in case of failures. Alternatively you may use same step for both paths (red and green) and test using getPrevStep() function for errors (cf. STATUS property).
Two things worth mentioning:
This makes only sense for synchronous calls (so it waits for your Scenario to finish).
Why don't you use ODIStartScen() as an ODI Tool type of package/procedure step instead? Seems lot more elegant. Same answer applies.

Confusion about rubys IO#(read/write)_nonblock calls

I am currently doing the Ruby on the Web project for The Odin Project. The goal is to implement a very basic webserver that parses and responds to GET or POST requests.
My solution uses IO#gets and IO#read(maxlen) together with the Content-Length Header attribute to do the parsing.
Other solution use IO#read_nonblock. I googled for it, but was quite confused with the documentation for it. It's often mentioned together with Kernel#select, which didn't really help either.
Can someone explain to me what the nonblock calls do differently than the normal ones, how they avoid blocking the thread of execution, and how they play together with the Kernel#select method?
explain to me what the nonblock calls do differently than the normal ones
The crucial difference in behavior is when there is no data available to read at call time, but not at EOF:
read_nonblock() raises an exception kind of IO::WaitReadable
normal read(length) waits until length bytes are read (or EOF)
how they avoid blocking the thread of execution
According to the documentation, #read_nonblock is using the read(2) system call after O_NONBLOCK is set for the underlying file descriptor.
how they play together with the Kernel#select method?
There's also IO.select. We can use it in this case to wait for availability of input data, so that a subsequent read_nonblock() won't cause an error. This is especially useful if there are multiple input streams, where it is not known from which stream data will arrive next and for which read() would have to be called.
In a blocking write you wait until bytes got written to a file, on the other hand a nonblocking write exits immediately. It means, that you can continue to execute your program, while operating system asynchronously writes data to a file. Then, when you want to write again, you use select to see whether the file is ready to accept next write.

Lua hook-like call AFTER line processing

Lua features hook call BEFORE every processed line. What I need is a call AFTER line is processed, so that I can check for encountered errors and so on. Is there a way to make such kind of call?
Otherwise things get a little bit confusing if error is encountered at the last line of the script. I don't get any feedback.
UPDATE #1
We want to catch both Lua errors and 'our' errors asserted via lua_error(*L) C interface, and Lua should throw correct debug info including the line number where the error occurred.
Using return hook we always get error line number -1, which is not what we want. Using any combination of pcall and any hook setup after lua_error(*L) we get either line number -1, or number of the next executed line, never a correct one.
SOLUTION#
We managed to make everything work. The thing was that Lua throws a real C exception after it detects an error, so some of our 'cleaning & finalizing' C code called from Lua operation did not execute, which messed up some flags and so on. The solution was to execute 'cleaning code' right before calling lua_error(...). This is correct and desired Lua behavior as we really want to stop executing the function once lua_error(...) is called, it was our mistake to expect any code would be executed after lua_error(...) call.
Tnx Paul Kulchenko, some of this behavior was found while trying to design a simple example script which reproduces the problem.
Try setting a return hook: it'll be called after the last line is executed.
I'm not sure debug hook is the best solution for what you are trying to do (or you need to provide more details). If you just need to check for run-time errors, why use debug hooks at all if you can run your code with pcall and get an error message that points to the line number where the error happened (or use xpcall, which also allows you to get a stack trace)? You can combine this with debug.getinfo(func, "L") to get a table whose indexes are valid line numbers for the function.

Help in understanding this bash file

I am trying to understand the code in this page: https://github.com/corroded/git-achievements/blob/gh-pages/git-achievements
and I'm kinda at a loss on how it actually works. I do know some bash and shell scripting, but how does this script actually "store" how many times you've used a command(im guessing saving into a text file?) and how does it "sense" that you actually typed in a git command? I have a feeling it's line 464 onwards that does it but I don't seem to quite follow the logic.
Can anyone explain this in a bit more understandable context?
I plan to do some achievements for other commands and I hope to have an idea on HOW to go about it without randomly copying and pasting stuff and voodoo.
Yes on 464 start the script, everything before are helping functions. I dont know how it gets installed, but I would assume you have to call this script instead of the normal git-command. It just checks if the first parameter is achievement, and if not then just (regular) git with the rest parameters is executed. Afterwards he checks if an error happend (if he exits). And then he just makes log_action and check_for_achievments. log_action just writes the issued command with a date into a text file, while achievments scans for that log file for certains events. If you want to add another achievment you have to do it in this check_for_achievments.
Just look how the big case handles it (most of the achievments call the count_function which counts the # usages of the function and matches when a power of 2 is reached).

Resources