From c7c35b8b5a64e44f01e7557a43d13e518dc62aa8 Mon Sep 17 00:00:00 2001 From: "M.Dent" Date: Sun, 28 Oct 2018 17:20:29 -0400 Subject: DB Updates to prep for pconfig timestamps. --- Zotlabs/Update/_1225.php | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) create mode 100644 Zotlabs/Update/_1225.php (limited to 'Zotlabs') diff --git a/Zotlabs/Update/_1225.php b/Zotlabs/Update/_1225.php new file mode 100644 index 000000000..a7d866154 --- /dev/null +++ b/Zotlabs/Update/_1225.php @@ -0,0 +1,26 @@ + Date: Sun, 28 Oct 2018 17:23:31 -0400 Subject: Add timestamp and associated logic to pconfig --- Zotlabs/Lib/PConfig.php | 65 ++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 53 insertions(+), 12 deletions(-) (limited to 'Zotlabs') diff --git a/Zotlabs/Lib/PConfig.php b/Zotlabs/Lib/PConfig.php index ec0792ce1..31c0ee87b 100644 --- a/Zotlabs/Lib/PConfig.php +++ b/Zotlabs/Lib/PConfig.php @@ -57,6 +57,7 @@ class PConfig { \App::$config[$uid][$c]['config_loaded'] = true; } \App::$config[$uid][$c][$k] = $rr['v']; + \App::$config[$uid][$c]['pcfgud:'.$k] = $rr['updated']; } } } @@ -113,7 +114,7 @@ class PConfig { * The value to store * @return mixed Stored $value or false */ - static public function Set($uid, $family, $key, $value) { + static public function Set($uid, $family, $key, $value, $updated=NULL) { // this catches subtle errors where this function has been called // with local_channel() when not logged in (which returns false) @@ -130,27 +131,43 @@ class PConfig { $dbvalue = ((is_array($value)) ? serialize($value) : $value); $dbvalue = ((is_bool($dbvalue)) ? intval($dbvalue) : $dbvalue); + if (! $updated) { + $updated = datetime_convert(); + } + + if(self::Get($uid, $family, $key) === false) { if(! array_key_exists($uid, \App::$config)) \App::$config[$uid] = array(); if(! array_key_exists($family, \App::$config[$uid])) \App::$config[$uid][$family] = array(); - $ret = q("INSERT INTO pconfig ( uid, cat, k, v ) VALUES ( %d, '%s', '%s', '%s' ) ", + $ret = q("INSERT INTO pconfig ( uid, cat, k, v, updated ) VALUES ( %d, '%s', '%s', '%s', '%s' ) ", intval($uid), dbesc($family), dbesc($key), - dbesc($dbvalue) + dbesc($dbvalue), + dbesc($updated) ); + + \App::$config[$uid][$family]['pcfgud:'.$key] = $updated; + } else { - - $ret = q("UPDATE pconfig SET v = '%s' WHERE uid = %d and cat = '%s' AND k = '%s'", - dbesc($dbvalue), - intval($uid), - dbesc($family), - dbesc($key) - ); + $new = (\App::$config[$uid][$family]['pcfgud:'.$key] < $updated); + + if ($new) { + $ret = q("UPDATE pconfig SET v = '%s' WHERE uid = %d and cat = '%s' AND k = '%s' AND updated = '%s'", + dbesc($dbvalue), + intval($uid), + dbesc($family), + dbesc($key), + dbesc($updated) + ); + } else { + logger('Refusing to update pconfig with outdated info.', LOGGER_NORMAL, LOG_ERR); + return self::Get($uid, $family, $key); + } } // keep a separate copy for all variables which were @@ -163,7 +180,11 @@ class PConfig { \App::$config[$uid]['transient'][$family] = array(); \App::$config[$uid][$family][$key] = $value; - \App::$config[$uid]['transient'][$family][$key] = $value; + + if ($new) { + \App::$config[$uid]['transient'][$family][$key] = $value; + \App::$config[$uid]['transient'][$family]['pcfgud:'.$key] = $updated; + } if($ret) return $value; @@ -186,11 +207,20 @@ class PConfig { * The configuration key to delete * @return mixed */ - static public function Delete($uid, $family, $key) { + static public function Delete($uid, $family, $key, $updated = NULL) { if(is_null($uid) || $uid === false) return false; + $updated = ($updated) ? $updated : datetime_convert(); + + $newer = (\App::$config[$uid][$family]['pcfgud:'.$key] < $updated); + + if (! $newer) { + logger('Refusing to delete pconfig with outdated delete request.', LOGGER_NORMAL, LOG_ERR); + return false; + } + $ret = false; if(array_key_exists($uid,\App::$config) @@ -205,6 +235,17 @@ class PConfig { dbesc($key) ); + // Synchronize delete with clones. + + if(! array_key_exists('transient', \App::$config[$uid])) + \App::$config[$uid]['transient'] = array(); + if(! array_key_exists($family, \App::$config[$uid]['transient'])) + \App::$config[$uid]['transient'][$family] = array(); + + if ($new) { + \App::$config[$uid]['transient'][$family]['pcfgdel:'.$key] = $updated; + } + return $ret; } -- cgit v1.2.3 From 1241e778f9073b5ba50d966eea20b28b9400339b Mon Sep 17 00:00:00 2001 From: "M.Dent" Date: Sun, 28 Oct 2018 17:30:22 -0400 Subject: Fix to set update time in pconfig on update --- Zotlabs/Lib/PConfig.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'Zotlabs') diff --git a/Zotlabs/Lib/PConfig.php b/Zotlabs/Lib/PConfig.php index 31c0ee87b..8bc5681f0 100644 --- a/Zotlabs/Lib/PConfig.php +++ b/Zotlabs/Lib/PConfig.php @@ -157,12 +157,12 @@ class PConfig { $new = (\App::$config[$uid][$family]['pcfgud:'.$key] < $updated); if ($new) { - $ret = q("UPDATE pconfig SET v = '%s' WHERE uid = %d and cat = '%s' AND k = '%s' AND updated = '%s'", + $ret = q("UPDATE pconfig SET v = '%s', updated = '%s' WHERE uid = %d and cat = '%s' AND k = '%s' ", dbesc($dbvalue), + dbesc($updated), intval($uid), dbesc($family), - dbesc($key), - dbesc($updated) + dbesc($key) ); } else { logger('Refusing to update pconfig with outdated info.', LOGGER_NORMAL, LOG_ERR); -- cgit v1.2.3 From 0060f88c4599c5cda1c6d5a7f6eb345a496e382f Mon Sep 17 00:00:00 2001 From: "M.Dent" Date: Mon, 29 Oct 2018 23:04:13 -0400 Subject: Add tracking of deleted pconfig variables --- Zotlabs/Lib/PConfig.php | 44 ++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 40 insertions(+), 4 deletions(-) (limited to 'Zotlabs') diff --git a/Zotlabs/Lib/PConfig.php b/Zotlabs/Lib/PConfig.php index 8bc5681f0..b9384cf6b 100644 --- a/Zotlabs/Lib/PConfig.php +++ b/Zotlabs/Lib/PConfig.php @@ -135,6 +135,16 @@ class PConfig { $updated = datetime_convert(); } + $hash = hash('sha256',$family.':'.$key); + + if (self::Get($uid, 'hz_delpconfig', $hash) !== false) { + if (Get($uid, 'hz_delpconfig', $hash) > $updated) { + logger('Refusing to update pconfig with outdated info (Item deleted more recently).', LOGGER_NORMAL, LOG_ERR); + return self::Get($uid,$family,$key); + } else { + self::Delete($uid,'hz_delpconfig',$hash); + } + } if(self::Get($uid, $family, $key) === false) { if(! array_key_exists($uid, \App::$config)) @@ -142,6 +152,7 @@ class PConfig { if(! array_key_exists($family, \App::$config[$uid])) \App::$config[$uid][$family] = array(); + $ret = q("INSERT INTO pconfig ( uid, cat, k, v, updated ) VALUES ( %d, '%s', '%s', '%s', '%s' ) ", intval($uid), dbesc($family), @@ -150,6 +161,14 @@ class PConfig { dbesc($updated) ); + // There is a possible race condition if another process happens + // to insert something after this thread has Loaded and now. We should + // at least make a note of it if it happens. + + if (!$ret) { + logger("Error: Insert to pconfig failed.",LOGGER_NORMAL, LOG_ERR); + } + \App::$config[$uid][$family]['pcfgud:'.$key] = $updated; } @@ -157,6 +176,12 @@ class PConfig { $new = (\App::$config[$uid][$family]['pcfgud:'.$key] < $updated); if ($new) { + + // @NOTE There is still a possible race condition under limited circumstances + // where a value will be updated by another thread with more current data than + // we have. At this point there is no easy way to test for it, so we update + // and hope for the best. + $ret = q("UPDATE pconfig SET v = '%s', updated = '%s' WHERE uid = %d and cat = '%s' AND k = '%s' ", dbesc($dbvalue), dbesc($updated), @@ -164,12 +189,16 @@ class PConfig { dbesc($family), dbesc($key) ); + + \App::$config[$uid][$family]['pcfgud:'.$key] = $updated; + } else { logger('Refusing to update pconfig with outdated info.', LOGGER_NORMAL, LOG_ERR); return self::Get($uid, $family, $key); } } + // keep a separate copy for all variables which were // set in the life of this page. We need this to // synchronise channel clones. @@ -223,11 +252,13 @@ class PConfig { $ret = false; - if(array_key_exists($uid,\App::$config) - && is_array(\App::$config['uid']) - && array_key_exists($family,\App::$config['uid']) - && array_key_exists($key, \App::$config[$uid][$family])) + if (isset(\App::$config[$uid][$family][$key])) { unset(\App::$config[$uid][$family][$key]); + } + + if (isset(\App::$config[$uid][$family]['pcfgud:'.$key])) { + unset(\App::$config[$uid][$family]['pcfgud:'.$key]); + } $ret = q("DELETE FROM pconfig WHERE uid = %d AND cat = '%s' AND k = '%s'", intval($uid), @@ -235,6 +266,11 @@ class PConfig { dbesc($key) ); + if ($family != 'hz_delpconfig') { + $hash = hash('sha256',$family.':'.$key); + set_pconfig($uid,'hz_delpconfig',$hash,$updated); + } + // Synchronize delete with clones. if(! array_key_exists('transient', \App::$config[$uid])) -- cgit v1.2.3