1. How to wait for file closing?
- Posted by SnakeCharmer Dec 10, 2012
- 1847 views
I have C++ code, that writes some strings to file. For example:
FILE *file = fopen("yum-yum.lst", "w");
fputs("Hot Fudge Sundae\n", file);
fputs("Muffin\n", file);
fputs("Hash Browns With Maple Syrup\n");
fclose(file);
I need to open and read (but not write) this file by my Euphoria program. How to be convinced of what the file is already closed? Otherwise it can be read not completely. I have no ideas, except adding keyword to end of file. For example, "END". But it isn't so effective because it is necessary to read all file to be convinced that it is full. Maybe, it is superfluous because Euphoria won't open file during writing?
2. Re: How to wait for file closing?
- Posted by ChrisB (moderator) Dec 10, 2012
- 1806 views
Hi
I think read_lines is what you are looking for.
http://openeuphoria.org/docs/std_io.html#_1717_read_lines
If you are asking whether another program, or another part of your program has the file open already, I'm not sure if there is a way to tell.
Chris
3. Re: How to wait for file closing?
- Posted by SnakeCharmer Dec 10, 2012
- 1788 views
Excuse for my meticulousness, but this problem is too important for me. Let's say two programs (C++ and Euphoria) work in parallel. C++ writes the lines "Hot Fudge Sundae" and "Muffin". Execution of instruction "read_lines" was at this moment. What will occur?
1. read_lines immediately return {"Hot Fudge Sundae", "Muffin"}
2. read_lines will wait for closing of the file and will return {"Hot Fudge Sundae", "Muffin", "Hash Browns With Maple Syrup"}
Thanks for your endurance.
4. Re: How to wait for file closing?
- Posted by useless_ Dec 10, 2012
- 1788 views
Multiprocessing can be a pain. Best effect is to use flag files. This way you can use more than one program language, any combination of OS, and many computers.
If App#1 wants to use FileB, see if Flag-FileB.txt has any data in it (or if Flag-FileB.txt exists), if not then write to Flag-FileB and close it. Now every App# who wants to use FileB can test Flag-FileB to see it is in use. When done with FileB, App#1 will clear Flag-FileB and close it (or delete it).
This trick should work anywhere, on any OS. There are more complicated and time-consuming ways to do this, which account for internet lag, you use time stamps and re-verifications, and in some cases several lock-files. I timestamp anyhow, to know when it was "locked" and who "locked" it.
useless
5. Re: How to wait for file closing?
- Posted by ChrisB (moderator) Dec 10, 2012
- 1718 views
Hi
That depends. The only way you can be sure that the eu program will read the program correctly is if the C program has close the file first.
The reason for this is that I believe the OS will 'hold on' to some bytes in a buffer, and this buffer won't be flushed to disk until the calling program closes, or releases, the file handle. In other words (and this is by way of illustration only)
C program
FILE *file = fopen("yum-yum.lst", "w");
fputs("Hot Fudge Sundae\n", file);
fputs("Muffin\n", file);
fputs("Hash Browns With Maple Syrup\n");
(fclose deliberately left off)
whats on the disk Hot Fudge Sundae Muffin Hash Browns Wi (th Maple Syrup is still in the buffer)
when fclose is called, th Maple Syrup is flushed, and the file on disk now looks like this
Hot Fudge Sundae Muffin Hash Browns With Maple Syrup
Now, some file systems will let you read that partially created disk, and some won't, and I don't know if there is a way to tell that there is an open file handle associated with that file.
If you are writing the C++ program, then I would suggest writing a small 'indicator' file that the eu program checks for before it reads the file, ie
pseudocode
if file 'yumyum.lck' exists then don't read file
The C++ program at the same time creates and deletes yumyum.lck whenever it opens and closes the file
That is how I would do it without having to worry about how the OS handles file locking and releasing.
There are probably better, and more sophisticated ways of doing it though.
Chris
6. Re: How to wait for file closing?
- Posted by mattlewis (admin) Dec 10, 2012
- 1829 views
I need to open and read (but not write) this file by my Euphoria program. How to be convinced of what the file is already closed? Otherwise it can be read not completely. I have no ideas, except adding keyword to end of file. For example, "END". But it isn't so effective because it is necessary to read all file to be convinced that it is full. Maybe, it is superfluous because Euphoria won't open file during writing?
You can lock the file exclusively when writing, and then attempt to get a shared lock when reading. Here is some euphoria code that demonstrates this:
-- write.ex include std/io.e integer fn = open("foo.txt", "w") lock_file( fn, LOCK_EXCLUSIVE ) puts(fn, "start!\n") system_exec("eui read.ex", -2) puts(fn, "end!\n") close(fn) system_exec("eui read.ex", -2) ------------------------------------------ -- read.ex include std/io.e include std/console.e puts(1, "READING:\n") integer fn = open( "foo.txt", "r") if fn != 1 then if lock_file( fn, LOCK_SHARED ) then display( read_lines( fn ) ) end if close(fn) end if puts(1, "DONE\n")
In C, you could lock a file like this on Linux:
FILE* f = fopen("foo.txt", "w"); int result = flock(fileno(f)), LOCK_EX);
The process is similar in Windows, I think.
Alternatively, you could communicate via sockets to tell your euphoria program that it should read the file.
Matt
7. Re: How to wait for file closing?
- Posted by useless_ Dec 10, 2012
- 1760 views
The C++ program at the same time creates and deletes yumyum.lck whenever it opens and closes the file
That is how I would do it without having to worry about how the OS handles file locking and releasing.
There are probably better, and more sophisticated ways of doing it though.
Chris
You're correct. The biggest problem with using the OS to lock a file is if the app crashes, the file remains locked, and no one can use it until you manually unlock it.
The filesystem can be abused this way tho: any app that wants access to the file can write a filename-req-appname.txt file (or some other more imaginitive name), and then dir(filename-req-*.txt) will list the access queue for the file.
useless
8. Re: How to wait for file closing?
- Posted by mattlewis (admin) Dec 10, 2012
- 1728 views
You're correct. The biggest problem with using the OS to lock a file is if the app crashes, the file remains locked, and no one can use it until you manually unlock it.
This does not appear to be the case on Linux, BTW (it's not clear which OS the OP is using). I added a sleep(100) in my write.ex after writing but before closing the file, and then killed the process manually while it was sleeping. Afterwards, read.ex was able to read the file normally. However, the buffer did out appear to have automatically flushed when I killed the program. Adding a call to flush() before the sleep() call worked.
Matt
9. Re: How to wait for file closing?
- Posted by DerekParnell (admin) Dec 10, 2012
- 1700 views
I just did a quick test and it appears that lock_file() is not working on Windows platform. It appears that it always reports that it locked a file, even when the file is locked by another lock_file() in a separate application.
10. Re: How to wait for file closing?
- Posted by SnakeCharmer Dec 11, 2012
- 1686 views
Apparently, I won't be able to do without lock-files. I have C-code, that get data from optical sensors and Eu-code, that control robot.
Pseudo-code of C-part:
0. delete "whattodo", if it exist
1. get data from optic sensors
2. put data to file "thatisee"
3. create empty file "whattodo"
4. wait for file "turnleft", "turnrght" or "goahead"
5. send order to engines
6. delete files "turnleft", turnrhgt" and "goahead"
7. go to step 1
Pseudo-code of Eu-part:
1. wait for file "whattodo"
2. read file "thatisee"
3. get answer from AI
4. rename "whattodo" to "turnleft", "turnrght" or "goahead"
5. go to step 1
OK?
Whether additional actions are necessary? Whether it is necessary to check, what the file "thatisee" was really updated after step 2?
11. Re: How to wait for file closing?
- Posted by ChrisB (moderator) Dec 11, 2012
- 1661 views
Hi
That looks a little tangled. Try (pseudocode)
c program
file *fp, *fl //get data from sensors fl = fopen("lock_file", "w") puts(fl, "~") fclose(fl) fp = fopen("datafile", "w") //put all your data in there fclose(fp) unlink("lock_file")
then in the eu program
if file_exists("lock_file") then --can't do anything, come back later else -- get your data data = read_lines(datafile) end if
Note, unless you've got a huge data file to write from the C program, then the chances of the eu program encountering the lock file are low. The other danger of course is that the C program starts to write a new datafile before the eu program has finished reading it - you could always write another don't write anything lock file from the eu program, to be checked by the C program before it starts writing.
Chris
12. Re: How to wait for file closing?
- Posted by SnakeCharmer Dec 12, 2012
- 1613 views
Eureka! I will rename the file with data. The open file can't be renamed therefore collisions are impossible. Thus it is required to do a pause while the file is renamed, but with Euphoria it is simple. And on C++-part it isn't necessary to care of anything at all.
C++-part:
0. create temporary directory and set it as current
1. dump data to "thatisee"
2. wait for "turnleft", "turnrght" or "goahead"
3. obay
4. delete "turnleft", "turnrght" and "goahead"
5. if directory isn't empty, then go to 5 (I am not sure that this check is necessary)
6. go to 1
Eu-part:
1. if "thatisee" isn't exist, then go to 1
2. if (rename "thatisee" to "thatisee.tmp") is fail, then go to 2
3. if "thatisee.tmp" isn't exist, then go to 3
4. contemplate(read_lines("thatisee.tmp"))
5. rename "thatisee.tmp" to "turnleft", "turnrght" or "goahead"
6. go to 1
13. Re: How to wait for file closing?
- Posted by mattlewis (admin) Dec 12, 2012
- 1553 views
I just did a quick test and it appears that lock_file() is not working on Windows platform. It appears that it always reports that it locked a file, even when the file is locked by another lock_file() in a separate application.
I think I know why. In be_machine.c, inside of lock_file(), I find:
#if defined(EMINGW) r = 0; // TODO: FOR NOW! #else // defined EMINGW r = lock(fd, first, last - first + 1); #endif // defined EMINGW
...and hg blame tells me that "NOW" was quite a while ago:
jeremy Wed Apr 29 16:24:43 2009 +0000: r = 0; // TODO: FOR NOW!
I suspect we should convert the FILE* to a HANDLE using _get_osfhandle, and then use LockFile on Windows.
Matt
14. Re: How to wait for file closing?
- Posted by petelomax Dec 12, 2012
- 1551 views
I think I know why. In be_machine.c, inside of lock_file(), I find:
#if defined(EMINGW)
...and hg blame tells me that "NOW" was quite a while ago:
Some more history:
2006:
#if defined(ELCC)
2009:
#if defined(ELCC) || defined(EMINGW)
15. Re: How to wait for file closing?
- Posted by FredRansom Dec 12, 2012
- 1589 views
After the last write, just before the fclose, place this statement: fflush (file); That forces Windows to write everything in the buffer to disc right away. Otherwise Windows won't write anything until it gets around to it, when it needs the buffer for something else, or when you shut down. fflush followed by fclose should make the file available for your Euphoria program as soon as you need it.
16. Re: How to wait for file closing?
- Posted by FredRansom Dec 12, 2012
- 1566 views
I don't know what your needs are, but if you are running the programs from the command line, you might use pipes which send standard out from the first program to standard in of the second program. It works the same on Windows and Unix/Linux. The operating system then takes care of the whole thing. Just type something like this: prog1 | prog2 or prog1 > myFile > prog2. Of course this won't work if you're using stdout and stdin for other purposes.
17. Re: How to wait for file closing?
- Posted by SnakeCharmer Dec 13, 2012
- 1560 views
After the last write, just before the fclose, place this statement: fflush (file);
Thanks!
About pipes: I considered this option, but files are more convenient in my case.