Wait for file to be written

Dear rooters

Inone of my macros I am invoking a system call that is writing a data file to disk. Before reading the file I will have to wait until it’s closed. Is there a way to find out if a file is still being written or if it is closed already?
Currently I am using gSystem->Sleep(5000) to wait 5 seconds. In most cases this works but sometimes for longer data files this is not sufficient.
Thanks and regards,
delos

PS: I am forced to use root 5.22.

If the file is opened and written by a completely different process it is rather hard to ensure a 100 % safe solution. The quickest way would be to let the writing process create a second file “isDone” alongside once it finished. You then can query for its existence.

It’s a workaround, but better than coding against low-level OS features.

Benedikt

Dear hegner

Thanks but I don’t have any possibility to change the way the process is writing a file.
It is an executable that reads our binary archive data and then writes an ascii file which I then want to read with root.

Cheers,
delos

Hi Delos,

you could however wrap that process such as

#!/bin/bash
<thecreatingcommand>
touch isDone

Cheers,
Benedikt

Dear Benedikt

Thanks, but I don’t understand. Sorry for that.
What I am doing in root is system("/usr/local/bin/ArchiveExport -o tmp.dat -start “10/07/2016 00:00:00” -end “10/14/2016 00:00:00” -gnuplot -precision 9 /gfa/archiver-data/archive_ZHE_MT/index ZOP:MHC1:TPW").
This writes a file tmp.dat that I have to wait for. So the process or program respectively is “ArchiveExport”.
Could you help me with this “touch”?

Cheers,
delos

Hi Delos,

so you are executing the command from within a ROOT macro. I believe this is different from the script in which you do the 5s wait? Because your call of system should actually wait until things finished.

Maybe you can copy & paste some of your actual script.

Thanks,
Benedikt

Dear Benedikt

Yes, I execute the cmd from a root macro:

	char cmdString[500];
	strcpy(cmdString,"ArchiveExport -o tmp.dat -start \"");
	if(StartMonth->GetIntNumber()<10) strcat(cmdString,"0");
	strcat(cmdString,Form("%d",StartMonth->GetIntNumber()));
	strcat(cmdString,"/");
	if(StartDay->GetIntNumber()<10) strcat(cmdString,"0");
	strcat(cmdString,Form("%d",StartDay->GetIntNumber()));
	strcat(cmdString,"/");
	strcat(cmdString,Form("%d",StartYear->GetIntNumber()));
	strcat(cmdString," 00:00:00\" -end \"");
	strcat(cmdString,Form("%d",EndMonth->GetIntNumber()));
	strcat(cmdString,"/");
	strcat(cmdString,Form("%d",EndDay->GetIntNumber()));
	strcat(cmdString,"/");
	strcat(cmdString,Form("%d",EndYear->GetIntNumber()));
	strcat(cmdString," 00:00:00\" -no_text -linear 600 -precision 5 /gfa/archiver-data/archive_ZHE_MT/index MHC1:IST:2");

	system(cmdString);
	gSystem->Sleep(5000);

The I start opening the file to read the data and plot it.

Cheers,
delos

Hi Delos,

OK, having everything happening in the same job could make it simpler. However I must admit I don’t understand why the existing code is not enough. According to man7.org/linux/man-pages/man3/system.3.html system should properly wait for the command to finish. Can you check the return value of system for WIFEXITED and alike? It is entirely unrelated to ROOT though.

Cheers,
Benedikt

A workaround could be:

while(gSystem->GetFromPipe("pidof /usr/local/bin/ArchiveExport")!="")
{
	cout << "ArchiveExport still working: " << gSystem->GetFromPipe("pidof ArchiveExport") << . "Trying again in 5s..." << endl;
	gSystem->Sleep(5000);
}

See:
stackoverflow.com/questions/9117 … is-running
root.cern.ch/doc/master/classTS … 6d140d05ec

Thanks ferhue, your solution works for me.

Cheers,
delos