e956e809d9d13adb4d5891bf1cee99b390585b42
[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.11 (Sleepycat) 8/18/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->mutex, -1,
46             dbp->dbenv == NULL ? NULL : dbp->dbenv->db_yield)) != 0)
47                 return (ret);
48
49         if ((ret_dbp = LIST_FIRST(&dbp->handleq)) != NULL)
50                 /* Simply take one off the list. */
51                 LIST_REMOVE(ret_dbp, links);
52         else {
53                 /* Allocate a new handle. */
54                 if ((ret_dbp = (DB *)malloc(sizeof(*dbp))) == NULL) {
55                         ret = ENOMEM;
56                         goto err;
57                 }
58                 memcpy(ret_dbp, dbp, sizeof(*dbp));
59                 ret_dbp->internal = NULL;
60                 TAILQ_INIT(&ret_dbp->curs_queue);
61
62                 /* Set the locker, the lock structure and the lock DBT. */
63                 if ((ret = __db_getlockid(dbp, ret_dbp)) != 0)
64                         goto err;
65
66                 /* Finally, call the access method specific dup function. */
67                 if ((ret = am_func(dbp, ret_dbp)) != 0)
68                         goto err;
69         }
70
71         *dbpp = ret_dbp;
72
73         if (0) {
74 err:            if (ret_dbp != NULL)
75                         FREE(ret_dbp, sizeof(*ret_dbp));
76         }
77         if ((t_ret =
78             __db_mutex_unlock((db_mutex_t *)dbp->mutex, -1)) != 0 && ret == 0)
79                 ret = t_ret;
80         return (ret);
81 }
82
83 /*
84  * __db_puthandle --
85  *      Return a DB handle to the pool for later use.
86  *
87  * PUBLIC: int __db_puthandle __P((DB *));
88  */
89 int
90 __db_puthandle(dbp)
91         DB *dbp;
92 {
93         DB *master;
94         int ret;
95
96         master = dbp->master;
97         if ((ret = __db_mutex_lock((db_mutex_t *)master->mutex, -1,
98             dbp->dbenv == NULL ? NULL : dbp->dbenv->db_yield)) != 0)
99                 return (ret);
100
101         LIST_INSERT_HEAD(&master->handleq, dbp, links);
102
103         return (__db_mutex_unlock((db_mutex_t *)master->mutex, -1));
104 }
105
106 /*
107  * __db_getlockid --
108  *      Create a new locker ID and copy the file lock information from
109  *      the old DB into the new one.
110  */
111 static int
112 __db_getlockid(dbp, new_dbp)
113         DB *dbp, *new_dbp;
114 {
115         int ret;
116
117         if (F_ISSET(dbp, DB_AM_LOCKING)) {
118                 if ((ret = lock_id(dbp->dbenv->lk_info, &new_dbp->locker)) != 0)
119                         return (ret);
120                 memcpy(new_dbp->lock.fileid, dbp->lock.fileid, DB_FILE_ID_LEN);
121                 new_dbp->lock_dbt.size = sizeof(new_dbp->lock);
122                 new_dbp->lock_dbt.data = &new_dbp->lock;
123         }
124         return (0);
125 }