florian030
2014-02-20 0543b213df8eaaa4c3067296ab517bc5fa2ec70e
add mysql-quota (http://www.howtoforge.com/forums/showthread.php?t=64975)
4 files added
18 files modified
372 ■■■■ changed files
install/sql/ispconfig3.sql 3 ●●●●● patch | view | raw | blame | history
install/tpl/server.ini.master 2 ●●●●● patch | view | raw | blame | history
interface/lib/classes/tools_monitor.inc.php 25 ●●●●● patch | view | raw | blame | history
interface/web/admin/form/server_config.tform.php 12 ●●●●● patch | view | raw | blame | history
interface/web/admin/lib/lang/en_server_config.lng 2 ●●●●● patch | view | raw | blame | history
interface/web/admin/templates/server_config_web_edit.htm 12 ●●●●● patch | view | raw | blame | history
interface/web/client/form/client.tform.php 14 ●●●●● patch | view | raw | blame | history
interface/web/client/form/client_template.tform.php 14 ●●●●● patch | view | raw | blame | history
interface/web/client/lib/lang/en_client.lng 2 ●●●●● patch | view | raw | blame | history
interface/web/client/lib/lang/en_client_template.lng 6 ●●●●● patch | view | raw | blame | history
interface/web/client/templates/client_edit_limits.htm 4 ●●●● patch | view | raw | blame | history
interface/web/client/templates/client_template_edit_limits.htm 6 ●●●● patch | view | raw | blame | history
interface/web/sites/database_edit.php 16 ●●●●● patch | view | raw | blame | history
interface/web/sites/form/database.tform.php 16 ●●●●● patch | view | raw | blame | history
interface/web/sites/lib/lang/en_database.lng 3 ●●●●● patch | view | raw | blame | history
interface/web/sites/templates/database_edit.htm 6 ●●●● patch | view | raw | blame | history
server/conf/mail/db_quota_notification_de.txt 13 ●●●●● patch | view | raw | blame | history
server/conf/mail/db_quota_notification_en.txt 13 ●●●●● patch | view | raw | blame | history
server/conf/mail/db_quota_ok_notification_de.txt 13 ●●●●● patch | view | raw | blame | history
server/conf/mail/db_quota_ok_notification_en.txt 13 ●●●●● patch | view | raw | blame | history
server/lib/classes/cron.d/100-monitor_database_size.inc.php 59 ●●●● patch | view | raw | blame | history
server/lib/classes/cron.d/300-quota_notify.inc.php 118 ●●●●● patch | view | raw | blame | history
install/sql/ispconfig3.sql
@@ -214,6 +214,7 @@
  `default_dbserver` int(11) NOT NULL DEFAULT '1',
  `dns_servers` blob NOT NULL DEFAULT '',
  `limit_database` int(11) NOT NULL DEFAULT '-1',
  `limit_database_quota` int(11) NOT NULL default '-1',
  `limit_cron` int(11) NOT NULL DEFAULT '0',
  `limit_cron_type` enum('url','chrooted','full') NOT NULL DEFAULT 'url',
  `limit_cron_frequency` int(11) NOT NULL DEFAULT '5',
@@ -317,6 +318,7 @@
  `limit_dns_slave_zone` int(11) NOT NULL default '-1',
  `limit_dns_record` int(11) NOT NULL default '-1',
  `limit_database` int(11) NOT NULL default '-1',
  `limit_database_quota` int(11) NOT NULL default '-1',
  `limit_cron` int(11) NOT NULL default '0',
  `limit_cron_type` enum('url','chrooted','full') NOT NULL default 'url',
  `limit_cron_frequency` int(11) NOT NULL default '5',
@@ -1757,6 +1759,7 @@
  `type` varchar(16) NOT NULL DEFAULT 'y',
  `database_name` varchar(64) DEFAULT NULL,
  `database_name_prefix` varchar(50) NOT NULL default '',
  `database_quota` int(11) unsigned DEFAULT NULL,
  `database_user_id` int(11) unsigned DEFAULT NULL,
  `database_ro_user_id` int(11) unsigned DEFAULT NULL,
  `database_charset` varchar(64) DEFAULT NULL,
install/tpl/server.ini.master
@@ -101,6 +101,8 @@
overquota_notify_admin=y
overquota_notify_client=y
overquota_notify_freq=7
overquota_db_notify_admin=y
overquota_db_notify_client=y
overquota_notify_onok=n
[dns]
interface/lib/classes/tools_monitor.inc.php
@@ -124,32 +124,35 @@
        $record = $app->db->queryOneRecord("SELECT data, state FROM monitor_data WHERE type = 'database_size' and server_id = " . $_SESSION['monitor']['server_id'] . " order by created desc");
        if(isset($record['data'])) {
            $data = unserialize($record['data']);
            /*
                Format the data
                */
            //* format the data
            $html =
                '<div class="systemmonitor-state state-'.$record['state'].'">
                    <div class="systemmonitor-content icons32 ico-'.$record['state'].'">
                    <table>
                    <thead>
                    <tr>
                    <table><thead><tr>
                    <td>'.$app->lng("monitor_database_name_txt").'</td>
                    <td>'.$app->lng("monitor_database_size_txt").'</td>
                    <td>'.$app->lng("monitor_database_client_txt").'</td>
                    <td>'.$app->lng("monitor_database_domain_txt").'</td>
                    </tr>';
            foreach($data as $line) {
                $html .= '<tr>';
                if ($line['size'] > 0) $line['size'] = $app->functions->formatBytes($line['size']);
                $t=$app->db->queryOneRecord("SELECT username FROM client WHERE sys_groupid = ".$line['client_id']);
                $line['client_id']=$t['username'];
                unset($t);
                //* get the client
                $line['client']=$app->db->queryOneRecord("SELECT client.username FROM web_database, sys_group, client WHERE web_database.sys_groupid = sys_group.groupid AND sys_group.client_id = client.client_id AND web_database.database_name='".$line['database_name']."'")['username'];
                //* get the domain
                $line['domain']=$app->db->queryOneRecord("SELECT domain FROM web_domain WHERE domain_id=(SELECT parent_domain_id FROM web_database WHERE database_name='".$line['database_name']."')")['domain'];
                //* remove the sys_groupid from output
                unset($line['sys_groupid']);
                foreach ($line as $item) {
                    $html .= '<td>' . $item . '</td>';
                }
                $html .= '</tr></tmpl loop>';
            }
            $html .= '</tbody></table>';
            $html .= '</div></div>';
            $html .= '</tbody></table></div></div>';
        } else {
            $html = '<p>'.$app->lng("no_data_database_size_txt").'</p>';
        }
interface/web/admin/form/server_config.tform.php
@@ -688,6 +688,18 @@
            'default' => 'y',
            'value' => array(0 => 'n', 1 => 'y')
        ),
        'overquota_db_notify_admin' => array(
            'datatype' => 'VARCHAR',
            'formtype' => 'CHECKBOX',
            'default' => 'y',
            'value' => array(0 => 'n', 1 => 'y')
        ),
        'overquota_db_notify_client' => array(
            'datatype' => 'VARCHAR',
            'formtype' => 'CHECKBOX',
            'default' => 'y',
            'value' => array(0 => 'n', 1 => 'y')
        ),
        'overquota_notify_freq' => array(
            'datatype' => 'INTEGER',
            'formtype' => 'TEXT',
interface/web/admin/lib/lang/en_server_config.lng
@@ -197,4 +197,6 @@
$wb['backup_dir_is_mount_txt'] = 'Backup directory is a mount?';
$wb['backup_dir_mount_cmd_txt'] = 'Mount command, if backup directory not mounted';
$wb['backup_delete_txt'] = 'Delete backups on domain/website delete';
$wb["overquota_db_notify_admin_txt"] = 'Send DB quota warnings to admin';
$wb["overquota_db_notify_client_txt"] = 'Send DB quota warnings to client';
?>
interface/web/admin/templates/server_config_web_edit.htm
@@ -125,6 +125,18 @@
                    {tmpl_var name='overquota_notify_client'}
                </div>
            </div>
            <div class="ctrlHolder">
                <p class="label">{tmpl_var name='overquota_db_notify_admin_txt'}</p>
                <div class="multiField">
                    {tmpl_var name='overquota_db_notify_admin'}
                 </div>
            </div>
            <div class="ctrlHolder">
                <p class="label">{tmpl_var name='overquota_db_notify_client_txt'}</p>
                <div class="multiField">
                    {tmpl_var name='overquota_db_notify_client'}
                 </div>
            </div>
            <div class="ctrlHolder">
                <label for="overquota_notify_freq">{tmpl_var name='overquota_notify_freq_txt'}</label>
                <input name="overquota_notify_freq" id="overquota_notify_freq" value="{tmpl_var name='overquota_notify_freq'}" size="40" maxlength="255" type="text" class="textInput" />&nbsp;{tmpl_var name='overquota_notify_freq_note_txt'}
interface/web/client/form/client.tform.php
@@ -1093,6 +1093,20 @@
            'rows'  => '',
            'cols'  => ''
        ),
        'limit_database_quota' => array (
            'datatype' => 'INTEGER',
            'formtype' => 'TEXT',
            'validators' => array (  0 => array ( 'type' => 'ISINT',
                    'errmsg'=> 'limit_database_quota_error_notint'),
            ),
            'default' => '-1',
            'value'  => '',
            'separator' => '',
            'width'  => '10',
            'maxlength' => '10',
            'rows'  => '',
            'cols'  => ''
        ),
        'limit_cron' => array (
            'datatype'  => 'INTEGER',
            'formtype'  => 'TEXT',
interface/web/client/form/client_template.tform.php
@@ -557,6 +557,20 @@
            'rows'  => '',
            'cols'  => ''
        ),
        'limit_database_quota' => array (
            'datatype' => 'INTEGER',
            'formtype' => 'TEXT',
            'validators' => array (  0 => array ( 'type' => 'ISINT',
                    'errmsg'=> 'limit_database_quota_error_notint'),
            ),
            'default' => '-1',
            'value'  => '',
            'separator' => '',
            'width'  => '10',
            'maxlength' => '10',
            'rows'  => '',
            'cols'  => ''
        ),
        'limit_cron' => array (
            'datatype'  => 'INTEGER',
            'formtype'  => 'TEXT',
interface/web/client/lib/lang/en_client.lng
@@ -172,4 +172,6 @@
$wb['added_date_txt'] = 'Added date';
$wb['parent_client_id_txt'] = 'Client of reseller';
$wb['none_txt'] = 'none';
$wb['limit_database_quota_txt'] = 'Database quota';
$wb['limit_database_quota_error_notint'] = 'The database quota limit must be a number.';
?>
interface/web/client/lib/lang/en_client_template.lng
@@ -89,5 +89,7 @@
$wb['limit_aps_txt'] = 'Max. number of APS instances';
$wb['limit_aps_error_notint'] = 'The APS instances limit must be a number.';
$wb['limit_domainmodule_txt'] = 'Domainmodule Limit';
$wb['client_limits_txt'] = 'Client Limits'
?>
$wb['client_limits_txt'] = 'Client Limits';
$wb['limit_database_quota_txt'] = 'Database quota';
$wb['limit_database_quota_error_notint'] = 'The database quota limit must be a number.';
?>
interface/web/client/templates/client_edit_limits.htm
@@ -229,6 +229,10 @@
                    <label for="limit_database">{tmpl_var name='limit_database_txt'}</label>
                    <input name="limit_database" id="limit_database" value="{tmpl_var name='limit_database'}" size="10" maxlength="10" type="text" class="textInput formLengthLimit" />
                </div>
                <div class="ctrlHolder">
                    <label for="limit_database_quota">{tmpl_var name='limit_database_quota_txt'}</label>
                    <input name="limit_database_quota" id="limit_database_quota" value="{tmpl_var name='limit_database_quota'}" size="10" maxlength="10" type="text" class="textInput formLengthLimit" />&nbsp;MB
                </div>
            </div>
            <div class="subsectiontoggle"><span></span>{tmpl_var name='cron_job_limits_txt'}<em></em></div>
            <div style="display:none;">
interface/web/client/templates/client_template_edit_limits.htm
@@ -171,6 +171,10 @@
                    <label for="limit_database">{tmpl_var name='limit_database_txt'}</label>
                    <input name="limit_database" id="limit_database" value="{tmpl_var name='limit_database'}" size="10" maxlength="10" type="text" class="textInput formLengthLimit" />
                </div>
                <div class="ctrlHolder">
                    <label for="limit_database_quota">{tmpl_var name='limit_database_quota_txt'}</label>
                    <input name="limit_database_quota" id="limit_database_quota" value="{tmpl_var name='limit_database_quota'}" size="10" maxlength="10" type="text" class="textInput formLengthLimit" />&nbsp;MB
                </div>
            </div>
            <div class="subsectiontoggle"><span></span>{tmpl_var name='cron_job_limits_txt'}<em></em></div>
            <div style="display:none;">
@@ -247,4 +251,4 @@
        </div>
    </div>
</div>
</div>
interface/web/sites/database_edit.php
@@ -166,7 +166,7 @@
        if($_SESSION["s"]["user"]["typ"] != 'admin') {
            // Get the limits of the client
            $client_group_id = $_SESSION["s"]["user"]["default_group"];
            $client = $app->db->queryOneRecord("SELECT db_servers, limit_database FROM sys_group, client WHERE sys_group.client_id = client.client_id and sys_group.groupid = $client_group_id");
            $client = $app->db->queryOneRecord("SELECT db_servers, limit_database, limit_database_quota FROM sys_group, client WHERE sys_group.client_id = client.client_id AND sys_group.groupid = $client_group_id");
            // When the record is updated
            if($this->id > 0) {
@@ -191,6 +191,20 @@
                    }
                }
                // Check client quota
                 if ($client['limit_database_quota'] >= 0) {
                    $tmp = $app->db->queryOneRecord("SELECT sum(database_quota) as db_quota FROM web_database WHERE sys_groupid = $client_group_id");
                    $db_quota = $tmp['db_quota'];
                    $new_db_quota = $app->functions->intval($this->dataRecord["database_quota"]);
                    if(($db_quota + $new_db_quota > $client['limit_database_quota']) || ($new_db_quota < 0 && $client['limit_database_quota'] >= 0)) {
                        $max_free_quota = floor($client['limit_database_quota'] - $db_quota);
                        if($max_free_quota < 0) $max_free_quota = 0;
                        $app->tform->errorMessage .= $app->tform->lng("limit_database_quota_free_txt").": ".$max_free_quota." MB<br>";
                        $this->dataRecord['database_quota'] = $max_free_quota;
                    }
                    unset($tmp);
                }
            }
        } else {
            // check if client of database parent domain is client of db user!
interface/web/sites/form/database.tform.php
@@ -79,7 +79,7 @@
            'formtype' => 'SELECT',
            'default' => '',
            'datasource' => array (  'type' => 'SQL',
                'querystring' => "SELECT web_domain.domain_id, CONCAT(web_domain.domain, ' :: ', server.server_name) AS parent_domain FROM web_domain, server WHERE web_domain.type = 'vhost' AND web_domain.server_id = server.server_id AND {AUTHSQL::web_domain} ORDER BY web_domain.domain",
                'querystring' => "SELECT web_domain.domain_id, CONCAT(web_domain.domain, ' :: ', server.server_name) AS parent_domain FROM web_domain, server WHERE web_domain.type = 'vhost' AND web_domain.server_id = server.server_id AND {AUTHSQL} ORDER BY web_domain.domain",
                'keyfield'=> 'domain_id',
                'valuefield'=> 'parent_domain'
            ),
@@ -117,6 +117,20 @@
            'width'  => '30',
            'maxlength' => '25'
        ),
        'database_quota' => array (
            'datatype' => 'INTEGER',
            'formtype' => 'TEXT',
            'validators' => array (  0 => array ( 'type' => 'ISINT',
                'errmsg'=> 'limit_database_quota_error_notint'),
            ),
            'default' => '-1',
            'value'  => '',
            'separator' => '',
            'width'  => '10',
            'maxlength' => '10',
            'rows'  => '',
            'cols'  => ''
        ),
        'database_user_id' => array (
            'datatype' => 'INTEGER',
            'formtype' => 'SELECT',
interface/web/sites/lib/lang/en_database.lng
@@ -43,4 +43,7 @@
$wb['globalsearch_noresults_limit_txt'] = "0 results";
$wb['globalsearch_searchfield_watermark_txt'] = "Search";
$wb['globalsearch_suggestions_text_txt'] = "Suggestions";
$wb['limit_database_quota_txt'] = 'Database quota';
$wb['limit_database_quota_error_notint'] = 'The database quota limit must be a number.';
$wb['limit_database_quota_free_txt']='Max. available DB quota ';
?>
interface/web/sites/templates/database_edit.htm
@@ -62,6 +62,10 @@
                        <input name="database_name" id="database_name" value="{tmpl_var name='database_name'}" size="30" maxlength="255" type="text" class="textInput formLengthHalf" />
                </tmpl_if>
            </div>
            <div class="ctrlHolder">
                <label for="database_quota">{tmpl_var name='limit_database_quota_txt'}</label>
                <input name="database_quota" id="database_quota" value="{tmpl_var name='limit_database_quota'}" size="10" maxlength="10" type="text" class="textInput formLengthLimit" />&nbsp;MB
            </div>
            <div class="ctrlHolder">
                <label for="database_user_id">{tmpl_var name='database_user_txt'}</label>
                <select name="database_user_id" id="database_user_id" class="selectInput">
@@ -149,4 +153,4 @@
        searchFieldWatermark: '',
        resultBoxPosition: 'e'
    });
</script>
</script>
server/conf/mail/db_quota_notification_de.txt
New file
@@ -0,0 +1,13 @@
ME-Version: 1.0
Content-type: text/plain; charset=utf-8
Content-Transfer-Encoding: 8bit
From: {admin_mail}
Reply-To: {admin_mail}
Subject: Datenbank-Speicherhinweis
Ihre Datenbank {database_name} hat den verfuegbaren Speicherplatz (nahezu) ausgeschoepft.
Datenbank:                        {databbase_name}
Belegter Speicherplatz:            {used}
Verfuegbarer Speicherplatz:        {quota}
Belegter Speicherplatz in %:    {ratio}
server/conf/mail/db_quota_notification_en.txt
New file
@@ -0,0 +1,13 @@
ME-Version: 1.0
Content-type: text/plain; charset=utf-8
Content-Transfer-Encoding: 8bit
From: {admin_mail}
Reply-To: {admin_mail}
Subject: Database quota notification
The database {database_name} is near or over quota.
Database:        {databbase_name}
Used space:        {used}
Quota:            {quota}
Usage ratio:    {ratio}
server/conf/mail/db_quota_ok_notification_de.txt
New file
@@ -0,0 +1,13 @@
ME-Version: 1.0
Content-type: text/plain; charset=utf-8
Content-Transfer-Encoding: 8bit
From: {admin_mail}
Reply-To: {admin_mail}
Subject: Datenbank-Speicherhinweis
Der belegte Speicherplatz Ihrer Datenbank {database_name} ist wieder ok.
Datenbank:                        {databbase_name}
Belegter Speicherplatz:            {used}
Verfuegbarer Speicherplatz:        {quota}
Belegter Speicherplatz in %:    {ratio}
server/conf/mail/db_quota_ok_notification_en.txt
New file
@@ -0,0 +1,13 @@
MIME-Version: 1.0
Content-type: text/plain; charset=utf-8
Content-Transfer-Encoding: 8bit
From: {admin_mail}
Reply-To: {admin_mail}
Subject: Database quota ok
The database {database_name} is no longer near or over quota.
Database:        {database_name}
Used space:        {used}
Quota:            {quota}
Usage ratio:    {ratio}
server/lib/classes/cron.d/100-monitor_database_size.inc.php
@@ -77,38 +77,39 @@
        /** The state of the database-usage */
        $state = 'ok';
        /** Fetch the data of all active databases into an array */
        $records = $app->db->queryAllRecords("SELECT database_name, sys_groupid FROM web_database WHERE server_id = $server_id AND active='y' GROUP BY sys_groupid, database_name ASC");
        if(is_array($records) && !empty($records)) {
        /** Fetch the data of all databases into an array */
        $databases = $app->db->queryAllRecords("SELECT database_name, sys_groupid FROM web_database WHERE server_id = $server_id GROUP BY sys_groupid, database_name ASC");
        if(is_array($databases) && !empty($databases)) {
            $data = array();
            for ($i = 0; $i < sizeof($records); $i++) {
                $data[$i]['name'] = $records[$i]['database_name'];
                $data[$i]['size'] = $app->db->getDatabaseSize($data[$i]['name']);
                $data[$i]['client_id'] = $records[$i]['sys_groupid'];
            for ($i = 0; $i < sizeof($databases); $i++) {
                $data[$i]['database_name']= $databases[$i]['database_name'];
                $data[$i]['size'] = $app->db->getDatabaseSize($databases[$i]['database_name']);
                $data[$i]['sys_groupid'] = $databases[$i]['sys_groupid'];
            }
            $res = array();
            $res['server_id'] = $server_id;
            $res['type'] = $type;
            $res['data'] = $data;
            $res['state'] = $state;
            //* Insert the data into the database
            $sql = 'REPLACE INTO monitor_data (server_id, type, created, data, state) ' .
                'VALUES (' .
                $res['server_id'] . ', ' .
                "'" . $app->dbmaster->quote($res['type']) . "', " .
                'UNIX_TIMESTAMP(), ' .
                "'" . $app->dbmaster->quote(serialize($res['data'])) . "', " .
                "'" . $res['state'] . "'" .
                ')';
            $app->dbmaster->query($sql);
            //* The new data is written, now we can delete the old one
            $this->_tools->delOldRecords($res['type'], $res['server_id']);
        }
        $res = array();
        $res['server_id'] = $server_id;
        $res['type'] = $type;
        $res['data'] = $data;
        $res['state'] = $state;
        /*
         * Insert the data into the database
         */
        $sql = 'REPLACE INTO monitor_data (server_id, type, created, data, state) ' .
            'VALUES (' .
            $res['server_id'] . ', ' .
            "'" . $app->dbmaster->quote($res['type']) . "', " .
            'UNIX_TIMESTAMP(), ' .
            "'" . $app->dbmaster->quote(serialize($res['data'])) . "', " .
            "'" . $res['state'] . "'" .
            ')';
        $app->dbmaster->query($sql);
        /* The new data is written, now we can delete the old one */
        $this->_tools->delOldRecords($res['type'], $res['server_id']);
        parent::onRunJob();
    }
server/lib/classes/cron.d/300-quota_notify.inc.php
@@ -463,7 +463,125 @@
            }
        }
        //######################################################################################################
        // send database quota warnings by email
        //######################################################################################################
        if ($app->dbmaster == $app->db) {
            $global_config = $app->getconf->get_global_config('mail');
            //* get monitor-data
            $tmp_rec = $app->db->queryAllRecords("SELECT data from monitor_data WHERE type = 'database_size' ORDER BY created DESC");
            if(is_array($tmp_rec)) {
                $monitor_data = array();
                foreach ($tmp_rec as $tmp_mon) {
                    $tmp_array = unserialize($app->db->unquote($tmp_mon['data']));
                    if(is_array($tmp_array))
                        foreach($tmp_array as $sys_groupid => $data)
                            $monitor_data[$data['sys_groupid']][] = $data;
                }
                //* remove duplicates from monitor-data
                foreach($monitor_data as $_monitor_data)
                    $monitor_data[$_monitor_data[0]['sys_groupid']]=array_map("unserialize", array_unique(array_map("serialize", $_monitor_data)));
            }
            //* get databases
            $database_records = $app->db->queryAllRecords("SELECT database_id,sys_groupid,database_name,database_quota,last_quota_notification,DATEDIFF(CURDATE(), last_quota_notification) as `notified_before` FROM web_database;");
            if(is_array($database_records) && !empty($database_records) && is_array($monitor_data) && !empty($monitor_data)) {
                //* check database-quota
                foreach($database_records as $rec) {
                    $database = $rec['database_name'];
                    $quota = $rec['database_quota'] * 1024 * 1024;
                    if (!is_numeric($quota)) break;
                    foreach ($monitor_data as $cid) {
                        foreach($cid_data as $monitor) {
                            if ($monitor['database_name'] == $database) {
                                //* get the client
                                $client = $app->db->queryOneRecord("SELECT client.username, client.email FROM web_database, sys_group, client WHERE web_database.sys_groupid = sys_group.groupid AND sys_group.client_id = client.client_id AND web_database.database_name='".$database."'");
                                //* check quota
                                if ($quota > 0) $used_ratio = $monitor['size'] / $quota;
                                else $used_ratio = 0;
                                //* send notifications only if 90% or more of the quota are used
                                if($used_ratio > 0.9) {
                                    //* reset notification date
                                    if($rec['last_quota_notification']) $app->dbmaster->datalogUpdate('web_database', "last_quota_notification = NULL", 'database_id', $rec['database_id']);
                                    $app->dbmaster->datalogUpdate('web_database', "last_quota_notification = CURDATE()", 'database_id', $rec['database_id']);
                                    // send notification - everything ok again
                                    if($rec['last_quota_notification'] && $web_config['overquota_notify_onok'] == 'y' && ($web_config['overquota_db_notify_admin'] == 'y' || $web_config['overquota_db_notify_client'] == 'y')) {
                                        $placeholders = array(
                                            '{database_name}' => $rec['database_name'],
                                            '{admin_mail}' => ($global_config['admin_mail'] != ''? $global_config['admin_mail'] : 'root'),
                                            '{used}' => $app->functions->formatBytes($monitor['size']),
                                            '{quota}' => $quota.' MB',
                                            '{ratio}' => number_format($used_ratio * 100, 2, '.', '').'%'
                                        );
                                        $recipients = array();
                                        //* send email to admin
                                        if($global_config['admin_mail'] != '' && $web_config['overquota_db_notify_admin'] == 'y')
                                            $recipients[] = $global_config['admin_mail'];
                                        //* Send email to client
                                        if($web_config['overquota_db_notify_client'] == 'y' && $client['email'] != '')
                                            $recipients[] = $client['email'];
                                        send_notification_email('db_quota_ok_notification', $placeholders, $recipients);
                                    }
                                }
                                //* could a notification be sent?
                                $send_notification = false;
                                if(!$rec['last_quota_notification']) $send_notification = true; //* not yet notified
                                elseif($web_config['overquota_notify_freq'] > 0 && $rec['notified_before'] >= $web_config['overquota_notify_freq']) $send_notification = true;
                                //* Send quota notifications
                                if(($web_config['overquota_db_notify_admin'] == 'y' || $web_config['overquota_db_notify_client'] == 'y') && $send_notification == true) {
                                    $app->dbmaster->datalogUpdate('web_database', "last_quota_notification = CURDATE()", 'database_id', $rec['database_id']);
                                    $placeholders = array(
                                        '{database_name}' => $rec['database_name'],
                                        '{admin_mail}' => ($global_config['admin_mail'] != ''? $global_config['admin_mail'] : 'root'),
                                        '{used}' => $app->functions->formatBytes($monitor['size']),
                                        '{quota}' => $quota.' MB',
                                        '{ratio}' => number_format($used_ratio * 100, 2, '.', '').'%'
                                    );
                                    $recipients = array();
                                    //* send email to admin
                                    if($global_config['admin_mail'] != '' && $web_config['overquota_db_notify_admin'] == 'y')
                                        $recipients[] = $global_config['admin_mail'];
                                    //* Send email to client
                                    if($web_config['overquota_db_notify_client'] == 'y' && $client['email'] != '')
                                        $recipients[] = $client['email'];
                                    send_notification_email('db_quota_notification', $placeholders, $recipients);
                                }
                            }
                        }
                    }
                }
            }
        }
        parent::onRunJob();
    }