]> git.ipfire.org Git - oddments/ddns.git/blobdiff - src/ddns/database.py
database: Remove some unused code to close the database
[oddments/ddns.git] / src / ddns / database.py
index 930118775e5557f07ab5681866161e06cad6ca60..2de050b1b7f590e3c570365b9f0702054a61d0d6 100644 (file)
@@ -1,4 +1,4 @@
-#!/usr/bin/python
+#!/usr/bin/python3
 ###############################################################################
 #                                                                             #
 # ddns - A dynamic DNS client for IPFire                                      #
@@ -20,7 +20,7 @@
 ###############################################################################
 
 import datetime
-import os.path
+import os
 import sqlite3
 
 # Initialize the logger.
@@ -31,12 +31,11 @@ logger.propagate = 1
 class DDNSDatabase(object):
        def __init__(self, core, path):
                self.core = core
+               self.path = path
 
-               # Open the database file
-               self._db = self._open_database(path)
-
-       def __del__(self):
-               self._close_database()
+               # We won't open the connection to the database directly
+               # so that we do not do it unnecessarily.
+               self._db = None
 
        def _open_database(self, path):
                logger.debug("Opening database %s" % path)
@@ -46,7 +45,7 @@ class DDNSDatabase(object):
                conn = sqlite3.connect(path, detect_types=sqlite3.PARSE_DECLTYPES|sqlite3.PARSE_COLNAMES)
                conn.isolation_level = None
 
-               if not exists:
+               if not exists and self.is_writable():
                        logger.debug("Initialising database layout")
                        c = conn.cursor()
                        c.executescript("""
@@ -61,17 +60,27 @@ class DDNSDatabase(object):
                                        k TEXT NOT NULL,
                                        v TEXT NOT NULL
                                );
+
+                               CREATE INDEX idx_updates_hostname ON updates(hostname);
                        """)
                        c.execute("INSERT INTO settings(k, v) VALUES(?, ?)", ("version", "1"))
 
                return conn
 
-       def _close_database(self):
-               if self._db:
-                       self._db_close()
-                       self._db = None
+       def is_writable(self):
+               # Check if the database file exists and is writable.
+               ret = os.access(self.path, os.W_OK)
+               if ret:
+                       return True
+
+               # If not, we check if we are able to write to the directory.
+               # In that case the database file will be created in _open_database().
+               return os.access(os.path.dirname(self.path), os.W_OK)
 
        def _execute(self, query, *parameters):
+               if self._db is None:
+                       self._db = self._open_database(self.path)
+
                c = self._db.cursor()
                try:
                        c.execute(query, parameters)
@@ -79,6 +88,10 @@ class DDNSDatabase(object):
                        c.close()
 
        def add_update(self, hostname, status, message=None):
+               if not self.is_writable():
+                       logger.warning("Could not log any updates because the database is not writable")
+                       return
+
                self._execute("INSERT INTO updates(hostname, status, message, timestamp) \
                        VALUES(?, ?, ?, ?)", hostname, status, message, datetime.datetime.utcnow())
 
@@ -97,12 +110,58 @@ class DDNSDatabase(object):
 
                return self.add_update(hostname, "failure", message=message)
 
-       def last_update(self, hostname, status="success"):
+       def last_update(self, hostname, status=None):
+               """
+                       Returns the timestamp of the last update (with the given status code).
+               """
+               if self._db is None:
+                       self._db = self._open_database(self.path)
+
+               c = self._db.cursor()
+
+               try:
+                       if status:
+                               c.execute("SELECT timestamp FROM updates WHERE hostname = ? AND status = ? \
+                                       ORDER BY timestamp DESC LIMIT 1", (hostname, status))
+                       else:
+                               c.execute("SELECT timestamp FROM updates WHERE hostname = ? \
+                                       ORDER BY timestamp DESC LIMIT 1", (hostname,))
+
+                       for row in c:
+                               return row[0]
+               finally:
+                       c.close()
+
+       def last_update_status(self, hostname):
+               """
+                       Returns the update status of the last update.
+               """
+               if self._db is None:
+                       self._db = self._open_database(self.path)
+
+               c = self._db.cursor()
+
+               try:
+                       c.execute("SELECT status FROM updates WHERE hostname = ? \
+                               ORDER BY timestamp DESC LIMIT 1", (hostname,))
+
+                       for row in c:
+                               return row[0]
+               finally:
+                       c.close()
+
+       def last_update_failure_message(self, hostname):
+               """
+                       Returns the reason string for the last failed update (if any).
+               """
+               if self._db is None:
+                       self._db = self._open_database(self.path)
+
                c = self._db.cursor()
 
                try:
-                       c.execute("SELECT timestamp FROM updates WHERE hostname = ? AND status = ? \
-                               ORDER BY timestamp DESC LIMIT 1", (hostname, status))
+                       c.execute("SELECT message FROM updates WHERE hostname = ? AND status = ? \
+                               ORDER BY timestamp DESC LIMIT 1", (hostname, "failure"))
 
                        for row in c:
                                return row[0]