aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authortradke <tradke@eff87b29-5268-4891-90a3-a07138403961>2005-10-16 10:12:13 +0000
committertradke <tradke@eff87b29-5268-4891-90a3-a07138403961>2005-10-16 10:12:13 +0000
commit9d70096709e7f9d63787a45d5f5ac626b5fb0933 (patch)
tree6b921cc58adb07bbad09aafb2610ffeb04bc8168
parent5ddaa33cf638637596371ca68d19191350ac255d (diff)
For announced JPEGs: write to a temporary file first and then (atomically)
rename it to the real output file. This fixes problems with a threaded HTTPD where JPEG files could be downloaded while they were still being written to. git-svn-id: http://svn.cactuscode.org/arrangements/CactusIO/IOJpeg/trunk@116 eff87b29-5268-4891-90a3-a07138403961
-rw-r--r--src/Write.c58
1 files changed, 40 insertions, 18 deletions
diff --git a/src/Write.c b/src/Write.c
index 4005fd9..faf87ef 100644
--- a/src/Write.c
+++ b/src/Write.c
@@ -313,7 +313,7 @@ static void WriteData (const cGH *GH, int vindex, const char *alias, int dim,
unsigned char *dataout;
const ioJpegGH *myGH;
ioAdvertisedFileDesc advertised_file;
- char *filename, *fullname;
+ char *filename, *tmpfilename, *fullname;
char slicename[30];
const char *extensions[] = {"xy", "xz", "yz"};
DECLARE_CCTK_PARAMETERS
@@ -338,50 +338,72 @@ static void WriteData (const cGH *GH, int vindex, const char *alias, int dim,
sprintf (slicename, "%s_[%d]", extensions[dir], myGH->sp2xyz[dim-1][dir]);
}
- filename = (char *) malloc (strlen (myGH->out_dir) + strlen (alias) +
- sizeof (slicename) + 20);
+ filename = malloc (strlen (myGH->out_dir) + strlen (alias) +
+ sizeof (slicename) + 20);
if (CCTK_Equals (mode, "remove"))
{
sprintf (filename, "%s%s_%s.jpeg", myGH->out_dir, alias, slicename);
+ tmpfilename = malloc (strlen (filename) + 5);
+ sprintf (tmpfilename, "%s.tmp", filename);
}
else
{
sprintf (filename, "%s%s_%s.it_%d.jpeg", myGH->out_dir, alias, slicename,
GH->cctk_iteration);
+ tmpfilename = NULL;
}
- file = fopen (filename, "w");
+ /* Write a JPEG file to be advertised to a temporary file first
+ and rename it later.
+ This fixes a racing problem with HTTPD when running with pthreads support:
+ a file could be downloaded (through the HTTPD thread) while is was still
+ being written to (in the main simulation thread).
+ Now the JPEG is written to a temporary file first and then (atomically)
+ renamed. */
+ file = fopen (tmpfilename ? tmpfilename : filename, "w");
if (file)
{
/* write the data */
WriteJPEGToFileRGB (hsize[0], hsize[1], dataout, colormap_quality, file);
- /* advertise the file for downloading */
- if (CCTK_Equals (mode, "remove") && myGH->out_last[vindex] < 0)
+ /* close the file */
+ fclose (file);
+
+ /* in "remove" mode: rename and advertise the file for downloading */
+ if (tmpfilename)
{
- fullname = CCTK_FullName (vindex);
- advertised_file.slice = slicename;
- advertised_file.thorn = CCTK_THORNSTRING;
- advertised_file.varname = fullname;
- advertised_file.description = "Jpegs of slices";
- advertised_file.mimetype = "image/jpeg";
+ if (rename (tmpfilename, filename))
+ {
+ CCTK_VWarn (1, __LINE__, __FILE__, CCTK_THORNSTRING,
+ "Cannot rename temporary output file '%s' into '%s'",
+ tmpfilename, filename);
+ }
+ else if (myGH->out_last[vindex] < 0)
+ {
+ fullname = CCTK_FullName (vindex);
+ advertised_file.slice = slicename;
+ advertised_file.thorn = CCTK_THORNSTRING;
+ advertised_file.varname = fullname;
+ advertised_file.description = "Jpegs of slices";
+ advertised_file.mimetype = "image/jpeg";
- IOUtil_AdvertiseFile (GH, filename, &advertised_file);
+ IOUtil_AdvertiseFile (GH, filename, &advertised_file);
- free (fullname);
+ free (fullname);
+ }
}
-
- /* close the file */
- fclose (file);
}
else
{
CCTK_VWarn (1, __LINE__, __FILE__, CCTK_THORNSTRING,
- "Cannot open IOJpeg output file '%s'", filename);
+ "Cannot open IOJpeg %s output file '%s'",
+ tmpfilename ? "temporary" : "",
+ tmpfilename ? tmpfilename : filename);
}
/* clean up */
free (dataout);
+ free (tmpfilename);
free (filename);
}