ncurses 5.9 - patch 20130216
[ncurses.git] / ncurses / tinfo / hashed_db.c
index bf7a968ee96dd93c63e9577534ffe0f84bdfa527..1b3eb97dd92e3f6675fa1aa1f2fc1d9cc9cadf14 100644 (file)
@@ -1,5 +1,5 @@
 /****************************************************************************
- * Copyright (c) 2006,2008 Free Software Foundation, Inc.                   *
+ * Copyright (c) 2006-2011,2013 Free Software Foundation, Inc.              *
  *                                                                          *
  * Permission is hereby granted, free of charge, to any person obtaining a  *
  * copy of this software and associated documentation files (the            *
 
 #if USE_HASHED_DB
 
-MODULE_ID("$Id: hashed_db.c,v 1.14 2008/12/13 20:59:02 tom Exp $")
+MODULE_ID("$Id: hashed_db.c,v 1.16 2013/02/16 21:50:03 tom Exp $")
 
 #if HASHED_DB_API >= 2
 static DBC *cursor;
 #endif
 
+typedef struct _myconn {
+    struct _myconn *next;
+    DB *db;
+    char *path;
+    bool modify;
+} MYCONN;
+
+static MYCONN *connections;
+
+static void
+cleanup(void)
+{
+    while (connections != 0) {
+       _nc_db_close(connections->db);
+    }
+}
+
+static DB *
+find_connection(const char *path, bool modify)
+{
+    DB *result = 0;
+    MYCONN *p;
+
+    for (p = connections; p != 0; p = p->next) {
+       if (!strcmp(p->path, path) && p->modify == modify) {
+           result = p->db;
+           break;
+       }
+    }
+
+    return result;
+}
+
+static void
+drop_connection(DB * db)
+{
+    MYCONN *p, *q;
+
+    for (p = connections, q = 0; p != 0; q = p, p = p->next) {
+       if (p->db == db) {
+           if (q != 0)
+               q->next = p->next;
+           else
+               connections = p->next;
+           free(p->path);
+           free(p);
+           break;
+       }
+    }
+}
+
+static void
+make_connection(DB * db, const char *path, bool modify)
+{
+    MYCONN *p = typeCalloc(MYCONN, 1);
+
+    if (p != 0) {
+       p->db = db;
+       p->path = strdup(path);
+       p->modify = modify;
+       if (p->path != 0) {
+           p->next = connections;
+           connections = p;
+       } else {
+           free(p);
+       }
+    }
+}
+
 /*
  * Open the database.
  */
@@ -51,50 +120,57 @@ _nc_db_open(const char *path, bool modify)
     DB *result = 0;
     int code;
 
+    if (connections == 0)
+       atexit(cleanup);
+
+    if ((result = find_connection(path, modify)) == 0) {
+
 #if HASHED_DB_API >= 4
-    db_create(&result, NULL, 0);
-    if ((code = result->open(result,
-                            NULL,
-                            path,
-                            NULL,
-                            DB_HASH,
-                            modify ? DB_CREATE : DB_RDONLY,
-                            0644)) != 0) {
-       result = 0;
-    }
+       db_create(&result, NULL, 0);
+       if ((code = result->open(result,
+                                NULL,
+                                path,
+                                NULL,
+                                DB_HASH,
+                                modify ? DB_CREATE : DB_RDONLY,
+                                0644)) != 0) {
+           result = 0;
+       }
 #elif HASHED_DB_API >= 3
-    db_create(&result, NULL, 0);
-    if ((code = result->open(result,
-                            path,
-                            NULL,
-                            DB_HASH,
-                            modify ? DB_CREATE : DB_RDONLY,
-                            0644)) != 0) {
-       result = 0;
-    }
+       db_create(&result, NULL, 0);
+       if ((code = result->open(result,
+                                path,
+                                NULL,
+                                DB_HASH,
+                                modify ? DB_CREATE : DB_RDONLY,
+                                0644)) != 0) {
+           result = 0;
+       }
 #elif HASHED_DB_API >= 2
-    if ((code = db_open(path,
-                       DB_HASH,
-                       modify ? DB_CREATE : DB_RDONLY,
-                       0644,
-                       (DB_ENV *) 0,
-                       (DB_INFO *) 0,
-                       &result)) != 0) {
-       result = 0;
-    }
+       if ((code = db_open(path,
+                           DB_HASH,
+                           modify ? DB_CREATE : DB_RDONLY,
+                           0644,
+                           (DB_ENV *) 0,
+                           (DB_INFO *) 0,
+                           &result)) != 0) {
+           result = 0;
+       }
 #else
-    if ((result = dbopen(path,
-                        modify ? (O_CREAT | O_RDWR) : O_RDONLY,
-                        0644,
-                        DB_HASH,
-                        NULL)) == 0) {
-       code = errno;
-    }
+       if ((result = dbopen(path,
+                            modify ? (O_CREAT | O_RDWR) : O_RDONLY,
+                            0644,
+                            DB_HASH,
+                            NULL)) == 0) {
+           code = errno;
+       }
 #endif
-    if (result != 0) {
-       T(("opened %s", path));
-    } else {
-       T(("cannot open %s: %s", path, strerror(code)));
+       if (result != 0) {
+           make_connection(result, path, modify);
+           T(("opened %s", path));
+       } else {
+           T(("cannot open %s: %s", path, strerror(code)));
+       }
     }
     return result;
 }
@@ -107,6 +183,7 @@ _nc_db_close(DB * db)
 {
     int result;
 
+    drop_connection(db);
 #if HASHED_DB_API >= 2
     result = db->close(db, 0);
 #else