Skip to content
Permalink
Browse files

Use table cache_waypoint_pool to generate a list of unused waypoints …

…and assign waypoints to new caches from this list.
  • Loading branch information...
ocoliver
ocoliver committed Nov 4, 2012
1 parent b298bfc commit d6ae786829a6861d062a73fc0e4f01fda74f4e80
@@ -316,7 +316,24 @@
*/
$opt['logic']['ocprefixes'] = 'oc';
/* Database charset
/* pregenerated waypoint list for new caches
* - Waypoint prefix (OC, OP, OZ ... AA=local development)
* - When pool contains less than min_count, generation process starts
* and fills up the pool until max_count is reached.
*/
$opt['logic']['waypoint_pool']['prefix'] = 'AA';
$opt['logic']['waypoint_pool']['min_count'] = 1000;
$opt['logic']['waypoint_pool']['max_count'] = 2000;
// chars used for waypoints. Remember to reinstall triggers and clear cache_waypoint_pool after changing
$opt['logic']['waypoint_pool']['valid_chars'] = '0123456789ABCDEF';
// fill_gaps = true: search for gaps between used waypoints and fill up these gaps
// (fill_gaps is slow and CPU intensive on database server. For
// productive servers you may want to generate some waypoints
// without fill_gaps first)
// fill_gaps = false: continue with the last waypoint
$opt['logic']['waypoint_pool']['fill_gaps'] = false;
/* Database charset
* frontend and php charsets are UTF-8
* here you can set a different charset for the MySQL-Engine
* usefull if your database is not UTF-8.
@@ -75,6 +75,99 @@
END IF;
END;");
// get decimal value of waypoint
sql_dropFunction('WPTODEC');
sql("CREATE FUNCTION `WPTODEC` (wp VARCHAR(7), prefix VARCHAR(2)) RETURNS INT DETERMINISTIC SQL SECURITY INVOKER
BEGIN
-- all used chars in waypoint, in their ascending order
DECLARE WP_ORDER CHAR(36) DEFAULT '&1';
-- list of base 36 chars in their ascending order
DECLARE B36_ORDER CHAR(36) DEFAULT '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ';
-- will contain the waypoint value, without prefix
DECLARE WP_VALUE CHAR(5) DEFAULT '00000';
-- will contain WP_VALUE where all chars replaced by their equivalents in B36_ORDER
DECLARE B36_VALUE CHAR(5) DEFAULT '';
-- loop counter
DECLARE WP_POS INT DEFAULT 1;
-- index of a char in WP_ORDER/B36_ORDER
DECLARE WP_ORDER_INDEX INT;
-- validate input
IF ISNULL(wp) OR ISNULL(prefix) THEN
RETURN 0;
END IF;
IF LENGTH(prefix) != 2 OR LENGTH(wp)<3 OR LENGTH(wp)>7 THEN
RETURN 0;
END IF;
IF LEFT(wp, 2) != prefix THEN
RETURN 0;
END IF;
-- get waypoint value with exactly 5 digits
SET WP_VALUE = RIGHT(CONCAT('00000', SUBSTRING(wp, 3)), 5);
-- replace each char in WP_VALUE with the equivalent base 36 char
REPEAT
SET WP_ORDER_INDEX = LOCATE(SUBSTRING(WP_VALUE, WP_POS, 1), WP_ORDER);
IF WP_ORDER_INDEX = 0 THEN
RETURN 0;
END IF;
SET B36_VALUE = CONCAT(B36_VALUE, SUBSTRING(B36_ORDER, WP_ORDER_INDEX, 1));
SET WP_POS = WP_POS + 1;
UNTIL WP_POS>5 END REPEAT;
-- now use CONV() to convert from base 36 system to decimal
RETURN CONV(B36_VALUE, LENGTH(WP_ORDER), 10);
END;",
$opt['logic']['waypoint_pool']['valid_chars']);
// inverse function of WPTODEC
sql_dropFunction('DECTOWP');
sql("CREATE FUNCTION `DECTOWP` (wp INT, prefix VARCHAR(2)) RETURNS VARCHAR(7) DETERMINISTIC SQL SECURITY INVOKER
BEGIN
-- all used chars in waypoint, in their ascending order
DECLARE WP_ORDER CHAR(36) DEFAULT '&1';
-- list of base 36 chars in their ascending order
DECLARE B36_ORDER CHAR(36) DEFAULT '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ';
-- base 36 value of the decimal waypoint value
DECLARE B36_VALUE VARCHAR(5);
-- will contain the waypoint value, without prefix
DECLARE WP_VALUE CHAR(5) DEFAULT '';
-- loop counter
DECLARE B36_POS INT DEFAULT 1;
-- index of a char in WP_ORDER/B36_ORDER
DECLARE B36_ORDER_INDEX INT;
-- validate input
IF ISNULL(wp) OR ISNULL(prefix) THEN
RETURN '';
END IF;
IF LENGTH(prefix) != 2 OR wp=0 THEN
RETURN '';
END IF;
-- convert the decimal waypoint value to base 36
SET B36_VALUE = CONV(wp, 10, LENGTH(WP_ORDER));
-- replace each char in B36_VALUE with the equivalent wp-char
REPEAT
SET B36_ORDER_INDEX = LOCATE(SUBSTRING(B36_VALUE, B36_POS, 1), B36_ORDER);
IF B36_ORDER_INDEX = 0 THEN
RETURN '';
END IF;
SET WP_VALUE = CONCAT(WP_VALUE, SUBSTRING(WP_ORDER, B36_ORDER_INDEX, 1));
SET B36_POS = B36_POS + 1;
UNTIL B36_POS>LENGTH(B36_VALUE) END REPEAT;
IF LENGTH(WP_VALUE)<4 THEN
RETURN CONCAT(prefix, RIGHT(CONCAT('0000', WP_VALUE), 4));
ELSE
RETURN CONCAT(prefix, WP_VALUE);
END IF;
END;",
$opt['logic']['waypoint_pool']['valid_chars']);
/* Stored procedures containing database logic
*/
@@ -0,0 +1,8 @@
SET NAMES 'utf8';
DROP TABLE IF EXISTS `cache_waypoint_pool`;
CREATE TABLE `cache_waypoint_pool` (
`wp_oc` char(7) NOT NULL,
`cache_id` int(10) unsigned default NULL,
PRIMARY KEY (`wp_oc`),
KEY `cache_id` (`cache_id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 ;
@@ -86,43 +86,26 @@ function create_uuid()
// set a unique waypoint to this cache
function setCacheWaypoint($cacheid)
{
global $oc_waypoint_prefix;
// The following code runs into trouble, if multiple users/threads request a new
// waypoint synchronously (-> RT ticket #4071). We will hack around this problem by
// repeating the operation with random delays. Another solution would be a table-lock.
global $opt;
// 2012-08-23 following
// changes: removed 4 hexdigits limit; added random delay;
// increased maxloop 10 -> 20; simplified loop
// cleanup previous assignments failures
sql("DELETE FROM `cache_waypoint_pool` WHERE `cache_id`='&1'", $cacheid);
$nLoop = 20;
// reserve a waypoint
sql("UPDATE `cache_waypoint_pool` SET `cache_id`='&1' ORDER BY WPTODEC(`wp_oc`, '&2') ASC LIMIT 1", $cacheid, $opt['logic']['waypoint_pool']['prefix']);
do
{
// add zero to convert CONV's string result to a sortable number
$rs = sql("SELECT MAX(0 + CONV(SUBSTR(wp_oc,3),16,10)) maxwp FROM `caches` WHERE wp_oc!='OCGC77'");
$r = sql_fetch_assoc($rs);
mysql_free_result($rs);
// TODO: cronjob for waypoint pool generation may not run on development systems
// add a fix to generate a new waypoints on demand (insert this new waypoint to cache_waypoint_pool with reserved cache_id
// and follow standard assignment code to prevent race conditions with cronjob)
if ($r['maxwp'] == null)
$nNext = 1; // first cache in database
else
$nNext = $r['maxwp'] + 1;
$nNext = dechex($nNext);
while (mb_strlen($nNext) < 4)
$nNext = '0' . $nNext;
// assign reserved waypoint to the cache
// for the moment, we use IGNORE to catch duplicate keys that occur in any failure case
// the cache keeps without a waypoint in this case. Later we change field caches.wp_oc to NOT NULL and assign waypoint in BEFORE INSERT trigger
sql("UPDATE IGNORE `caches` INNER JOIN `cache_waypoint_pool` ON `caches`.`cache_id`=`cache_waypoint_pool`.`cache_id` SET `caches`.`wp_oc`=`cache_waypoint_pool`.`wp_oc` WHERE `caches`.`cache_id`='&1'", $cacheid);
$sWP = $oc_waypoint_prefix . mb_strtoupper($nNext);
if (sql("UPDATE IGNORE `caches` SET `wp_oc`='&1' WHERE `cache_id`='&2' AND ISNULL(`wp_oc`)", $sWP, $cacheid))
$nLoop = 0;
else
usleep(rand(0,50000));
} while (--$nLoop > 0);
}
// cleanup
sql("DELETE FROM `cache_waypoint_pool` WHERE `cache_id`='&1'", $cacheid);
}
function setLastFound($cacheid)
{
@@ -40,10 +40,6 @@
$oc_nodeid = 4;
$opt['logic']['node']['id'] = 4;
// waypoint prefix of the node
// OC = oc.de, OP = oc.pl, ... AA = local development
$oc_waypoint_prefix = 'OC';
//name of the cookie
$opt['cookie']['name'] = 'oc_devel';
$opt['cookie']['path'] = '/';
@@ -120,7 +116,25 @@
$opt['translate']['debug'] = false;
// see config2/settings-dist.inc.php
// copy of config2/settings-dist.inc.php
/* pregenerated waypoint list for new caches
* - Waypoint prefix (OC, OP, OZ etc.)
* - When pool contains less than min_count, generation process starts
* and fills up the pool until max_count is reached.
*/
$opt['logic']['waypoint_pool']['prefix'] = 'AA';
$opt['logic']['waypoint_pool']['min_count'] = 1000;
$opt['logic']['waypoint_pool']['max_count'] = 2000;
// chars used for waypoints. Remember to reinstall triggers and clear cache_waypoint_pool after changing
$opt['logic']['waypoint_pool']['valid_chars'] = '0123456789ABCDEF';
// fill_gaps = true: search for gaps between used waypoints and fill up these gaps
// (fill_gaps is slow and CPU intensive on database server. For
// productive servers you may want to generate some waypoints
// without fill_gaps first)
// fill_gaps = false: continue with the last waypoint
$opt['logic']['waypoint_pool']['fill_gaps'] = false;
// see config2/settings-dist.inc.php
$opt['template']['default']['locale'] = 'DE'; // may be overwritten by $opt['domain'][...]['locale']
$opt['template']['locales']['DE']['show'] = true;
@@ -33,10 +33,6 @@
//id of the node
$oc_nodeid = 4;
// waypoint prefix of the node
// OC = oc.de, OP = oc.pl, ... AA = local development
$oc_waypoint_prefix = 'AA';
//name of the cookie
$opt['cookie']['name'] = 'oc_devel';
$opt['cookie']['path'] = '/';
@@ -122,7 +118,25 @@
$opt['translate']['debug'] = false;
// see config2/settings-dist.inc.php
// copy of config2/settings-dist.inc.php
/* pregenerated waypoint list for new caches
* - Waypoint prefix (OC, OP, OZ etc.)
* - When pool contains less than min_count, generation process starts
* and fills up the pool until max_count is reached.
*/
$opt['logic']['waypoint_pool']['prefix'] = 'AA';
$opt['logic']['waypoint_pool']['min_count'] = 1000;
$opt['logic']['waypoint_pool']['max_count'] = 2000;
// chars used for waypoints. Remember to reinstall triggers and clear cache_waypoint_pool after changing
$opt['logic']['waypoint_pool']['valid_chars'] = '0123456789ABCDEF';
// fill_gaps = true: search for gaps between used waypoints and fill up these gaps
// (fill_gaps is slow and CPU intensive on database server. For
// productive servers you may want to generate some waypoints
// without fill_gaps first)
// fill_gaps = false: continue with the last waypoint
$opt['logic']['waypoint_pool']['fill_gaps'] = false;
// see config2/settings-dist.inc.php
$opt['template']['default']['locale'] = 'DE'; // may be overwritten by $opt['domain'][...]['locale']
$opt['template']['default']['country'] = 'DE'; // may be overwritten by $opt['domain'][...]['country']
Oops, something went wrong.

0 comments on commit d6ae786

Please sign in to comment.
You can’t perform that action at this time.