123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133 |
- from Config import config
- from Db import Db
- import time
- class ChartDb(Db):
- def __init__(self):
- self.version = 2
- super(ChartDb, self).__init__(self.getSchema(), "%s/chart.db" % config.data_dir)
- self.foreign_keys = True
- self.checkTables()
- self.sites = self.loadSites()
- self.types = self.loadTypes()
- def getSchema(self):
- schema = {}
- schema["db_name"] = "Chart"
- schema["tables"] = {}
- schema["tables"]["data"] = {
- "cols": [
- ["data_id", "INTEGER PRIMARY KEY ASC AUTOINCREMENT NOT NULL UNIQUE"],
- ["type_id", "INTEGER NOT NULL"],
- ["site_id", "INTEGER"],
- ["value", "INTEGER"],
- ["date_added", "DATETIME DEFAULT (CURRENT_TIMESTAMP)"]
- ],
- "indexes": [
- "CREATE INDEX site_id ON data (site_id)",
- "CREATE INDEX date_added ON data (date_added)"
- ],
- "schema_changed": 2
- }
- schema["tables"]["type"] = {
- "cols": [
- ["type_id", "INTEGER PRIMARY KEY NOT NULL UNIQUE"],
- ["name", "TEXT"]
- ],
- "schema_changed": 1
- }
- schema["tables"]["site"] = {
- "cols": [
- ["site_id", "INTEGER PRIMARY KEY NOT NULL UNIQUE"],
- ["address", "TEXT"]
- ],
- "schema_changed": 1
- }
- return schema
- def getTypeId(self, name):
- if name not in self.types:
- self.execute("INSERT INTO type ?", {"name": name})
- self.types[name] = self.cur.cursor.lastrowid
- return self.types[name]
- def getSiteId(self, address):
- if address not in self.sites:
- self.execute("INSERT INTO site ?", {"address": address})
- self.sites[address] = self.cur.cursor.lastrowid
- return self.sites[address]
- def loadSites(self):
- sites = {}
- for row in self.execute("SELECT * FROM site"):
- sites[row["address"]] = row["site_id"]
- return sites
- def loadTypes(self):
- types = {}
- for row in self.execute("SELECT * FROM type"):
- types[row["name"]] = row["type_id"]
- return types
- def deleteSite(self, address):
- if address in self.sites:
- site_id = self.sites[address]
- del self.sites[address]
- self.execute("DELETE FROM site WHERE ?", {"site_id": site_id})
- self.execute("DELETE FROM data WHERE ?", {"site_id": site_id})
- def archive(self):
- week_back = 1
- while 1:
- s = time.time()
- date_added_from = time.time() - 60 * 60 * 24 * 7 * (week_back + 1)
- date_added_to = date_added_from + 60 * 60 * 24 * 7
- res = self.execute("""
- SELECT
- MAX(date_added) AS date_added,
- SUM(value) AS value,
- GROUP_CONCAT(data_id) AS data_ids,
- type_id,
- site_id,
- COUNT(*) AS num
- FROM data
- WHERE
- site_id IS NULL AND
- date_added > :date_added_from AND
- date_added < :date_added_to
- GROUP BY strftime('%Y-%m-%d %H', date_added, 'unixepoch', 'localtime'), type_id
- """, {"date_added_from": date_added_from, "date_added_to": date_added_to})
- num_archived = 0
- cur = self.getCursor()
- for row in res:
- if row["num"] == 1:
- continue
- cur.execute("INSERT INTO data ?", {
- "type_id": row["type_id"],
- "site_id": row["site_id"],
- "value": row["value"],
- "date_added": row["date_added"]
- })
- cur.execute("DELETE FROM data WHERE data_id IN (%s)" % row["data_ids"])
- num_archived += row["num"]
- self.log.debug("Archived %s data from %s weeks ago in %.3fs" % (num_archived, week_back, time.time() - s))
- week_back += 1
- time.sleep(0.1)
- if num_archived == 0:
- break
- # Only keep 6 month of global stats
- self.execute(
- "DELETE FROM data WHERE site_id IS NULL AND date_added < :date_added_limit",
- {"date_added_limit": time.time() - 60 * 60 * 24 * 30 * 6 }
- )
- # Only keep 1 month of site stats
- self.execute(
- "DELETE FROM data WHERE site_id IS NOT NULL AND date_added < :date_added_limit",
- {"date_added_limit": time.time() - 60 * 60 * 24 * 30 }
- )
- if week_back > 1:
- self.execute("VACUUM")
|