182 lines
3.7 KiB
PL/PgSQL
182 lines
3.7 KiB
PL/PgSQL
-- LegacyWorlds Beta 6
|
|
-- PostgreSQL database scripts
|
|
--
|
|
-- Game updates - control functions
|
|
--
|
|
-- Copyright(C) 2004-2010, DeepClone Development
|
|
-- --------------------------------------------------------
|
|
|
|
|
|
|
|
--
|
|
-- Start a tick
|
|
--
|
|
|
|
CREATE OR REPLACE FUNCTION sys.start_tick( OUT tick_id BIGINT )
|
|
STRICT VOLATILE
|
|
SECURITY DEFINER
|
|
AS $$
|
|
DECLARE
|
|
n_tick BIGINT;
|
|
c_tick BIGINT;
|
|
BEGIN
|
|
-- Get next / current tick
|
|
SELECT INTO n_tick , c_tick next_tick , current_tick
|
|
FROM sys.status
|
|
WHERE maintenance_start IS NULL
|
|
FOR UPDATE;
|
|
IF NOT FOUND OR c_tick IS NOT NULL THEN
|
|
tick_id := NULL;
|
|
RETURN;
|
|
END IF;
|
|
|
|
-- Prepare game updates
|
|
UPDATE sys.updates SET last_tick = n_tick , status = 'FUTURE'
|
|
WHERE last_tick < n_tick;
|
|
|
|
-- Update system status
|
|
UPDATE sys.status SET current_tick = n_tick , next_tick = n_tick + 1;
|
|
|
|
tick_id := n_tick;
|
|
END;
|
|
$$ LANGUAGE plpgsql;
|
|
|
|
GRANT EXECUTE ON FUNCTION sys.start_tick( ) TO :dbuser;
|
|
|
|
|
|
|
|
--
|
|
-- Marks a tick as completed
|
|
--
|
|
|
|
CREATE OR REPLACE FUNCTION sys.end_tick( IN tick_id BIGINT )
|
|
RETURNS VOID
|
|
STRICT VOLATILE
|
|
SECURITY DEFINER
|
|
AS $$
|
|
BEGIN
|
|
UPDATE events.events SET status = 'READY'
|
|
WHERE status = 'TICK' AND tick = tick_id;
|
|
UPDATE sys.status SET current_tick = NULL;
|
|
PERFORM msgs.deliver_internal( );
|
|
END;
|
|
$$ LANGUAGE plpgsql;
|
|
|
|
GRANT EXECUTE ON FUNCTION sys.end_tick( BIGINT ) TO :dbuser;
|
|
|
|
|
|
|
|
--
|
|
-- Check if a tick got "stuck"
|
|
--
|
|
|
|
CREATE OR REPLACE FUNCTION sys.check_stuck_tick( OUT tick_id BIGINT )
|
|
STRICT VOLATILE
|
|
SECURITY DEFINER
|
|
AS $$
|
|
DECLARE
|
|
c_tick BIGINT;
|
|
u_count INT;
|
|
BEGIN
|
|
-- Get next / current tick
|
|
SELECT INTO c_tick current_tick
|
|
FROM sys.status
|
|
WHERE maintenance_start IS NULL
|
|
FOR UPDATE;
|
|
IF NOT FOUND OR c_tick IS NULL THEN
|
|
tick_id := NULL;
|
|
RETURN;
|
|
END IF;
|
|
|
|
-- Are there any updates left?
|
|
SELECT INTO u_count count(*) FROM sys.updates
|
|
WHERE status = 'FUTURE' AND last_tick = c_tick;
|
|
IF u_count = 0 THEN
|
|
PERFORM sys.end_tick( c_tick );
|
|
tick_id := NULL;
|
|
ELSE
|
|
tick_id := c_tick;
|
|
END IF;
|
|
END;
|
|
$$ LANGUAGE plpgsql;
|
|
|
|
GRANT EXECUTE ON FUNCTION sys.check_stuck_tick( ) TO :dbuser;
|
|
|
|
|
|
|
|
--
|
|
-- Prepare game updates
|
|
--
|
|
-- Parameters:
|
|
-- u_id Current update identifier
|
|
-- u_type Type of game updates to prepare
|
|
--
|
|
-- Returns:
|
|
-- has_more TRUE if there are more updates, FALSE otherwise
|
|
--
|
|
|
|
CREATE OR REPLACE FUNCTION sys.prepare_updates( IN u_id BIGINT , IN u_type update_type , OUT has_more BOOLEAN )
|
|
STRICT VOLATILE
|
|
SECURITY DEFINER
|
|
AS $$
|
|
BEGIN
|
|
UPDATE sys.updates SET status = 'PROCESSING'
|
|
WHERE id IN (
|
|
SELECT id FROM sys.updates
|
|
WHERE gu_type = u_type
|
|
AND last_tick = u_id
|
|
AND status = 'FUTURE'
|
|
ORDER BY id
|
|
LIMIT sys.get_constant( 'game.batchSize' )::BIGINT
|
|
);
|
|
|
|
has_more := FOUND;
|
|
END;
|
|
$$ LANGUAGE plpgsql;
|
|
|
|
GRANT EXECUTE ON FUNCTION sys.prepare_updates( BIGINT , update_type ) TO :dbuser;
|
|
|
|
|
|
|
|
--
|
|
-- Execute procedural game updates
|
|
--
|
|
-- Parameters:
|
|
-- c_tick Current tick identifier
|
|
-- u_type Type of updates to execute
|
|
--
|
|
|
|
CREATE OR REPLACE FUNCTION sys.exec_update_proc( IN c_tick BIGINT , IN u_type update_type )
|
|
RETURNS VOID
|
|
STRICT VOLATILE
|
|
SECURITY DEFINER
|
|
AS $$
|
|
BEGIN
|
|
EXECUTE 'SELECT sys.process_' || lower( u_type::TEXT ) || '_updates( $1 )'
|
|
USING c_tick;
|
|
END;
|
|
$$ LANGUAGE plpgsql;
|
|
|
|
GRANT EXECUTE ON FUNCTION sys.exec_update_proc( BIGINT , update_type ) TO :dbuser;
|
|
|
|
|
|
--
|
|
-- Mark updates as processed
|
|
--
|
|
-- Parameters:
|
|
-- c_tick Current tick identifier
|
|
-- u_type Type of updates to execute
|
|
--
|
|
|
|
CREATE OR REPLACE FUNCTION sys.updates_processed( IN c_tick BIGINT , IN u_type update_type )
|
|
RETURNS VOID
|
|
STRICT VOLATILE
|
|
SECURITY DEFINER
|
|
AS $$
|
|
UPDATE sys.updates SET status = 'PROCESSED'
|
|
WHERE status = 'PROCESSING'
|
|
AND last_tick = $1
|
|
AND gu_type = $2
|
|
$$ LANGUAGE SQL;
|
|
|
|
GRANT EXECUTE ON FUNCTION sys.updates_processed( BIGINT , update_type ) TO :dbuser;
|