using System;
using System.Collections.Generic;
using System.Configuration;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Timers;
using Aitex.Core.RT.DBCore;
using Aitex.Core.RT.Log;
using Aitex.Core.RT.SCCore;
using Aitex.Core.Util;
using log4net.Repository.Hierarchy;
using Npgsql;
namespace MECF.Framework.Common.DBCore
{
///
/// 单例模式,周期性地执行删除数据表的操作
///
public sealed class DatabaseCleaner
{
NpgsqlConnection conn;
List tableNames = new List();
bool _isDataCleanEnabled = false;
int _daysOfRetainData = 90;
DateTime _dateDataKeepTo;
private PeriodicJob _cleanThread;
private string _dbName;
public DatabaseCleaner()
{
}
public void Initialize(string dbName)
{
_dbName = dbName;
_isDataCleanEnabled = !SC.ContainsItem("System.EnableDataClean") || SC.GetValue("System.EnableDataClean");
if (_isDataCleanEnabled)
{
GetDaysOfRetainData();
}
_cleanThread = new PeriodicJob(24 * 60 * 60 *1000, MonitorCleanData, "Database cleaner", true);
}
public void Terminate()
{
_cleanThread.Stop();
}
public bool MonitorCleanData( )
{
try
{
string sql = null;
string log = null;
int count = 0;
NpgsqlCommand command = null;
string[,] timeStamp = { { "carrier_data", "load_time" },
{ "event_data", "occur_time" },
{ "process_data", "process_begin_time" },
{ "wafer_data", "create_time" },
{ "wafer_move_history", "arrive_time" } };
GetDaysOfRetainData();
tableNames.Clear();
GetTableNames();
if (tableNames.Count == 0) return true; // 数据库中没有需要删除的数据表
// 实例化一个NpsqlConnection的对象
conn = new NpgsqlConnection(PostgresqlHelper.ConnectionString);
conn.Open();
conn.ChangeDatabase(_dbName);
DeviceTimer timer = new DeviceTimer();
for (int i = 0; i < timeStamp.GetLength(0); i++)
{
// 判断数据库中是否存在指定的表和字段
sql = string.Format("select count(*) from information_schema.columns where table_schema='public' and table_name ='{0}' and column_name='{1}'", timeStamp[i, 0], timeStamp[i, 1]);
command = new NpgsqlCommand(sql, conn);
count = Convert.ToInt32(command.ExecuteScalar());
if (count == 1) // 存在则返回1,不存在则返回0
{
// 删除指定日期前的所有记录
timer.Start(300 * 1000);
sql = string.Format("delete from \"{0}\" where \"{1}\" <= '{2}'", timeStamp[i, 0], timeStamp[i, 1], _dateDataKeepTo.ToString("yyyy/MM/dd HH:mm:ss.fff"));
command = new NpgsqlCommand(sql, conn);
command.ExecuteNonQuery();
double elapsedTime = timer.GetElapseTime() / 1000;
log = string.Format("当前日期为{0},删除目录表{1}里{2}天前的记录,用时{3}秒,执行的sql:{4}", System.DateTime.Now.ToString("D"), timeStamp[i, 0], _daysOfRetainData, elapsedTime, sql);
LOG.Info(log);
System.Threading.Thread.Sleep(50);
}
}
foreach (string tableName in tableNames)
{
timer.Start(300 * 1000);
sql = string.Format("drop table \"{0}\"", tableName);
command = new NpgsqlCommand(sql, conn);
command.ExecuteNonQuery();
double elapsedTime = timer.GetElapseTime() / 1000;
log = string.Format("当前日期为{0},删除{1}天前的数据表{2},用时{3}秒,执行的sql:{4}", System.DateTime.Now.ToString("D"), _daysOfRetainData, tableName, elapsedTime, sql);
LOG.Info(log);
System.Threading.Thread.Sleep(50);
}
conn.Close();
conn.ClearPool();
conn = null;
}
catch (Exception ex)
{
LOG.Write(ex);
if (conn != null)
{
conn.Close();
conn.ClearPool();
}
conn = null;
}
return true;
}
///
/// 获取数据表的总数
///
///
public void GetTableNames()
{
try
{
// 实例化一个NpsqlConnection的对象
conn = new NpgsqlConnection(PostgresqlHelper.ConnectionString);
_dateDataKeepTo = System.DateTime.Now.AddDays(-_daysOfRetainData); // 获取90天前的年月日
string sql = "select tablename from pg_tables where schemaname='public' and tablename like '20%' order by tablename asc";
conn.Open();
conn.ChangeDatabase(_dbName);
NpgsqlCommand command = new NpgsqlCommand(sql, conn);
NpgsqlDataReader dataReader = command.ExecuteReader(); // 获得一个结果集的检索结果
while (dataReader.Read())
{
for (int i = 0; i < dataReader.FieldCount; i++)
{
string tableName = dataReader[i].ToString();
tableName = tableName.Substring(0, 8);
if (DateTime.ParseExact(tableName, "yyyyMMdd", System.Globalization.CultureInfo.InvariantCulture) <= _dateDataKeepTo) // 判断是否早于指定的日期
{
tableNames.Add(dataReader[i].ToString());
}
}
}
dataReader.Close();
dataReader.Dispose();
conn.Close();
conn.ClearPool();
conn = null;
}
catch (Exception ex)
{
LOG.Write(ex);
if (conn != null)
{
conn.Close();
conn.ClearPool();
}
conn = null;
}
}
///
/// 获取需要保留数据的天数
///
public void GetDaysOfRetainData()
{
int days = 90;
if (SC.ContainsItem("System.DataKeepDays"))
days = SC.GetValue("System.DataKeepDays");
if (days < 10)
{
LOG.Warning($"database keep days should be at least 10 days.current setting {days}");
days = 10;
}
if (days > 365)
{
LOG.Warning($"database keep days should be less than 365 days.current setting {days}");
days = 365;
}
_daysOfRetainData = days;
}
}
}