Update to db 2.3.10.
[kopensolaris-gnu/glibc.git] / db2 / mp / mp_open.c
1 /*-
2  * See the file LICENSE for redistribution information.
3  *
4  * Copyright (c) 1996, 1997
5  *      Sleepycat Software.  All rights reserved.
6  */
7 #include "config.h"
8
9 #ifndef lint
10 static const char sccsid[] = "@(#)mp_open.c     10.13 (Sleepycat) 9/23/97";
11 #endif /* not lint */
12
13 #ifndef NO_SYSTEM_INCLUDES
14 #include <sys/types.h>
15
16 #include <errno.h>
17 #include <fcntl.h>
18 #include <stdlib.h>
19 #include <string.h>
20 #include <unistd.h>
21 #endif
22
23 #include "db_int.h"
24 #include "shqueue.h"
25 #include "db_shash.h"
26 #include "mp.h"
27 #include "common_ext.h"
28
29 /*
30  * memp_open --
31  *      Initialize and/or join a memory pool.
32  */
33 int
34 memp_open(path, flags, mode, dbenv, retp)
35         const char *path;
36         int flags, mode;
37         DB_ENV *dbenv;
38         DB_MPOOL **retp;
39 {
40         DB_MPOOL *dbmp;
41         size_t cachesize;
42         int ret;
43
44         /* Validate arguments. */
45 #ifdef HAVE_SPINLOCKS
46 #define OKFLAGS (DB_CREATE | DB_MPOOL_PRIVATE | DB_NOMMAP | DB_THREAD)
47 #else
48 #define OKFLAGS (DB_CREATE | DB_MPOOL_PRIVATE | DB_NOMMAP)
49 #endif
50         if ((ret = __db_fchk(dbenv, "memp_open", flags, OKFLAGS)) != 0)
51                 return (ret);
52
53         /* Extract fields from DB_ENV structure. */
54         cachesize = dbenv == NULL ? 0 : dbenv->mp_size;
55
56         /* Create and initialize the DB_MPOOL structure. */
57         if ((dbmp = (DB_MPOOL *)calloc(1, sizeof(DB_MPOOL))) == NULL)
58                 return (ENOMEM);
59         LIST_INIT(&dbmp->dbregq);
60         TAILQ_INIT(&dbmp->dbmfq);
61
62         dbmp->dbenv = dbenv;
63
64         /* Decide if it's possible for anyone else to access the pool. */
65         if ((dbenv == NULL && path == NULL) ||
66             (dbenv != NULL && F_ISSET(dbenv, DB_MPOOL_PRIVATE)))
67                 F_SET(dbmp, MP_ISPRIVATE);
68
69         /*
70          * XXX
71          * HP-UX won't permit mutexes to live in anything but shared memory.
72          * So, we have to instantiate the shared mpool region file on that
73          * architecture, regardless.  If this turns out to be a performance
74          * problem, we could probably use anonymous memory instead.
75          */
76 #if defined(__hppa)
77         F_CLR(dbmp, MP_ISPRIVATE);
78 #endif
79
80         /*
81          * Map in the region.  We do locking regardless, as portions of it are
82          * implemented in common code (if we put the region in a file, that is).
83          */
84         F_SET(dbmp, MP_LOCKREGION);
85         if ((ret = __memp_ropen(dbmp, path, cachesize, mode, flags)) != 0)
86                 goto err;
87         F_CLR(dbmp, MP_LOCKREGION);
88
89         /*
90          * If there's concurrent access, then we have to lock the region.
91          * If it's threaded, then we have to lock both the handles and the
92          * region, and we need to allocate a mutex for that purpose.
93          */
94         if (!F_ISSET(dbmp, MP_ISPRIVATE))
95                 F_SET(dbmp, MP_LOCKREGION);
96         if (LF_ISSET(DB_THREAD)) {
97                 F_SET(dbmp, MP_LOCKHANDLE | MP_LOCKREGION);
98                 LOCKREGION(dbmp);
99                 ret = __memp_ralloc(dbmp,
100                     sizeof(db_mutex_t), NULL, &dbmp->mutexp);
101                 UNLOCKREGION(dbmp);
102                 if (ret != 0) {
103                         (void)memp_close(dbmp);
104                         goto err;
105                 }
106                 LOCKINIT(dbmp, dbmp->mutexp);
107         }
108
109         *retp = dbmp;
110         return (0);
111
112 err:    if (dbmp != NULL)
113                 FREE(dbmp, sizeof(DB_MPOOL));
114         return (ret);
115 }
116
117 /*
118  * memp_close --
119  *      Close a memory pool.
120  */
121 int
122 memp_close(dbmp)
123         DB_MPOOL *dbmp;
124 {
125         DB_MPOOLFILE *dbmfp;
126         DB_MPREG *mpreg;
127         int ret, t_ret;
128
129         ret = 0;
130
131         /* Discard DB_MPREGs. */
132         while ((mpreg = LIST_FIRST(&dbmp->dbregq)) != NULL) {
133                 LIST_REMOVE(mpreg, q);
134                 FREE(mpreg, sizeof(DB_MPREG));
135         }
136
137         /* Discard DB_MPOOLFILEs. */
138         while ((dbmfp = TAILQ_FIRST(&dbmp->dbmfq)) != NULL)
139                 if ((t_ret = memp_fclose(dbmfp)) != 0 && ret == 0)
140                         ret = t_ret;
141
142         /* Discard thread mutex. */
143         if (F_ISSET(dbmp, MP_LOCKHANDLE)) {
144                 LOCKREGION(dbmp);
145                 __db_shalloc_free(dbmp->addr, dbmp->mutexp);
146                 UNLOCKREGION(dbmp);
147         }
148
149         /* Close the region. */
150         if ((t_ret = __memp_rclose(dbmp)) && ret == 0)
151                 ret = t_ret;
152
153         /* Discard the structure. */
154         FREE(dbmp, sizeof(DB_MPOOL));
155
156         return (ret);
157 }
158
159 /*
160  * memp_unlink --
161  *      Exit a memory pool.
162  */
163 int
164 memp_unlink(path, force, dbenv)
165         const char *path;
166         int force;
167         DB_ENV *dbenv;
168 {
169         return (__db_runlink(dbenv,
170             DB_APP_NONE, path, DB_DEFAULT_MPOOL_FILE, force));
171 }
172
173 /*
174  * memp_register --
175  *      Register a file type's pgin, pgout routines.
176  */
177 int
178 memp_register(dbmp, ftype, pgin, pgout)
179         DB_MPOOL *dbmp;
180         int ftype;
181         int (*pgin) __P((db_pgno_t, void *, DBT *));
182         int (*pgout) __P((db_pgno_t, void *, DBT *));
183 {
184         DB_MPREG *mpr;
185
186         if ((mpr = (DB_MPREG *)malloc(sizeof(DB_MPREG))) == NULL)
187                 return (ENOMEM);
188
189         mpr->ftype = ftype;
190         mpr->pgin = pgin;
191         mpr->pgout = pgout;
192
193         /*
194          * Insert at the head.  Because we do a linear walk, we'll find
195          * the most recent registry in the case of multiple entries, so
196          * we don't have to check for multiple registries.
197          */
198         LOCKHANDLE(dbmp, dbmp->mutexp);
199         LIST_INSERT_HEAD(&dbmp->dbregq, mpr, q);
200         UNLOCKHANDLE(dbmp, dbmp->mutexp);
201
202         return (0);
203 }