Fix line feeds again, VS is also broken.
[shibboleth/cpp-sp.git] / odbc-store / odbc-store.cpp
index 48bbe8e..1ad49a2 100644 (file)
@@ -332,24 +332,40 @@ ODBCStorageService::ODBCStorageService(const DOMElement* e) : m_log(Category::ge
     e = XMLHelper::getNextSiblingElement(e, RetryOnError);
     while (e) {
         if (e->hasChildNodes()) {
-            m_retries.push_back(XMLString::parseInt(e->getTextContent()));
-            m_log.info("will retry operations when native ODBC error (%ld) is returned", m_retries.back());
+            try {
+                int code = XMLString::parseInt(e->getTextContent());
+                m_retries.push_back(code);
+                m_log.info("will retry operations when native ODBC error (%d) is returned", code);
+            }
+            catch (XMLException&) {
+                m_log.error("skipping non-numeric ODBC retry code");
+            }
         }
         e = XMLHelper::getNextSiblingElement(e, RetryOnError);
     }
 
-    // Initialize the cleanup thread
-    shutdown_wait.reset(CondWait::create());
-    cleanup_thread = Thread::create(&cleanup_fn, (void*)this);
+    if (m_cleanupInterval > 0) {
+        // Initialize the cleanup thread
+        shutdown_wait.reset(CondWait::create());
+        cleanup_thread = Thread::create(&cleanup_fn, (void*)this);
+    }
+    else {
+        m_log.info("no cleanup interval configured, no cleanup thread will be started");
+    }
 }
 
 ODBCStorageService::~ODBCStorageService()
 {
     shutdown = true;
-    shutdown_wait->signal();
-    cleanup_thread->join(nullptr);
-    if (m_henv != SQL_NULL_HANDLE)
+    if (shutdown_wait.get()) {
+        shutdown_wait->signal();
+    }
+    if (cleanup_thread) {
+        cleanup_thread->join(nullptr);
+    }
+    if (m_henv != SQL_NULL_HANDLE) {
         SQLFreeHandle(SQL_HANDLE_ENV, m_henv);
+    }
 }
 
 pair<bool,bool> ODBCStorageService::log_error(SQLHANDLE handle, SQLSMALLINT htype, const char* checkfor)
@@ -507,8 +523,16 @@ bool ODBCStorageService::createRow(const char* table, const char* context, const
         }
         m_log.error("insert record failed (t=%s, c=%s, k=%s)", table, context, key);
         logres = log_error(stmt, SQL_HANDLE_STMT, "23000");
-        if (logres.second)
-            return false;   // supposedly integrity violation?
+        if (logres.second) {
+            // Supposedly integrity violation.
+            // Try and delete any expired record still hanging around until the final attempt.
+            if (attempts > 0) {
+                reap(table, context);
+                logres.first = true;    // force it to treat as a retryable error
+                continue;
+            }
+            return false;
+        }
     } while (attempts && logres.first);
 
     throw IOException("ODBC StorageService failed to insert record.");