From 1f701a61ea9d20f890d66d52087d2a272d6bfe4a Mon Sep 17 00:00:00 2001 From: John Cupitt Date: Thu, 5 May 2016 15:00:40 +0100 Subject: [PATCH] try signalling invalidate on load error to knock load ops out of cache --- TODO | 8 +++++++ libvips/foreign/foreign.c | 42 +++++++++++++++++++++++++++++++++ libvips/foreign/jpeg2vips.c | 8 ++++++- libvips/include/vips/internal.h | 2 ++ libvips/iofuncs/header.c | 4 ++++ 5 files changed, 63 insertions(+), 1 deletion(-) diff --git a/TODO b/TODO index cf0dcd7a..659486f5 100644 --- a/TODO +++ b/TODO @@ -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? diff --git a/libvips/foreign/foreign.c b/libvips/foreign/foreign.c index 7389fbf5..ead692d0 100644 --- a/libvips/foreign/foreign.c +++ b/libvips/foreign/foreign.c @@ -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" ); } /** diff --git a/libvips/foreign/jpeg2vips.c b/libvips/foreign/jpeg2vips.c index dab23237..aad4cd6e 100644 --- a/libvips/foreign/jpeg2vips.c +++ b/libvips/foreign/jpeg2vips.c @@ -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]; diff --git a/libvips/include/vips/internal.h b/libvips/include/vips/internal.h index ca92fa89..188abf77 100644 --- a/libvips/include/vips/internal.h +++ b/libvips/include/vips/internal.h @@ -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*/ diff --git a/libvips/iofuncs/header.c b/libvips/iofuncs/header.c index 5e913759..3bc00e25 100644 --- a/libvips/iofuncs/header.c +++ b/libvips/iofuncs/header.c @@ -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: