Merge branch 'patch-20181028a' into 'dev'

Add timestamp to pconfig

See merge request hubzilla/core!1355
This commit is contained in:
Mario 2018-11-05 10:40:29 +01:00
commit d6523c67a6
6 changed files with 157 additions and 20 deletions

View File

@ -57,6 +57,7 @@ class PConfig {
\App::$config[$uid][$c]['config_loaded'] = true; \App::$config[$uid][$c]['config_loaded'] = true;
} }
\App::$config[$uid][$c][$k] = $rr['v']; \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 * The value to store
* @return mixed Stored $value or false * @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 // this catches subtle errors where this function has been called
// with local_channel() when not logged in (which returns false) // with local_channel() when not logged in (which returns false)
@ -130,29 +131,74 @@ class PConfig {
$dbvalue = ((is_array($value)) ? serialize($value) : $value); $dbvalue = ((is_array($value)) ? serialize($value) : $value);
$dbvalue = ((is_bool($dbvalue)) ? intval($dbvalue) : $dbvalue); $dbvalue = ((is_bool($dbvalue)) ? intval($dbvalue) : $dbvalue);
if (! $updated) {
$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(self::Get($uid, $family, $key) === false) {
if(! array_key_exists($uid, \App::$config)) if(! array_key_exists($uid, \App::$config))
\App::$config[$uid] = array(); \App::$config[$uid] = array();
if(! array_key_exists($family, \App::$config[$uid])) if(! array_key_exists($family, \App::$config[$uid]))
\App::$config[$uid][$family] = array(); \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), intval($uid),
dbesc($family), dbesc($family),
dbesc($key), dbesc($key),
dbesc($dbvalue) dbesc($dbvalue),
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;
} }
else { else {
$new = (\App::$config[$uid][$family]['pcfgud:'.$key] < $updated);
$ret = q("UPDATE pconfig SET v = '%s' WHERE uid = %d and cat = '%s' AND k = '%s'", if ($new) {
dbesc($dbvalue),
intval($uid), // @NOTE There is still a possible race condition under limited circumstances
dbesc($family), // where a value will be updated by another thread with more current data than
dbesc($key) // 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),
intval($uid),
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 // keep a separate copy for all variables which were
// set in the life of this page. We need this to // set in the life of this page. We need this to
// synchronise channel clones. // synchronise channel clones.
@ -163,7 +209,11 @@ class PConfig {
\App::$config[$uid]['transient'][$family] = array(); \App::$config[$uid]['transient'][$family] = array();
\App::$config[$uid][$family][$key] = $value; \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) if($ret)
return $value; return $value;
@ -186,18 +236,29 @@ class PConfig {
* The configuration key to delete * The configuration key to delete
* @return mixed * @return mixed
*/ */
static public function Delete($uid, $family, $key) { static public function Delete($uid, $family, $key, $updated = NULL) {
if(is_null($uid) || $uid === false) if(is_null($uid) || $uid === false)
return 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; $ret = false;
if(array_key_exists($uid,\App::$config) if (isset(\App::$config[$uid][$family][$key])) {
&& is_array(\App::$config['uid'])
&& array_key_exists($family,\App::$config['uid'])
&& array_key_exists($key, \App::$config[$uid][$family]))
unset(\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'", $ret = q("DELETE FROM pconfig WHERE uid = %d AND cat = '%s' AND k = '%s'",
intval($uid), intval($uid),
@ -205,6 +266,22 @@ class PConfig {
dbesc($key) 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]))
\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; return $ret;
} }

26
Zotlabs/Update/_1225.php Normal file
View File

@ -0,0 +1,26 @@
<?php
namespace Zotlabs\Update;
class _1225 {
function run() {
if(ACTIVE_DBTYPE == DBTYPE_POSTGRES) {
$r1 = q("ALTER TABLE pconfig ADD updated timestamp NOT NULL DEFAULT '0001-01-01 00:00:00' ");
$r2 = q("create index \"pconfig_updated_idx\" on pconfig (\"updated\")");
$r = ($r1 && $r2);
}
else {
$r = q("ALTER TABLE `pconfig` ADD `updated` datetime NOT NULL DEFAULT '0001-01-01 00:00:00' ,
ADD INDEX `pconfig_updated` (`updated`)");
}
if($r)
return UPDATE_SUCCESS;
return UPDATE_FAILED;
}
}

View File

@ -54,7 +54,7 @@ define ( 'STD_VERSION', '3.9.4' );
define ( 'ZOT_REVISION', '6.0a' ); define ( 'ZOT_REVISION', '6.0a' );
define ( 'DB_UPDATE_VERSION', 1224 ); define ( 'DB_UPDATE_VERSION', 1225 );
define ( 'PROJECT_BASE', __DIR__ ); define ( 'PROJECT_BASE', __DIR__ );

View File

@ -59,8 +59,8 @@ function set_pconfig($uid, $family, $key, $value) {
return Zlib\PConfig::Set($uid,$family,$key,$value); return Zlib\PConfig::Set($uid,$family,$key,$value);
} }
function del_pconfig($uid, $family, $key) { function del_pconfig($uid, $family, $key, $updated = NULL) {
return Zlib\PConfig::Delete($uid,$family,$key); return Zlib\PConfig::Delete($uid,$family,$key,$updated);
} }
function load_xconfig($xchan) { function load_xconfig($xchan) {

View File

@ -3507,8 +3507,41 @@ function process_channel_sync_delivery($sender, $arr, $deliveries) {
if(array_key_exists('config',$arr) && is_array($arr['config']) && count($arr['config'])) { if(array_key_exists('config',$arr) && is_array($arr['config']) && count($arr['config'])) {
foreach($arr['config'] as $cat => $k) { foreach($arr['config'] as $cat => $k) {
foreach($arr['config'][$cat] as $k => $v)
set_pconfig($channel['channel_id'],$cat,$k,$v); $pconfig_updated = [];
$pconfig_del = [];
foreach($arr['config'][$cat] as $k => $v) {
if (strpos($k,'pcfgud:')===0) {
$realk = substr($k,7);
$pconfig_updated[$realk] = $v;
unset($arr['config'][$cat][$k]);
}
if (strpos($k,'pcfgdel:')===0) {
$realk = substr($k,8);
$pconfig_del[$realk] = datetime_convert();
unset($arr['config'][$cat][$k]);
}
}
foreach($arr['config'][$cat] as $k => $v) {
if (!isset($pconfig_updated[$k])) {
$pconfig_updated[$k] = NULL;
}
set_pconfig($channel['channel_id'],$cat,$k,$v,$pconfig_updated[$k]);
}
foreach($pconfig_del as $k => $updated) {
del_pconfig($channel['channel_id'],$cat,$k,$updated);
}
} }
} }

View File

@ -1505,6 +1505,7 @@ class ComposerStaticInit7b34d7e50a62201ec5d5e526a5b8b35d
'Zotlabs\\Update\\_1222' => __DIR__ . '/../..' . '/Zotlabs/Update/_1222.php', 'Zotlabs\\Update\\_1222' => __DIR__ . '/../..' . '/Zotlabs/Update/_1222.php',
'Zotlabs\\Update\\_1223' => __DIR__ . '/../..' . '/Zotlabs/Update/_1223.php', 'Zotlabs\\Update\\_1223' => __DIR__ . '/../..' . '/Zotlabs/Update/_1223.php',
'Zotlabs\\Update\\_1224' => __DIR__ . '/../..' . '/Zotlabs/Update/_1224.php', 'Zotlabs\\Update\\_1224' => __DIR__ . '/../..' . '/Zotlabs/Update/_1224.php',
'Zotlabs\\Update\\_1225' => __DIR__ . '/../..' . '/Zotlabs/Update/_1225.php',
'Zotlabs\\Web\\CheckJS' => __DIR__ . '/../..' . '/Zotlabs/Web/CheckJS.php', 'Zotlabs\\Web\\CheckJS' => __DIR__ . '/../..' . '/Zotlabs/Web/CheckJS.php',
'Zotlabs\\Web\\Controller' => __DIR__ . '/../..' . '/Zotlabs/Web/Controller.php', 'Zotlabs\\Web\\Controller' => __DIR__ . '/../..' . '/Zotlabs/Web/Controller.php',
'Zotlabs\\Web\\HTTPHeaders' => __DIR__ . '/../..' . '/Zotlabs/Web/HTTPHeaders.php', 'Zotlabs\\Web\\HTTPHeaders' => __DIR__ . '/../..' . '/Zotlabs/Web/HTTPHeaders.php',