attr-sql: Use a serializable transaction when inserting identities
authorTobias Brunner <tobias@strongswan.org>
Thu, 10 Oct 2013 09:02:16 +0000 (11:02 +0200)
committerTobias Brunner <tobias@strongswan.org>
Fri, 11 Oct 2013 13:29:10 +0000 (15:29 +0200)
src/libhydra/plugins/attr_sql/sql_attribute.c

index 20c606e..0a06c41 100644 (file)
@@ -50,9 +50,8 @@ static u_int get_identity(private_sql_attribute_t *this, identification_t *id)
 {
        enumerator_t *e;
        u_int row;
-       int try = 0;
 
-retry:
+       this->db->transaction(this->db, TRUE);
        /* look for peer identity in the identities table */
        e = this->db->query(this->db,
                                                "SELECT id FROM identities WHERE type = ? AND data = ?",
@@ -61,26 +60,20 @@ retry:
        if (e && e->enumerate(e, &row))
        {
                e->destroy(e);
+               this->db->commit(this->db);
                return row;
        }
        DESTROY_IF(e);
-       if (try > 0)
-       {
-               return 0;
-       }
        /* not found, insert new one */
        if (this->db->execute(this->db, &row,
                                  "INSERT INTO identities (type, data) VALUES (?, ?)",
                                  DB_INT, id->get_type(id), DB_BLOB, id->get_encoding(id)) == 1)
        {
+               this->db->commit(this->db);
                return row;
        }
-       /* the INSERT could fail due to the UNIQUE constraint, if the identity was
-        * added concurrently by another thread or the pool utility,
-        * therefore try finding it again. a nicer fix would be to use locking
-        * on the database, but our API currently not supports that */
-       try++;
-       goto retry;
+       this->db->rollback(this->db);
+       return 0;
 }
 
 /**