See Release Notes
Long Term Support Release
Differences Between: [Versions 401 and 403]
1 <?php 2 // This file is part of Moodle - http://moodle.org/ 3 // 4 // Moodle is free software: you can redistribute it and/or modify 5 // it under the terms of the GNU General Public License as published by 6 // the Free Software Foundation, either version 3 of the License, or 7 // (at your option) any later version. 8 // 9 // Moodle is distributed in the hope that it will be useful, 10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 // GNU General Public License for more details. 13 // 14 // You should have received a copy of the GNU General Public License 15 // along with Moodle. If not, see <http://www.gnu.org/licenses/>. 16 17 namespace core\lock; 18 19 /** 20 * Timing wrapper around a lock factory. 21 * 22 * This passes all calls through to the underlying lock factory, but adds timing information on how 23 * long it takes to get a lock and how long the lock is held for. 24 * 25 * @package core 26 * @category lock 27 * @copyright 2022 The Open University 28 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 29 */ 30 class timing_wrapper_lock_factory implements lock_factory { 31 32 /** @var lock_factory Real lock factory */ 33 protected $factory; 34 35 /** @var string Type (Frankenstyle) used for these locks */ 36 protected $type; 37 38 /** 39 * Constructor required by interface. 40 * 41 * @param string $type Type (should be same as passed to real lock factory) 42 * @param lock_factory $factory Real lock factory 43 */ 44 public function __construct($type, lock_factory $factory = null) { 45 $this->type = $type; 46 if (!$factory) { 47 // This parameter has to be optional because of the interface, but it is actually 48 // required. 49 throw new \coding_exception('The $factory parameter must be specified'); 50 } 51 $this->factory = $factory; 52 } 53 54 /** 55 * Gets the real lock factory that this is wrapping. 56 * 57 * @return lock_factory ReaL lock factory 58 */ 59 public function get_real_factory(): lock_factory { 60 return $this->factory; 61 } 62 63 /** 64 * Implementation of lock_factory::get_lock that defers to function inner_get_lock and keeps 65 * track of how long it took. 66 * 67 * @param string $resource Identifier for the lock 68 * @param int $timeout Number of seconds to wait for a lock before giving up 69 * @param int $maxlifetime Number of seconds to wait before reclaiming a stale lock 70 * @return \core\lock\lock|boolean - An instance of \core\lock\lock if the lock was obtained, or false. 71 */ 72 public function get_lock($resource, $timeout, $maxlifetime = 86400) { 73 $before = microtime(true); 74 75 $result = $this->factory->get_lock($resource, $timeout, $maxlifetime); 76 77 $after = microtime(true); 78 self::record_lock_data($after, $before, $this->type, $resource, (bool)$result, $result); 79 if ($result) { 80 $result->init_factory($this); 81 } 82 83 return $result; 84 } 85 86 /** 87 * Records statistics about a lock to the performance data. 88 * 89 * @param float $after The time after the lock was achieved. 90 * @param float $before The time before the lock was requested. 91 * @param string $type The type of lock. 92 * @param string $resource The resource being locked. 93 * @param bool $result Whether the lock was successful. 94 * @param lock|string $lock A value uniquely identifying the lock. 95 * @return void 96 */ 97 public static function record_lock_data(float $after, float $before, string $type, string $resource, bool $result, $lock) { 98 global $PERF; 99 $duration = $after - $before; 100 if (empty($PERF->locks)) { 101 $PERF->locks = []; 102 } 103 $lockdata = (object) [ 104 'type' => $type, 105 'resource' => $resource, 106 'wait' => $duration, 107 'success' => $result 108 ]; 109 if ($result) { 110 $lockdata->lock = $lock; 111 $lockdata->timestart = $after; 112 } 113 $PERF->locks[] = $lockdata; 114 } 115 116 /** 117 * Release a lock that was previously obtained with {@see get_lock}. 118 * 119 * @param lock $lock - The lock to release. 120 * @return boolean - True if the lock is no longer held (including if it was never held). 121 */ 122 public function release_lock(lock $lock) { 123 self::record_lock_released_data($lock); 124 return $this->factory->release_lock($lock); 125 } 126 127 /** 128 * Find the lock in the performance info and update it with the time held. 129 * 130 * @param lock|string $lock A value uniquely identifying the lock. 131 * @return void 132 */ 133 public static function record_lock_released_data($lock) { 134 global $PERF; 135 136 // Find this lock in the list of locks we got, looking backwards since it is probably 137 // the last one. 138 for ($index = count($PERF->locks) - 1; $index >= 0; $index--) { 139 $lockdata = $PERF->locks[$index]; 140 if (!empty($lockdata->lock) && $lockdata->lock === $lock) { 141 // Update the time held. 142 unset($lockdata->lock); 143 $lockdata->held = microtime(true) - $lockdata->timestart; 144 break; 145 } 146 } 147 } 148 149 /** 150 * Calls parent factory to check if it supports timeout. 151 * 152 * @return boolean False if attempting to get a lock will block indefinitely. 153 */ 154 public function supports_timeout() { 155 return $this->factory->supports_timeout(); 156 } 157 158 /** 159 * Calls parent factory to check if it auto-releases locks. 160 * 161 * @return boolean True if this lock type will be automatically released when the current process ends. 162 */ 163 public function supports_auto_release() { 164 return $this->factory->supports_auto_release(); 165 } 166 167 /** 168 * Calls parent factory to check if it supports recursion. 169 * 170 * @deprecated since Moodle 3.10. 171 * @return boolean True if attempting to get 2 locks on the same resource will "stack" 172 */ 173 public function supports_recursion() { 174 return $this->factory->supports_recursion(); 175 } 176 177 /** 178 * Calls parent factory to check if it is available. 179 * 180 * @return boolean True if this lock type is available in this environment. 181 */ 182 public function is_available() { 183 return $this->factory->is_available(); 184 } 185 186 /** 187 * Calls parent factory to try to extend the lock. 188 * 189 * @deprecated since Moodle 3.10. 190 * @param lock $lock Lock obtained from this factory 191 * @param int $maxlifetime New max time to hold the lock 192 * @return boolean True if the lock was extended. 193 */ 194 public function extend_lock(lock $lock, $maxlifetime = 86400) { 195 return $this->factory->extend_lock($lock, $maxlifetime); 196 } 197 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body