Update from db-2.3.12.
[kopensolaris-gnu/glibc.git] / db2 / db / db_thread.c
1 /*-
2  * See the file LICENSE for redistribution information.
3  *
4  * Copyright (c) 1996, 1997
5  *      Sleepycat Software.  All rights reserved.
6  */
7
8 #include "config.h"
9
10 #ifndef lint
11 static const char sccsid[] = "@(#)db_thread.c   8.13 (Sleepycat) 10/25/97";
12 #endif /* not lint */
13
14 #ifndef NO_SYSTEM_INCLUDES
15 #include <sys/types.h>
16
17 #include <errno.h>
18 #include <stdlib.h>
19 #include <string.h>
20 #endif
21
22 #include "db_int.h"
23 #include "db_page.h"
24 #include "shqueue.h"
25 #include "db_am.h"
26
27 static int __db_getlockid __P((DB *, DB *));
28
29 /*
30  * __db_gethandle --
31  *      Called by db access method routines when the DB_THREAD flag is set.
32  *      This routine returns a handle, either an existing handle from the
33  *      chain of handles, or creating one if necessary.
34  *
35  * PUBLIC: int __db_gethandle __P((DB *, int (*)(DB *, DB *), DB **));
36  */
37 int
38 __db_gethandle(dbp, am_func, dbpp)
39         DB *dbp, **dbpp;
40         int (*am_func) __P((DB *, DB *));
41 {
42         DB *ret_dbp;
43         int ret, t_ret;
44
45         if ((ret = __db_mutex_lock((db_mutex_t *)dbp->mutexp, -1)) != 0)
46                 return (ret);
47
48         if ((ret_dbp = LIST_FIRST(&dbp->handleq)) != NULL)
49                 /* Simply take one off the list. */
50                 LIST_REMOVE(ret_dbp, links);
51         else {
52                 /* Allocate a new handle. */
53                 if ((ret_dbp = (DB *)__db_malloc(sizeof(*dbp))) == NULL) {
54                         ret = ENOMEM;
55                         goto err;
56                 }
57                 memcpy(ret_dbp, dbp, sizeof(*dbp));
58                 ret_dbp->internal = NULL;
59                 TAILQ_INIT(&ret_dbp->curs_queue);
60
61                 /* Set the locker, the lock structure and the lock DBT. */
62                 if ((ret = __db_getlockid(dbp, ret_dbp)) != 0)
63                         goto err;
64
65                 /* Finally, call the access method specific dup function. */
66                 if ((ret = am_func(dbp, ret_dbp)) != 0)
67                         goto err;
68         }
69
70         *dbpp = ret_dbp;
71
72         if (0) {
73 err:            if (ret_dbp != NULL)
74                         FREE(ret_dbp, sizeof(*ret_dbp));
75         }
76         if ((t_ret =
77             __db_mutex_unlock((db_mutex_t *)dbp->mutexp, -1)) != 0 && ret == 0)
78                 ret = t_ret;
79         return (ret);
80 }
81
82 /*
83  * __db_puthandle --
84  *      Return a DB handle to the pool for later use.
85  *
86  * PUBLIC: int __db_puthandle __P((DB *));
87  */
88 int
89 __db_puthandle(dbp)
90         DB *dbp;
91 {
92         DB *master;
93         int ret;
94
95         master = dbp->master;
96         if ((ret = __db_mutex_lock((db_mutex_t *)master->mutexp, -1)) != 0)
97                 return (ret);
98
99         LIST_INSERT_HEAD(&master->handleq, dbp, links);
100
101         return (__db_mutex_unlock((db_mutex_t *)master->mutexp, -1));
102 }
103
104 /*
105  * __db_getlockid --
106  *      Create a new locker ID and copy the file lock information from
107  *      the old DB into the new one.
108  */
109 static int
110 __db_getlockid(dbp, new_dbp)
111         DB *dbp, *new_dbp;
112 {
113         int ret;
114
115         if (F_ISSET(dbp, DB_AM_LOCKING)) {
116                 if ((ret = lock_id(dbp->dbenv->lk_info, &new_dbp->locker)) != 0)
117                         return (ret);
118                 memcpy(new_dbp->lock.fileid, dbp->lock.fileid, DB_FILE_ID_LEN);
119                 new_dbp->lock_dbt.size = sizeof(new_dbp->lock);
120                 new_dbp->lock_dbt.data = &new_dbp->lock;
121         }
122         return (0);
123 }