MDL-14992 towards better db sessions - session locking for mysql
This commit is contained in:
@@ -1739,6 +1739,17 @@ abstract class moodle_database {
|
||||
return false;
|
||||
}
|
||||
|
||||
/// session locking
|
||||
public function get_session_lock($name, $timeout) {
|
||||
// TODO: make this abstract
|
||||
return true;
|
||||
}
|
||||
|
||||
public function release_session_lock($name) {
|
||||
// TODO: make this abstract
|
||||
return true;
|
||||
}
|
||||
|
||||
/// performance and logging
|
||||
/**
|
||||
* Returns number of reads done by this database
|
||||
|
||||
@@ -23,7 +23,7 @@ class mysqli_native_moodle_database extends moodle_database {
|
||||
/// TODO: Decide if this method should go to DDL instead of being here
|
||||
public function create_database($dbhost, $dbuser, $dbpass, $dbname) {
|
||||
ob_start();
|
||||
$conn= new mysqli($dbhost, $dbuser, $dbpass); /// Connect without db
|
||||
$conn = new mysqli($dbhost, $dbuser, $dbpass); /// Connect without db
|
||||
$dberr = ob_get_contents();
|
||||
ob_end_clean();
|
||||
$errorno = @$conn->connect_errno;
|
||||
@@ -880,6 +880,51 @@ class mysqli_native_moodle_database extends moodle_database {
|
||||
return $positivematch ? 'REGEXP' : 'NOT REGEXP';
|
||||
}
|
||||
|
||||
/// session locking
|
||||
public function get_session_lock($name, $timeout) {
|
||||
$fullname = $this->dbname.'-'.$this->prefix.'-'.$name;
|
||||
$sql = "SELECT GET_LOCK(?,?)";
|
||||
$params = array($fullname, $timeout);
|
||||
$rawsql = $this->emulate_bound_params($sql, $params);
|
||||
|
||||
$this->query_start($sql, $params, SQL_QUERY_AUX);
|
||||
$result = $this->mysqli->query($rawsql);
|
||||
$this->query_end($result);
|
||||
|
||||
if ($result) {
|
||||
$arr = $result->fetch_assoc();
|
||||
$result->close();
|
||||
|
||||
if (reset($arr) == 1) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public function release_session_lock($name) {
|
||||
$fullname = $this->dbname.'-'.$this->prefix.'-'.$name;
|
||||
$sql = "SELECT RELEASE_LOCK(?)";
|
||||
$params = array($fullname);
|
||||
$rawsql = $this->emulate_bound_params($sql, $params);
|
||||
|
||||
$this->query_start($sql, $params, SQL_QUERY_AUX);
|
||||
$result = $this->mysqli->query($rawsql);
|
||||
$this->query_end($result);
|
||||
|
||||
if ($result) {
|
||||
$arr = $result->fetch_assoc();
|
||||
$result->close();
|
||||
|
||||
if (reset($arr) == 1) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/// transactions
|
||||
/**
|
||||
* on DBs that support it, switch to transaction mode and begin a transaction
|
||||
|
||||
+10
-2
@@ -311,7 +311,6 @@ class database_session extends session_stub {
|
||||
public function handler_read($sid) {
|
||||
global $CFG;
|
||||
|
||||
// TODO: implement normal locking (and later speculative locking)
|
||||
// TODO: implement timeout + auth plugin hook (see gc)
|
||||
|
||||
if ($this->record and $this->record->sid != $sid) {
|
||||
@@ -319,6 +318,11 @@ class database_session extends session_stub {
|
||||
return '';
|
||||
}
|
||||
|
||||
// lock session
|
||||
while (!$this->database->get_session_lock($sid, 10)) {
|
||||
sleep(1);
|
||||
}
|
||||
|
||||
try {
|
||||
if (!$record = $this->database->get_record('sessions', array('sid'=>$sid))) {
|
||||
$record = new object();
|
||||
@@ -367,6 +371,8 @@ class database_session extends session_stub {
|
||||
return true;
|
||||
}
|
||||
|
||||
$this->database->release_session_lock($this->record->sid);
|
||||
|
||||
$this->record->sid = $sid; // it might be regenerated
|
||||
$this->record->sessdata = base64_encode($session_data); // there might be some binary mess :-(
|
||||
$this->record->sessdatahash = md5($this->record->sessdata);
|
||||
@@ -391,6 +397,8 @@ class database_session extends session_stub {
|
||||
return true;
|
||||
}
|
||||
|
||||
$this->database->release_session_lock($this->record->sid);
|
||||
|
||||
try {
|
||||
$this->database->delete_records('sessions', array('sid'=>$this->record->sid));
|
||||
} catch (dml_exception $ex) {
|
||||
@@ -404,7 +412,7 @@ class database_session extends session_stub {
|
||||
$select = "timemodified + :maxlifetime < :now";
|
||||
$params = array('now'=>time(), 'maxlifetime'=>$maxlifetime);
|
||||
|
||||
// TODO: add auth plugin hook that would allow extennding of max lifetime
|
||||
// TODO: add auth plugin hook that would allow extending of max lifetime
|
||||
|
||||
try {
|
||||
$this->database->delete_records_select('sessions', $select, $params);
|
||||
|
||||
Reference in New Issue
Block a user