[gs-cvs] rev 8695 - branches/mtrender/src

ray at ghostscript.com ray at ghostscript.com
Sun May 4 10:27:05 PDT 2008


Author: ray
Date: 2008-05-04 10:27:04 -0700 (Sun, 04 May 2008)
New Revision: 8695

Modified:
   branches/mtrender/src/gxclmem.c
Log:
Fix re-opening a file for write, so that existing file is opened instead of
cloning an instance. Also add code to clean up a cloned 'log_blk' chains
if they were created because the memfile was compressed. Fixes a SEGV on
multi-page files when BAND_LIST_STORAGE=memory.


Modified: branches/mtrender/src/gxclmem.c
===================================================================
--- branches/mtrender/src/gxclmem.c	2008-05-02 20:13:50 UTC (rev 8694)
+++ branches/mtrender/src/gxclmem.c	2008-05-04 17:27:04 UTC (rev 8695)
@@ -242,74 +242,85 @@
 	    gs_note_error(gs_error_ioerror);
 	    goto finish;
 	}
-
-	/* We need to 'clone' this memfile so that each reader instance	*/
-	/* will be able to maintain it's own 'state'			*/
-	f = gs_alloc_struct(mem, MEMFILE, &st_MEMFILE,
-			    "memfile_fopen_instance(MEMFILE)");
-	if (f == NULL) {
-	    eprintf1("memfile_open_scratch(%s): gs_alloc_struct failed\n", fname);
-	    code = gs_note_error(gs_error_VMerror);
+	if (fmode[0] == 'w') {
+	    /* Reopen an existing file for 'write' */
+	    /* Check first to make sure that we have exclusive access */
+	    if (base_f->openlist != NULL) {
+		code = gs_note_error(gs_error_ioerror);
+		goto finish;
+	    }
+	    f = base_f;		/* use the file */
 	    goto finish;
-	}
-	memcpy(f, base_f, sizeof(MEMFILE));
-        f->memory = mem;
-	f->data_memory = data_mem;
-	f->compress_state = 0;		/* Not used by reader instance */
-	f->decompress_state = 0;	/* make clean for GC, or alloc'n failure */
-	f->reservePhysBlockChain = NULL;
-	f->reservePhysBlockCount = 0;
-	f->reserveLogBlockChain = NULL;
-	f->reserveLogBlockCount = 0;
-	f->openlist = base_f->openlist;
-	base_f->openlist = f;		/* link this one in to the base memfile */
-	f->base_memfile = base_f;
-	f->log_curr_pos = 0;
-	f->raw_head = NULL;
-	f->error_code = 0;
+	} else {
+	    /* Reopen an existing file for 'read' */
+	    /* We need to 'clone' this memfile so that each reader instance	*/
+	    /* will be able to maintain it's own 'state'			*/
+	    f = gs_alloc_struct(mem, MEMFILE, &st_MEMFILE,
+				"memfile_fopen_instance(MEMFILE)");
+	    if (f == NULL) {
+		eprintf1("memfile_open_scratch(%s): gs_alloc_struct failed\n", fname);
+		code = gs_note_error(gs_error_VMerror);
+		goto finish;
+	    }
+	    memcpy(f, base_f, sizeof(MEMFILE));
+	    f->memory = mem;
+	    f->data_memory = data_mem;
+	    f->compress_state = 0;		/* Not used by reader instance */
+	    f->decompress_state = 0;	/* make clean for GC, or alloc'n failure */
+	    f->reservePhysBlockChain = NULL;
+	    f->reservePhysBlockCount = 0;
+	    f->reserveLogBlockChain = NULL;
+	    f->reserveLogBlockCount = 0;
+	    f->openlist = base_f->openlist;
+	    base_f->openlist = f;		/* link this one in to the base memfile */
+	    f->base_memfile = base_f;
+	    f->log_curr_pos = 0;
+	    f->raw_head = NULL;
+	    f->error_code = 0;
 
-	if (f->log_head->phys_blk->data_limit != NULL) {
-	    /* The file is compressed, so we need to copy the logical block	*/
-	    /* list so that it is unique to this instance, and initialize	*/
-	    /* the decompressor.						*/
-	    LOG_MEMFILE_BLK *log_block, *new_log_block;
-	    int i;
-	    int num_log_blocks = (f->log_length + MEMFILE_DATA_SIZE - 1) / MEMFILE_DATA_SIZE;
-	    const stream_state *decompress_proto = clist_decompressor_state(NULL);
-	    const stream_template *decompress_template = decompress_proto->template;
+	    if (f->log_head->phys_blk->data_limit != NULL) {
+		/* The file is compressed, so we need to copy the logical block	*/
+		/* list so that it is unique to this instance, and initialize	*/
+		/* the decompressor.						*/
+		LOG_MEMFILE_BLK *log_block, *new_log_block;
+		int i;
+		int num_log_blocks = (f->log_length + MEMFILE_DATA_SIZE - 1) / MEMFILE_DATA_SIZE;
+		const stream_state *decompress_proto = clist_decompressor_state(NULL);
+		const stream_template *decompress_template = decompress_proto->template;
 
-	    new_log_block = MALLOC(f, num_log_blocks * sizeof(LOG_MEMFILE_BLK), "memfile_fopen" );
-	    if (new_log_block == NULL)
-		code = gs_note_error(gs_error_VMerror);
+		new_log_block = MALLOC(f, num_log_blocks * sizeof(LOG_MEMFILE_BLK), "memfile_fopen" );
+		if (new_log_block == NULL)
+		    code = gs_note_error(gs_error_VMerror);
 
-	    /* copy the logical blocks to the new list just allocated */
-	    for (log_block=f->log_head, i=0; log_block != NULL; log_block=log_block->link, i++) {
-		new_log_block[i].phys_blk = log_block->phys_blk;
-		new_log_block[i].phys_pdata = log_block->phys_pdata;
-		new_log_block[i].raw_block = NULL;
-		new_log_block[i].link = log_block->link == NULL ? NULL : new_log_block + i + 1;
+		/* copy the logical blocks to the new list just allocated */
+		for (log_block=f->log_head, i=0; log_block != NULL; log_block=log_block->link, i++) {
+		    new_log_block[i].phys_blk = log_block->phys_blk;
+		    new_log_block[i].phys_pdata = log_block->phys_pdata;
+		    new_log_block[i].raw_block = NULL;
+		    new_log_block[i].link = log_block->link == NULL ? NULL : new_log_block + i + 1;
+		}
+		f->log_head = new_log_block;
+
+		/* NB: don't need compress_state for reading */
+		f->decompress_state =
+		    gs_alloc_struct(mem, stream_state, decompress_template->stype,
+				    "memfile_open_scratch(decompress_state)");
+		if (f->decompress_state == 0) {
+		    eprintf1("memfile_open_scratch(%s): gs_alloc_struct failed\n", fname);
+		    code = gs_note_error(gs_error_VMerror);
+		    goto finish;
+		}
+		memcpy(f->decompress_state, decompress_proto,
+		       gs_struct_type_size(decompress_template->stype));
+		f->decompress_state->memory = mem;
+		if (decompress_template->set_defaults)
+		    (*decompress_template->set_defaults) (f->decompress_state);
 	    }
-	    f->log_head = new_log_block;
+	    f->log_curr_blk = f->log_head;
+	    memfile_get_pdata(f);		/* set up the initial block */
 
-	    /* NB: don't need compress_state for reading */
-	    f->decompress_state =
-		gs_alloc_struct(mem, stream_state, decompress_template->stype,
-				"memfile_open_scratch(decompress_state)");
-	    if (f->decompress_state == 0) {
-		eprintf1("memfile_open_scratch(%s): gs_alloc_struct failed\n", fname);
-		code = gs_note_error(gs_error_VMerror);
-		goto finish;
-	    }
-	    memcpy(f->decompress_state, decompress_proto,
-		   gs_struct_type_size(decompress_template->stype));
-	    f->decompress_state->memory = mem;
-	    if (decompress_template->set_defaults)
-		(*decompress_template->set_defaults) (f->decompress_state);
+	    goto finish;
 	}
-	f->log_curr_blk = f->log_head;
-	memfile_get_pdata(f);		/* set up the initial block */
-
-	goto finish;
     }
     fname[0] = 0;	/* no file name yet */
     f = gs_alloc_struct(mem, MEMFILE, &st_MEMFILE,
@@ -418,11 +429,34 @@
 	    prev_f->openlist = f->openlist;	/* link around the one being fclosed */
 	    /* Now delete this MEMFILE reader instance */
 	    /* NB: we don't delete 'base' instances until we delete */
-	    /* deallocate de/compress state */
-	    gs_free_object(f->memory, f->decompress_state,
-			   "memfile_close_and_unlink(decompress_state)");
-	    gs_free_object(f->memory, f->compress_state,
-			   "memfile_close_and_unlink(compress_state)");
+	    /* If the file is compressed, free the logical blocks, but not */
+	    /* the phys_blk info (that is still used by the base memfile   */
+	    if (f->log_head->phys_blk->data_limit != NULL) {
+		LOG_MEMFILE_BLK *tmpbp, *bp = f->log_head;
+
+		while (bp != NULL) {
+		    tmpbp = bp->link;
+		    FREE(f, bp, "memfile_free_mem(log_blk)");
+		    bp = tmpbp;
+		}
+		f->log_head = NULL;
+
+		/* Free any internal compressor state. */
+		if (f->compressor_initialized) {
+		    if (f->decompress_state->template->release != 0)
+			(*f->decompress_state->template->release) (f->decompress_state);
+		    if (f->compress_state->template->release != 0)
+			(*f->compress_state->template->release) (f->compress_state);
+		    f->compressor_initialized = false;
+		}
+		/* free the raw buffers                                           */
+		while (f->raw_head != NULL) {
+		    RAW_BUFFER *tmpraw = f->raw_head->fwd;
+
+		    FREE(f, f->raw_head, "memfile_free_mem(raw)");
+		    f->raw_head = tmpraw;
+		}
+	    }
 	    /* deallocate the memfile object proper */
 	    gs_free_object(f->memory, f, "memfile_close_and_unlink(MEMFILE)");
 	}



More information about the gs-cvs mailing list