Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Begin event on database #2757

Merged
merged 5 commits into from
Jul 17, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 19 additions & 4 deletions core/class/DB.class.php
Original file line number Diff line number Diff line change
Expand Up @@ -656,14 +656,18 @@ public static function compareTable($_table) {
$return[$_table['name']]['sql'] .= static::buildDefinitionField($field);
$return[$_table['name']]['sql'] .= ',';
}
$return[$_table['name']]['sql'] .= "\n" . 'primary key(';
$primary_key = '';
foreach ($_table['fields'] as $field) {
if (isset($field['key']) && $field['key'] == 'PRI') {
$return[$_table['name']]['sql'] .= '`' . $field['name'] . '`,';
$primary_key .= '`' . $field['name'] . '`,';
}
}
$return[$_table['name']]['sql'] = trim($return[$_table['name']]['sql'], ',');
$return[$_table['name']]['sql'] .= ')';
if($primary_key != ''){
$return[$_table['name']]['sql'] .= "\n" . 'primary key(';
$return[$_table['name']]['sql'] = trim($primary_key, ',');
$return[$_table['name']]['sql'] .= ')';
}
$return[$_table['name']]['sql'] = trim($return[$_table['name']]['sql'],',');
$return[$_table['name']]['sql'] .= ')' . "\n";
if (!isset($_table['engine'])) {
$_table['engine'] = 'InnoDB';
Expand All @@ -676,6 +680,17 @@ public static function compareTable($_table) {
return $return;
}
$forceRebuildIndex = false;
try {
$status = DB::Prepare('show table status where name="' . $_table['name'] . '"', array(), DB::FETCH_TYPE_ROW);
} catch (\Exception $e) {
$status = array();
}
if(!isset($_table['engine'])){
$_table['engine'] = 'InnoDB';
}
if(isset($status['Engine']) && $status['Engine'] != $_table['engine']){
$return[$_table['name']]['sql'] = 'ALTER TABLE `' . $_table['name'] . '` ENGINE = '.$_table['engine'];
}
foreach ($_table['fields'] as $field) {
$found = false;
foreach ($describes as $describe) {
Expand Down
221 changes: 97 additions & 124 deletions core/class/event.class.php
Original file line number Diff line number Diff line change
Expand Up @@ -22,137 +22,89 @@
class event {
/* * *************************Attributs****************************** */

private static $limit = 250;
private static $_fd = null;
protected $datetime;
protected $name;
protected $option;

/* * ***********************Methode static*************************** */

public static function getFileDescriptorLock() {
if (self::$_fd === null) {
@chmod(jeedom::getTmpFolder() . '/event_cache_lock', 0777);
self::$_fd = fopen(jeedom::getTmpFolder() . '/event_cache_lock', 'w');
}
if (self::$_fd === false) {
@chmod(jeedom::getTmpFolder() . '/event_cache_lock', 0777);
self::$_fd = fopen(jeedom::getTmpFolder() . '/event_cache_lock', 'w');
}
return self::$_fd;
}

public static function add($_event, $_option = array()) {
if (config::byKey('cache::engine') == 'MariadbCache') {
$cache = cache::byKey('event');
$value = json_decode($cache->getValue('[]'), true);
if (!is_array($value)) {
$value = array();
}
$value[] = array('datetime' => getmicrotime(), 'name' => $_event, 'option' => $_option);
cache::set('event', json_encode(self::cleanEvent($value)));
return;
}
$waitIfLocked = true;
$fd = self::getFileDescriptorLock();
if($fd === false){
return;
}
if (@flock($fd, LOCK_EX, $waitIfLocked)) {
$cache = cache::byKey('event');
$value = json_decode($cache->getValue('[]'), true);
if (!is_array($value)) {
$value = array();
}
$value[] = array('datetime' => getmicrotime(), 'name' => $_event, 'option' => $_option);
cache::set('event', json_encode(self::cleanEvent($value)));
flock($fd, LOCK_UN);
}
public static function add($_event, $_option = array(),$_clean = true) {
if(is_array($_option)){
$_option = json_encode($_option, JSON_UNESCAPED_UNICODE);
}
$value = array(
'datetime' => getmicrotime(),
'name' => $_event,
'option' => $_option
);
$sql = 'INSERT INTO `event` SET `datetime`=:datetime, `name`=:name,`option`=:option';
DB::Prepare($sql,$value, DB::FETCH_TYPE_ROW);
}

public static function adds($_event, $_values = array()) {
if (config::byKey('cache::engine') == 'MariadbCache') {
$cache = cache::byKey('event');
$value_src = json_decode($cache->getValue('[]'), true);
if (!is_array($value_src)) {
$value_src = array();
}
$value = array();
foreach ($_values as $option) {
$value[] = array('datetime' => getmicrotime(), 'name' => $_event, 'option' => $option);
}
cache::set('event', json_encode(self::cleanEvent(array_merge($value_src, $value))));
return;
}
$waitIfLocked = true;
$fd = self::getFileDescriptorLock();
if($fd === false){
return;
}
if (flock($fd, LOCK_EX, $waitIfLocked)) {
$cache = cache::byKey('event');
$value_src = json_decode($cache->getValue('[]'), true);
if (!is_array($value_src)) {
$value_src = array();
}
$value = array();
foreach ($_values as $option) {
$value[] = array('datetime' => getmicrotime(), 'name' => $_event, 'option' => $option);
}
cache::set('event', json_encode(self::cleanEvent(array_merge($value_src, $value))));
flock($fd, LOCK_UN);
foreach ($_values as $option) {
self::add($_event,$option,false);
}
}

public static function cleanEvent($_events) {
$_events = array_slice(array_values($_events), -self::$limit, self::$limit);
public static function cleanEvent() {
$sql = 'SELECT count(*) as number FROM `event`';
$result = DB::Prepare($sql, array(), DB::FETCH_TYPE_ROW);
$delete_number = $result['number'] - 250;
if($delete_number > 0){
$sql = 'DELETE FROM event ORDER BY `datetime` ASC LIMIT '.$delete_number;
DB::Prepare($sql, array(), DB::FETCH_TYPE_ROW);
}
$sql = 'SELECT ' . DB::buildField(__CLASS__) . '
FROM event';
$events = DB::Prepare($sql, array(), DB::FETCH_TYPE_ALL, PDO::FETCH_CLASS, __CLASS__);
$find = array();
$events = array_values($_events);
$now = strtotime('now') + 300;
foreach ($events as $key => $event) {
if ($event['datetime'] > $now) {
unset($events[$key]);
foreach ($events as $event) {
if ($event->getDatetime() > $now) {
$event->remove();
continue;
}
if ($event['name'] == 'eqLogic::update') {
$id = 'eqLogic::update::' . $event['option']['eqLogic_id'];
} elseif ($event['name'] == 'cmd::update') {
$id = 'cmd::update::' . $event['option']['cmd_id'];
} elseif ($event['name'] == 'scenario::update') {
$id = 'scenario::update::' . $event['option']['scenario_id'];
} elseif ($event['name'] == 'jeeObject::summary::update') {
$id = 'jeeObject::summary::update::' . $event['option']['object_id'];
if (is_array($event['option']['keys']) && count($event['option']['keys']) > 0) {
foreach ($event['option']['keys'] as $key2 => $value) {
if ($event->getName() == 'eqLogic::update') {
$id = 'eqLogic::update::' . $event->getOption('eqLogic_id');
} elseif ($event->getName() == 'cmd::update') {
$id = 'cmd::update::' . $event->getOption('cmd_id');
} elseif ($event->getName() == 'scenario::update') {
$id = 'scenario::update::' . $event->getOption('scenario_id');
} elseif ($event->getName() == 'jeeObject::summary::update') {
$id = 'jeeObject::summary::update::' . $event->getOption('object_id');
if (is_array($event->getOption('keys')) && count($event->getOption('keys')) > 0) {
foreach ($event->getOption('keys') as $key2 => $value) {
$id .= $key2;
}
}
} else {
continue;
}
if (isset($find[$id])) {
if ($find[$id]['datetime'] > $event['datetime']) {
unset($events[$key]);
if ($find[$id]->getDatetime() > $event->getDatetime()) {
$event->remove();
continue;
} else {
unset($events[$find[$id]['key']]);
$find[$id]->remove();
unset($find[$id]);
}
}
$find[$id] = array('datetime' => $event['datetime'], 'key' => $key);
$find[$id] = $event;
}
return array_values($events);
}

public static function orderEvent($a, $b) {
return ($a['datetime'] - $b['datetime']);
}

public static function changes($_datetime, $_longPolling = null, $_filter = null) {
self::cleanEvent();
$return = self::filterEvent(self::changesSince($_datetime), $_filter);
if ($_longPolling === null || count($return['result']) > 0) {
return $return;
if ($_longPolling === null || count($return) > 0) {
return array('datetime' => getmicrotime(), 'result'=> utils::o2a($return));
}
$waitTime = config::byKey('event::waitPollingTime');
$i = 0;
$max_cycle = $_longPolling / $waitTime;
while (count($return['result']) == 0 && $i < $max_cycle) {
while (count($return) == 0 && $i < $max_cycle) {
if ($waitTime < 1) {
usleep(1000000 * $waitTime);
} else {
Expand All @@ -162,24 +114,23 @@ public static function changes($_datetime, $_longPolling = null, $_filter = null
$return = self::filterEvent(self::changesSince($_datetime), $_filter);
$i++;
}
$return['result'] = self::cleanEvent($return['result']);
return $return;
return array('datetime' => getmicrotime(), 'result'=> utils::o2a($return));
}

private static function filterEvent($_data = array(), $_filter = null) {
private static function filterEvent($_events = array(), $_filter = null) {
if ($_filter == null) {
return $_data;
return $_events;
}
$filters = ($_filter !== null) ? cache::byKey($_filter . '::event')->getValue(array()) : array();
$return = array('datetime' => $_data['datetime'], 'result' => array());
foreach ($_data['result'] as $value) {
if ($_filter !== null && isset($_filter::$_listenEvents) && !in_array($value['name'], $_filter::$_listenEvents)) {
$return = array();
foreach (_events as $event) {
if ($_filter !== null && isset($_filter::$_listenEvents) && !in_array($event->getName(), $_filter::$_listenEvents)) {
continue;
}
if (count($filters) != 0 && $value['name'] == 'cmd::update' && !in_array($value['option']['cmd_id'], $filters)) {
if (count($filters) != 0 && $event->getName() == 'cmd::update' && !in_array($event->getOption('cmd_id'), $filters)) {
continue;
}
$return['result'][] = $value;
$return[] = $event;
}
return $return;
}
Expand All @@ -189,27 +140,49 @@ private static function changesSince($_datetime) {
if ($_datetime > $now) {
$_datetime = $now;
}
$return = array('datetime' => $_datetime, 'result' => array());
$cache = cache::byKey('event');
$events = json_decode($cache->getValue('[]'), true);
if (!is_array($events)) {
$events = array();
}
$values = array_reverse($events);
if (count($values) > 0) {
$return['datetime'] = $values[0]['datetime'];
foreach ($values as $value) {
if ($value['datetime'] <= $_datetime) {
break;
}
$return['result'][] = $value;
}
}
$return['result'] = array_reverse($return['result']);
return $return;
$sql = 'SELECT ' . DB::buildField(__CLASS__) . '
FROM event
WHERE `datetime` >= :datetime
ORDER BY `datetime`';
return DB::Prepare($sql, array('datetime' => $_datetime), DB::FETCH_TYPE_ALL, PDO::FETCH_CLASS, __CLASS__);
}

/* * *********************Methode d'instance************************* */

public function save($_direct = false){
DB::save($this, $_direct);
}

public function remove() {
return DB::remove($this);
}

/* * **********************Getteur Setteur*************************** */

public function getDatetime() {
return $this->datetime;
}

public function setDatetime($_datetime) {
$this->datetime = $_datetime;
return $this;
}

public function getName() {
return $this->name;
}

public function setName($_name) {
$this->name = $_name;
return $this;
}

public function getOption($_key = '', $_default = '') {
return utils::getJsonAttr($this->option, $_key, $_default);
}

public function setOption($_key, $_value) {
$this->option = utils::setJsonAttr($this->option, $_key, $_value);
return $this;
}
}
45 changes: 44 additions & 1 deletion install/database.json
Original file line number Diff line number Diff line change
Expand Up @@ -276,7 +276,7 @@
},
{
"name": "lifetime",
"type": "int",
"type": "int(11)",
"null": "YES",
"key": "",
"default": null,
Expand Down Expand Up @@ -716,6 +716,48 @@
}
}
},
{
"name": "event",
"engine" : "MEMORY",
"fields": [
{
"name": "datetime",
"type": "double(16,6)",
"null": "YES",
"key": "",
"default": null,
"extra": ""
},
{
"name": "name",
"type": "varchar(255)",
"null": "YES",
"key": "",
"default": null,
"extra": ""
},
{
"name": "option",
"type": "varchar(4095)",
"null": "YES",
"key": "",
"default": null,
"extra": ""
}
],
"indexes": {
"datetime": {
"Key_name": "datetime",
"Non_unique": "1",
"columns": {
"1": {
"column": "datetime",
"Sub_part": null
}
}
}
}
},
{
"name": "history",
"fields": [
Expand Down Expand Up @@ -920,6 +962,7 @@
},
{
"name": "interactQuery",
"engine" : "MyISAM",
"fields": [
{
"name": "id",
Expand Down
Loading