Commit feaeeffc authored by Carsten  Rose's avatar Carsten Rose
Browse files

recordLocking

DatabaseUpdateData.php: Table Form: recordLockTimeoutSeconds - default changed from 0 to 900 secs. Existing forms get the default timeout timout interval.
Dirty.php, QuickFormQuery.php: recordLockTimeoutSeconds will be retrieved from the Form.recordLockTimeoutSeconds definition (instead of parsing config.qfq.ini). Therefore a definition per form ist possible.
parent 4475fab6
......@@ -268,10 +268,9 @@ class QuickFormQuery {
// Check and release dirtyRecord.
if ($formMode === FORM_DELETE || $formMode === FORM_SAVE) {
$lockTimeout = $this->store->getVar(STORE_SYSTEM, SYSTEM_RECORD_LOCK_TIMEOUT_SECONDS);
$dirty = new Dirty($lockTimeout);
$dirty->checkDirtyAndRelease($formMode, $this->formSpec[F_DIRTY_MODE], $this->formSpec[F_TABLE_NAME],
$recordId);
$dirty = new Dirty();
$dirty->checkDirtyAndRelease($formMode, $this->formSpec[F_RECORD_LOCK_TIMEOUT_SECONDS],
$this->formSpec[F_DIRTY_MODE], $this->formSpec[F_TABLE_NAME], $recordId);
}
if ($formMode === FORM_DELETE) {
......
......@@ -55,7 +55,7 @@ $UPDATE_ARRAY = array(
'0.19.0' => [
"ALTER TABLE `Form` ADD `dirtyMode` ENUM( 'exclusive', 'advisory', 'none' ) NOT NULL DEFAULT 'exclusive' AFTER `requiredParameter`",
"ALTER TABLE `Form` ADD `recordLockTimeoutSeconds` INT NOT NULL DEFAULT '0' AFTER `parameter`"
"ALTER TABLE `Form` ADD `recordLockTimeoutSeconds` INT NOT NULL DEFAULT '900' AFTER `parameter`"
],
);
......
......@@ -40,26 +40,14 @@ class Dirty {
*/
private $session = null;
/**
* @var array()
*/
private $lockTimeout = false;
/**
* Init class
*/
public function __construct($lockTimeout = false, $phpUnit = false) {
public function __construct($phpUnit = false) {
$this->session = Session::getInstance($phpUnit);
$this->client = Client::getParam();
$this->db = new Database();
if($lockTimeout === false) {
$cfg = new Config();
$config = $cfg->readConfig('');
$this->lockTimeout = $config[SYSTEM_RECORD_LOCK_TIMEOUT_SECONDS];
} else {
$this->lockTimeout = $lockTimeout;
}
}
/**
......@@ -83,7 +71,7 @@ class Dirty {
$recordId = empty($sipVars[SIP_RECORD_ID]) ? 0 : $sipVars[SIP_RECORD_ID];
if($recordId>0) {
$tableVars = $this->db->sql("SELECT tableName, dirtyMode FROM Form AS f WHERE f.name=?", ROW_EXPECT_1, [$sipVars[SIP_FORM]], "Form not found: '" . $sipVars[SIP_FORM] . "'");
$tableVars = $this->db->sql("SELECT tableName, dirtyMode, recordLockTimeoutSeconds FROM Form AS f WHERE f.name=?", ROW_EXPECT_1, [$sipVars[SIP_FORM]], "Form not found: '" . $sipVars[SIP_FORM] . "'");
}
switch($this->client[API_LOCK_ACTION]) {
......@@ -91,7 +79,7 @@ class Dirty {
$answer = $this->acquireDirty($recordId, $tableVars);
break;
case API_LOCK_ACTION_RELEASE:
$answer = $this->checkDirtyAndRelease(FORM_SAVE, $tableVars[F_DIRTY_MODE], $tableVars[F_TABLE_NAME], $recordId);
$answer = $this->checkDirtyAndRelease(FORM_SAVE, $tableVars[F_RECORD_LOCK_TIMEOUT_SECONDS], $tableVars[F_DIRTY_MODE], $tableVars[F_TABLE_NAME], $recordId);
break;
default;
throw new CodeException("Unknown action: " . $this->client[API_LOCK_ACTION], ERROR_DIRTY_UNKNOWN_ACTION);
......@@ -127,8 +115,9 @@ class Dirty {
$recordDirty = $this->getRecordDirty($tableName, $recordId);
// Check if the record is timed out
if (count($recordDirty) != 0 && $this->lockTimeout > 0) {
$datetimeExpire = date_add(date_create($recordDirty[COLUMN_MODIFIED]), date_interval_create_from_date_string($this->lockTimeout . " second"));
if (count($recordDirty) != 0 && $tableVars[F_RECORD_LOCK_TIMEOUT_SECONDS] > 0) {
$datetimeExpire = date_add(date_create($recordDirty[COLUMN_MODIFIED]),
date_interval_create_from_date_string($tableVars[F_RECORD_LOCK_TIMEOUT_SECONDS] . " second"));
if ($datetimeExpire <= date_create("now")) {
$this->deleteDirtyRecord($recordDirty[COLUMN_ID]);
$recordDirty=array();
......@@ -137,7 +126,7 @@ class Dirty {
if (count($recordDirty) == 0) {
// No dirty record found.
$answer = $this->writeDirty($this->client[SIP_SIP], $recordId, $tableName, $formDirtyMode, $feUser);
$answer = $this->writeDirty($this->client[SIP_SIP], $recordId, $tableVars, $feUser);
} else {
$answer = $this->conflict($recordDirty, $formDirtyMode);
}
......@@ -204,14 +193,16 @@ class Dirty {
*
* @param string $s SIP given by URL GET
* @param int $recordId extracted from SIP
* @param string $tableName extracted from SIP
* @param string $formDirtyMode
* @param array $tableVars
* @param string $feUser
* @return array
* @throws CodeException
* @throws DbException
*/
private function writeDirty($s, $recordId, $tableName, $formDirtyMode, $feUser) {
private function writeDirty($s, $recordId,array $tableVars, $feUser) {
$tableName = $tableVars[F_TABLE_NAME];
$formDirtyMode = $tableVars[F_DIRTY_MODE];
$record = $this->db->sql("SELECT * FROM $tableName WHERE id=?", ROW_EXPECT_1, [$recordId], "Record to tag 'dirty' not found.");
......@@ -220,9 +211,12 @@ class Dirty {
// Write 'dirty' record
$this->db->sql("INSERT INTO Dirty (`sip`, `tableName`, `recordId`, `recordModified`, `feUser`, `qfqUserSessionCookie`, `dirtyMode`, `remoteAddress`, `created`) " .
"VALUES ( ?,?,?,?,?,?,?,?,? )", ROW_REGULAR, [$s, $tableName, $recordId, $recordModified, $feUser, $this->client[CLIENT_COOKIE_QFQ], $formDirtyMode, $this->client[CLIENT_REMOTE_ADDRESS], date('YmdHis')]);
"VALUES ( ?,?,?,?,?,?,?,?,? )", ROW_REGULAR,
[$s, $tableName, $recordId, $recordModified, $feUser, $this->client[CLIENT_COOKIE_QFQ], $formDirtyMode,
$this->client[CLIENT_REMOTE_ADDRESS], date('YmdHis')]);
return [API_STATUS => API_ANSWER_STATUS_SUCCESS, API_MESSAGE => '', API_LOCK_TIMEOUT => $this->lockTimeout ];
return [API_STATUS => API_ANSWER_STATUS_SUCCESS, API_MESSAGE => '',
API_LOCK_TIMEOUT => $tableVars[F_RECORD_LOCK_TIMEOUT_SECONDS] ];
}
......@@ -231,6 +225,7 @@ class Dirty {
* In case of not owner, throws an exception and the save should break.
*
* @param string $formMode FORM_DELETE, FORM_SAVE
* @param int $lockTimeout
* @param string $dirtyMode DIRTY_MODE_EXCLUSIVE, DIRTY_MODE_ADVISORY, DIRTY_MODE_NONE
* @param string $tableName
* @param int $recordId
......@@ -238,7 +233,7 @@ class Dirty {
* @throws CodeException
* @throws UserFormException
*/
public function checkDirtyAndRelease($formMode, $dirtyMode, $tableName, $recordId) {
public function checkDirtyAndRelease($formMode, $lockTimeout, $dirtyMode, $tableName, $recordId) {
$answer = [ API_STATUS => API_ANSWER_STATUS_SUCCESS, API_MESSAGE => ''];
......@@ -286,8 +281,8 @@ class Dirty {
}
// Check if the record is timed out
if ($this->lockTimeout > 0) {
$datetimeExpire = date_add(date_create($recordDirty[COLUMN_MODIFIED]), date_interval_create_from_date_string($this->lockTimeout . " second"));
if ($lockTimeout > 0) {
$datetimeExpire = date_add(date_create($recordDirty[COLUMN_MODIFIED]), date_interval_create_from_date_string($lockTimeout . " second"));
if ($datetimeExpire <= date_create("now")) {
$this->deleteDirtyRecord($recordDirty[COLUMN_ID]);
return $answer;
......
......@@ -27,7 +27,7 @@ CREATE TABLE IF NOT EXISTS `Form` (
`bsNoteColumns` VARCHAR(255) NOT NULL DEFAULT '',
`parameter` TEXT NOT NULL,
`recordLockTimeoutSeconds` INT(11) NOT NULL DEFAULT 0,
`recordLockTimeoutSeconds` INT(11) NOT NULL DEFAULT 900,
`deleted` ENUM('yes', 'no') NOT NULL DEFAULT 'no',
`modified` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
......@@ -214,7 +214,8 @@ VALUES
(1, 'modified', 'Modified', 'readonly', 'text', 'all', 'native', 370, 0, 20, '', '', '', '', '', 3, '', '', '', 'specialchar', 'no', ''),
(1, 'created', 'Created', 'readonly', 'text', 'all', 'native', 380, 0, 20, '', '', '', '', '', 3, '', '', '', 'specialchar', 'no', ''),
(1, 'multi', 'Multi', 'show', 'fieldset', 'all', 'native', 400, 0, 0, '', '', '', '', '', 4, '', '', '', 'specialchar', 'no', ''),
(1, 'multi', 'Multi', 'show', 'fieldset', 'all', 'native', 400, 0, 0, '', '', '', '', '', 4, '', '', '',
'specialchar', 'no', ''),
(1, 'multiMode', 'Multi Mode', 'show', 'radio', 'all', 'native', 410, 0, 0, '', '', '', '', '', 4, '', '', '',
'specialchar', 'no', ''),
(1, 'multiSql', 'Multi SQL', 'show', 'text', 'all', 'native', 420, '40,3', 0, '', '', '', '', '', 4, '', '', '',
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment