1. How to wait for file closing?

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?

new topic     » topic index » view message » categorize

2. Re: How to wait for file closing?

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

new topic     » goto parent     » topic index » view message » categorize

3. Re: How to wait for file closing?

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.

new topic     » goto parent     » topic index » view message » categorize

4. Re: How to wait for file closing?


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

new topic     » goto parent     » topic index » view message » categorize

5. Re: How to wait for file closing?

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

new topic     » goto parent     » topic index » view message » categorize

6. Re: How to wait for file closing?

SnakeCharmer said...

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

new topic     » goto parent     » topic index » view message » categorize

7. Re: How to wait for file closing?

ChrisB said...

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

new topic     » goto parent     » topic index » view message » categorize

8. Re: How to wait for file closing?

useless_ said...

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

new topic     » goto parent     » topic index » view message » categorize

9. Re: How to wait for file closing?

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.

new topic     » goto parent     » topic index » view message » categorize

10. Re: How to wait for file closing?

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?

new topic     » goto parent     » topic index » view message » categorize

11. Re: How to wait for file closing?

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

new topic     » goto parent     » topic index » view message » categorize

12. Re: How to wait for file closing?

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

new topic     » goto parent     » topic index » view message » categorize

13. Re: How to wait for file closing?

DerekParnell said...

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

new topic     » goto parent     » topic index » view message » categorize

14. Re: How to wait for file closing?

mattlewis said...

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) 
new topic     » goto parent     » topic index » view message » categorize

15. Re: How to wait for file closing?

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.

new topic     » goto parent     » topic index » view message » categorize

16. Re: How to wait for file closing?

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.

new topic     » goto parent     » topic index » view message » categorize

17. Re: How to wait for file closing?

FredRansom said...

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.

new topic     » goto parent     » topic index » view message » categorize

Search



Quick Links

User menu

Not signed in.

Misc Menu