try signalling invalidate on load error

to knock load ops out of cache
This commit is contained in:
John Cupitt 2016-05-05 15:00:40 +01:00
parent ca731e7967
commit 1f701a61ea
5 changed files with 63 additions and 1 deletions

8
TODO
View File

@ -1,3 +1,11 @@
- jpegload should put a pointer to the load operation inside the output image
somewhere
can we do this in the base class?
then the loaders can use this if they get a read error from the lib to
invalidate the load operation and knock it out of cache
- I like the new int mask creator in reducev, can we use it in im_vips2imask()
as well?

View File

@ -322,6 +322,10 @@
* ]|
*/
/* Usr this to link images to the load operations that made them.
*/
static GQuark vips__foreign_load_operation = 0;
G_DEFINE_ABSTRACT_TYPE( VipsForeign, vips_foreign, VIPS_TYPE_OPERATION );
static void
@ -882,6 +886,13 @@ vips_foreign_load_build( VipsObject *object )
g_object_set( object, "out", vips_image_new(), NULL );
/* Note the load object on the output image. Loaders can use this to
* signal invalidate if they hit a load error. See
* vips_foreign_load_invalidate() below.
*/
g_object_set_qdata( G_OBJECT( load->out ),
vips__foreign_load_operation, object );
vips_image_set_string( load->out,
VIPS_META_LOADER, class->nickname );
@ -1003,6 +1014,34 @@ vips_foreign_load_init( VipsForeignLoad *load )
load->access = VIPS_ACCESS_RANDOM;
}
/**
* Loaders can call this
*/
/**
* vips_foreign_load_invalidate:
* @image: image to invalidate
*
* Loaders can call this on the image they are making if they see a read error
* from the load library. It signals "invalidate" on the load operation and
* will cause it for be dropped from ache.
*
* If we know a file will cause a read error, we don't want to cache the error
* operation, we want to make sure the image will really be opened again if our
* caller tries again. For example, a broken file might be replaced by a
* working one.
*/
void
vips_foreign_load_invalidate( VipsImage *image )
{
VipsOperation *operation;
if( (operation = g_object_get_qdata( G_OBJECT( image ),
vips__foreign_load_operation )) ) {
vips_operation_invalidate( operation );
}
}
/* Abstract base class for image savers.
*/
@ -1763,6 +1802,9 @@ vips_foreign_operation_init( void )
#ifdef HAVE_OPENEXR
vips_foreign_load_openexr_get_type();
#endif /*HAVE_OPENEXR*/
vips__foreign_load_operation =
g_quark_from_static_string( "vips-foreign-load-operation" );
}
/**

View File

@ -959,8 +959,14 @@ read_jpeg_generate( VipsRegion *or,
/* Here for longjmp() from vips__new_error_exit().
*/
if( setjmp( jpeg->eman.jmp ) )
if( setjmp( jpeg->eman.jmp ) ) {
/* Signal invalidate on our load operation to force it from
* cache.
*/
vips_foreign_load_invalidate( or->im );
return( -1 );
}
for( y = 0; y < r->height; y++ ) {
JSAMPROW row_pointer[1];

View File

@ -246,6 +246,8 @@ typedef struct _VipsImagePixels {
gint64 npels; /* Number of pels calculated so far */
} VipsImagePixels;
void vips_foreign_load_invalidate( VipsImage *image );
#ifdef __cplusplus
}
#endif /*__cplusplus*/

View File

@ -402,6 +402,10 @@ vips_image_guess_format( const VipsImage *image )
{
VipsBandFormat format;
/* Stop a compiler warning.
*/
format = VIPS_INTERPRETATION_MULTIBAND;
switch( image->Type ) {
case VIPS_INTERPRETATION_B_W:
case VIPS_INTERPRETATION_HISTOGRAM: