From: miker Date: Sun, 16 May 2010 20:19:09 +0000 (+0000) Subject: Optional pgmemcache-based caching of permission checks. Significantly speeds permiss... X-Git-Url: https://old-git.evergreen-ils.org/?a=commitdiff_plain;h=0dd6cc6f0ccef4d5a68d80ec20fd6c24501e75cd;p=evergreen%2Ftadl.git Optional pgmemcache-based caching of permission checks. Significantly speeds permission testing for common checks against heavy-use users, such as circulation-related permissions. git-svn-id: svn://svn.open-ils.org/ILS/trunk@16439 dcc99617-32d9-48b4-a31d-7c20da2025e4 --- diff --git a/Open-ILS/src/sql/Pg/pgmemcache-perm_cache.sql b/Open-ILS/src/sql/Pg/pgmemcache-perm_cache.sql new file mode 100644 index 0000000000..42f8974078 --- /dev/null +++ b/Open-ILS/src/sql/Pg/pgmemcache-perm_cache.sql @@ -0,0 +1,126 @@ +BEGIN; + +/* + * Use pgmemcache and memcached to increase the speed of permission tests + * ---------------------------------------------------------------------- + * + * This set of fuctions allows the use of memcached as a caching mechanism for + * permission checks. It is transparent an optional. If memcache is not set + * up, either by not running or the lack of the pgmemcache postgres addon, + * then the default, existing behaviour is preserved and live database queries + * are used to test all permissions. + * + * + * On postgres 8.2 and before, pgmemcache 1.1 is required. For this older + * version of pgmemcache, configuration of memcached servers is performed by + * stored procs. Therefore, the installer of this Evergreen addition must + * edit the stored proc called permission.old_mc_servers() to initialize the + * appropriate set of memcached servers. For simple, single-database + * installations, the default of 'localhost' is most likely the desired + * setting. + * + * + * On postgres 8.3 and later, pgmemcache 2.x is required. In this new + * pgmemecache the server configuration is controlled from within the + * postgresql.conf file via user-defined variables read by the pgmemcache + * intialization routines. Please see the README for pgmemcache at + * + * http://cvs.pgfoundry.org/cgi-bin/cvsweb.cgi/pgmemcache/pgmemcache/README.pgmemcache?rev=1.21&content-type=text/plain + * + * or in the release tarball that was installed for details on configuration. + * + * + * TODO: Make the cache timout configurable via a global setting for EG 2.0 + * + */ + +CREATE OR REPLACE FUNCTION permission.old_mc_servers() RETURNS BOOL AS $f$ +BEGIN + PERFORM memcache_server_add('localhost', '11211'); +END; +$f$ LANGUAGE PLPGSQL; + +CREATE OR REPLACE FUNCTION permission.mc_init() RETURNS BOOL AS $f$ +DECLARE + old_memcache BOOL; +BEGIN + old_memcache = FALSE; + IF REGEXP_REPLACE(VERSION(),E'^.+?(\\d+\\.\\d+).*?$',E'\\1')::FLOAT < 8.3 THEN + old_memcache = TRUE; + IF memcache_init() THEN + PERFORM permission.old_mc_servers(); + END IF; + -- RAISE NOTICE 'Old postgres, must be old pgmemcache'; + ELSE + BEGIN + old_memcache = TRUE; + IF memcache_init() THEN + PERFORM permission.old_mc_servers(); + END IF; + -- RAISE NOTICE 'New postgres, but old pgmemcache'; + EXCEPTION WHEN OTHERS THEN + old_memcache = FALSE; + END; + END IF; + + IF NOT old_memcache THEN + PERFORM current_setting('pgmemcache.default_servers'); + -- RAISE NOTICE 'New postgres, new pgmemcache'; + END IF; + + -- no exception, we're good + RETURN TRUE; +EXCEPTION WHEN OTHERS THEN + RETURN FALSE; +END; +$f$ LANGUAGE PLPGSQL; + +CREATE OR REPLACE FUNCTION permission.set_cached_perm( iusr INT, tperm TEXT, iorg INT, bool_value BOOL, timeout INTERVAL ) RETURNS BOOL AS $f$ +BEGIN + IF permission.mc_init() THEN + -- RAISE NOTICE 'Setting perm cache'; + IF bool_value THEN + EXECUTE $$SELECT memcache_set('oils_permcache_$$ || iusr || tperm || iorg || $$', 't',$$ || quote_literal(timeout) || $$::INTERVAL);$$; + ELSE + EXECUTE $$SELECT memcache_set('oils_permcache_$$ || iusr || tperm || iorg || $$', 'f',$$ || quote_literal(timeout) || $$::INTERVAL);$$; + END IF; + END IF; + + RETURN bool_value; +EXCEPTION WHEN OTHERS THEN + RETURN bool_value; +END; +$f$ LANGUAGE PLPGSQL STABLE; + +CREATE OR REPLACE FUNCTION permission.set_cached_perm( iusr INT, tperm TEXT, iorg INT, bool_value BOOL ) RETURNS BOOL AS $f$ + SELECT permission.set_cached_perm( $1, $2, $3, $4, '10 minutes'::INTERVAL); +$f$ LANGUAGE SQL; + +CREATE OR REPLACE FUNCTION permission.check_cached_perm( iusr INT, tperm TEXT, iorg INT ) RETURNS BOOL AS $f$ +DECLARE + cached_value RECORD; + bool_value BOOL; +BEGIN + IF permission.mc_init() THEN + -- RAISE NOTICE 'Getting perm from cache'; + EXECUTE $$SELECT memcache_get('oils_permcache_$$ || iusr || tperm || iorg || $$') AS x;$$ INTO cached_value; + bool_value := cached_value.x = 't'; + END IF; + + RETURN bool_value; +EXCEPTION WHEN OTHERS THEN + RETURN NULL; +END; +$f$ LANGUAGE PLPGSQL STABLE; + +CREATE OR REPLACE FUNCTION permission.usr_has_perm ( INT, TEXT, INT ) RETURNS BOOL AS $f$ + SELECT CASE + WHEN permission.check_cached_perm( $1, $2, $3 ) IS NOT NULL THEN permission.check_cached_perm( $1, $2, $3 ) + WHEN permission.set_cached_perm($1, $2, $3, permission.usr_has_home_perm( $1, $2, $3 )) THEN TRUE + WHEN permission.set_cached_perm($1, $2, $3, permission.usr_has_work_perm( $1, $2, $3 )) THEN TRUE + ELSE FALSE + END; +$f$ LANGUAGE SQL; + +COMMIT; +