From 750d7c99c354bca2c1838612cb4e35ee6f3b2a92 Mon Sep 17 00:00:00 2001 From: "Tim Malone (Mac)" Date: Sat, 17 Jun 2017 21:11:12 +1000 Subject: [PATCH] WIP: Locking/unlocking just as required --- lib/filesystem.php | 40 +++++++++++++++++++++++++++++++++++++--- src/items.php | 2 ++ src/players.php | 20 +++++++++++++------- src/spawns.php | 10 ++++++---- 4 files changed, 58 insertions(+), 14 deletions(-) diff --git a/lib/filesystem.php b/lib/filesystem.php index 84213cc..2a318db 100755 --- a/lib/filesystem.php +++ b/lib/filesystem.php @@ -163,13 +163,21 @@ function slackemon_file_get_contents( $filename, $purpose, $acquire_lock = false * @param string $purpose The purpose of the write - 'cache' or 'store'. * @link http://php.net/file_put_contents */ -function slackemon_file_put_contents( $filename, $data, $purpose ) { +function slackemon_file_put_contents( $filename, $data, $purpose, $warn_if_not_locked = true ) { // Support $data being an array, like file_put_contents() does. if ( is_array( $data ) ) { $data = implode( '', $data ); } + // Warn if we're trying to write to a data store file that we don't own a lock on + if ( 'store' === $purpose && $warn_if_not_locked && ! slackemon_is_file_owned( $filename ) ) { + slackemon_lock_debug( + 'WARNING: Writing to ' . $filename . ' without a file lock.' . PHP_EOL . + print_r( debug_backtrace( DEBUG_BACKTRACE_IGNORE_ARGS, 3 ), true ) + ); + } + switch ( slackemon_get_data_method( $purpose ) ) { case 'local': @@ -668,6 +676,7 @@ function slackemon_get_data_method( $purpose ) { function slackemon_lock_file( $filename ) { global $_slackemon_file_locks; + // If file locking is not enabled, just return true so we don't prevent things from running if ( ! SLACKEMON_ENABLE_FILE_LOCKING ) { return true; } @@ -681,8 +690,8 @@ function slackemon_lock_file( $filename ) { clearstatcache(); // Required to ensure the file_exists call doesn't rely on its cache } - if ( slackemon_file_put_contents( $lock_filename, time(), 'store' ) ) { - $_slackemon_file_locks[] = $filename; + if ( slackemon_file_put_contents( $lock_filename, time(), 'store', false ) ) { + $_slackemon_file_locks[ md5( $filename ) ] = $filename; slackemon_lock_debug( 'Lock acquired on ' . $filename ); return true; } else { @@ -692,6 +701,31 @@ function slackemon_lock_file( $filename ) { } // Function slackemon_lock_file +function slackemon_unlock_file( $filename ) { + global $_slackemon_file_locks; + + if ( ! SLACKEMON_ENABLE_FILE_LOCKING ) { + return true; + } + + $lock_filename = slackemon_get_lock_filename( $filename ); + + if ( slackemon_unlink( $lock_filename, 'store' ) ) { + slackemon_lock_debug( 'Lock individually removed on ' . $filename ); + unset( $_slackemon_file_locks[ md5( $filename ) ] ); + return true; + } else { + slackemon_lock_debug( 'WARNING: Lock COULD NOT be REMOVED on ' . $filename, true ); + return false; + } + +} // Function slackemon_unlock_file + +function slackemon_is_file_owned( $filename ) { + global $_slackemon_file_locks; + return array_key_exists( md5( $filename ), $_slackemon_file_locks ); +} + function slackemon_remove_file_locks() { global $_slackemon_file_locks; diff --git a/src/items.php b/src/items.php index 2faa090..7e0f5e6 100755 --- a/src/items.php +++ b/src/items.php @@ -98,6 +98,8 @@ function slackemon_item_spawn( $trigger = [], $region = false, $timestamp = fals return slackemon_item_spawn( $trigger, $region, $timestamp ); } + slackemon_spawn_debug( 'Ok, will spawn a ' . slackemon_readable( $item_data->name ) . '.' ); + // Store details of the item spawn $spawn = [ 'id' => $item_data->id, diff --git a/src/players.php b/src/players.php index aadf270..6137c95 100755 --- a/src/players.php +++ b/src/players.php @@ -41,20 +41,26 @@ function slackemon_register_player( $user_id = USER_ID ) { } // Function slackemon_register_player -function slackemon_save_player_data( $player_data, $user_id = USER_ID ) { +function slackemon_save_player_data( $player_data, $user_id = USER_ID, $relinquish_lock = false ) { global $data_folder, $_cached_slackemon_player_data; $player_filename = $data_folder . '/players/' . $user_id; $_cached_slackemon_player_data[ $user_id ] = $player_data; - return slackemon_file_put_contents( $player_filename, json_encode( $player_data ), 'store' ); + $return = slackemon_file_put_contents( $player_filename, json_encode( $player_data ), 'store' ); + + if ( $relinquish_lock ) { + slackemon_unlock_file( $player_filename ); + } + + return $return; } // Function slackemon_save_player_data -function slackemon_get_player_data( $user_id = USER_ID ) { +function slackemon_get_player_data( $user_id = USER_ID, $for_writing = false ) { global $data_folder, $_cached_slackemon_player_data; - if ( isset( $_cached_slackemon_player_data[ $user_id ] ) ) { + if ( ! $for_writing && isset( $_cached_slackemon_player_data[ $user_id ] ) ) { return $_cached_slackemon_player_data[ $user_id ]; } @@ -66,7 +72,7 @@ function slackemon_get_player_data( $user_id = USER_ID ) { return false; } - $player_data = json_decode( slackemon_file_get_contents( $player_filename, 'store', true ) ); + $player_data = json_decode( slackemon_file_get_contents( $player_filename, 'store', $for_writing ) ); $_cached_slackemon_player_data[ $user_id ] = $player_data; // Ensure player is not caught in a cancelled region if the available regions change @@ -358,10 +364,10 @@ function slackemon_get_player_menu_mode( $user_id = USER_ID ) { function slackemon_set_player_menu_mode( $menu_mode, $user_id = USER_ID ) { - $player_data = slackemon_get_player_data( $user_id ); + $player_data = slackemon_get_player_data( $user_id, true ); $player_data->menu_mode = $menu_mode; - return slackemon_save_player_data( $player_data, $user_id ); + return slackemon_save_player_data( $player_data, $user_id, true ); } // Function slackemon_set_player_menu_mode diff --git a/src/spawns.php b/src/spawns.php index 16dd268..d18d0da 100755 --- a/src/spawns.php +++ b/src/spawns.php @@ -240,6 +240,8 @@ function( $_pokemon ) use ( $region_pokedex ) { return slackemon_spawn( $trigger, $region, $timestamp ); } + slackemon_spawn_debug( 'Ok, will spawn a ' . slackemon_readable( $pokemon->name ) . '.' ); + // Determine nature $natures = slackemon_get_natures(); $nature = $natures[ array_rand( $natures ) ]; @@ -333,7 +335,7 @@ function slackemon_save_spawn_data( $spawn_data ) { $spawn_filename = $data_folder . '/spawns/' . $spawn_id; $_cached_slackemon_spawn_data[ $spawn_id ] = $spawn_data; - return slackemon_file_put_contents( $spawn_filename, json_encode( $spawn_data ), 'store' ); + return slackemon_file_put_contents( $spawn_filename, json_encode( $spawn_data ), 'store', false ); } // Function slackemon_save_spawn_data @@ -580,7 +582,7 @@ function slackemon_notify_spawn( $spawn ) { function slackemon_record_spawn_for_user( $user_id, $spawn ) { global $data_folder; - $player_data = slackemon_get_player_data( $user_id ); + $player_data = slackemon_get_player_data( $user_id, true ); // Can we increment the 'seen' value on an existing spawn? $found_entry = false; @@ -611,9 +613,9 @@ function slackemon_record_spawn_for_user( $user_id, $spawn ) { 'cp' => $spawn['cp'], 'hp' => $spawn['stats']['hp'], ]; - slackemon_file_put_contents( $spawn_filename, json_encode( $spawn_data ), 'store' ); + slackemon_file_put_contents( $spawn_filename, json_encode( $spawn_data ), 'store', false ); - return slackemon_save_player_data( $player_data, $user_id ); + return slackemon_save_player_data( $player_data, $user_id, true ); } // Function slackemon_record_spawn