Update from db-2.3.12.
[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.15 (Sleepycat) 10/25/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 *)__db_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) || LF_ISSET(DB_MPOOL_PRIVATE))
66                 F_SET(dbmp, MP_ISPRIVATE);
67
68         /*
69          * XXX
70          * HP-UX won't permit mutexes to live in anything but shared memory.
71          * So, we have to instantiate the shared mpool region file on that
72          * architecture, regardless.  If this turns out to be a performance
73          * problem, we could probably use anonymous memory instead.
74          */
75 #if defined(__hppa)
76         F_CLR(dbmp, MP_ISPRIVATE);
77 #endif
78
79         /*
80          * Map in the region.  We do locking regardless, as portions of it are
81          * implemented in common code (if we put the region in a file, that is).
82          */
83         F_SET(dbmp, MP_LOCKREGION);
84         if ((ret = __memp_ropen(dbmp, path, cachesize, mode, flags)) != 0)
85                 goto err;
86         F_CLR(dbmp, MP_LOCKREGION);
87
88         /*
89          * If there's concurrent access, then we have to lock the region.
90          * If it's threaded, then we have to lock both the handles and the
91          * region, and we need to allocate a mutex for that purpose.
92          */
93         if (!F_ISSET(dbmp, MP_ISPRIVATE))
94                 F_SET(dbmp, MP_LOCKREGION);
95         if (LF_ISSET(DB_THREAD)) {
96                 F_SET(dbmp, MP_LOCKHANDLE | MP_LOCKREGION);
97                 LOCKREGION(dbmp);
98                 ret = __memp_ralloc(dbmp,
99                     sizeof(db_mutex_t), NULL, &dbmp->mutexp);
100                 UNLOCKREGION(dbmp);
101                 if (ret != 0) {
102                         (void)memp_close(dbmp);
103                         goto err;
104                 }
105                 LOCKINIT(dbmp, dbmp->mutexp);
106         }
107
108         *retp = dbmp;
109         return (0);
110
111 err:    if (dbmp != NULL)
112                 FREE(dbmp, sizeof(DB_MPOOL));
113         return (ret);
114 }
115
116 /*
117  * memp_close --
118  *      Close a memory pool.
119  */
120 int
121 memp_close(dbmp)
122         DB_MPOOL *dbmp;
123 {
124         DB_MPOOLFILE *dbmfp;
125         DB_MPREG *mpreg;
126         int ret, t_ret;
127
128         ret = 0;
129
130         /* Discard DB_MPREGs. */
131         while ((mpreg = LIST_FIRST(&dbmp->dbregq)) != NULL) {
132                 LIST_REMOVE(mpreg, q);
133                 FREE(mpreg, sizeof(DB_MPREG));
134         }
135
136         /* Discard DB_MPOOLFILEs. */
137         while ((dbmfp = TAILQ_FIRST(&dbmp->dbmfq)) != NULL)
138                 if ((t_ret = memp_fclose(dbmfp)) != 0 && ret == 0)
139                         ret = t_ret;
140
141         /* Discard thread mutex. */
142         if (F_ISSET(dbmp, MP_LOCKHANDLE)) {
143                 LOCKREGION(dbmp);
144                 __db_shalloc_free(dbmp->addr, dbmp->mutexp);
145                 UNLOCKREGION(dbmp);
146         }
147
148         /* Close the region. */
149         if ((t_ret = __memp_rclose(dbmp)) && ret == 0)
150                 ret = t_ret;
151
152         /* Discard the structure. */
153         FREE(dbmp, sizeof(DB_MPOOL));
154
155         return (ret);
156 }
157
158 /*
159  * memp_unlink --
160  *      Exit a memory pool.
161  */
162 int
163 memp_unlink(path, force, dbenv)
164         const char *path;
165         int force;
166         DB_ENV *dbenv;
167 {
168         return (__db_runlink(dbenv,
169             DB_APP_NONE, path, DB_DEFAULT_MPOOL_FILE, force));
170 }
171
172 /*
173  * memp_register --
174  *      Register a file type's pgin, pgout routines.
175  */
176 int
177 memp_register(dbmp, ftype, pgin, pgout)
178         DB_MPOOL *dbmp;
179         int ftype;
180         int (*pgin) __P((db_pgno_t, void *, DBT *));
181         int (*pgout) __P((db_pgno_t, void *, DBT *));
182 {
183         DB_MPREG *mpr;
184
185         if ((mpr = (DB_MPREG *)__db_malloc(sizeof(DB_MPREG))) == NULL)
186                 return (ENOMEM);
187
188         mpr->ftype = ftype;
189         mpr->pgin = pgin;
190         mpr->pgout = pgout;
191
192         /*
193          * Insert at the head.  Because we do a linear walk, we'll find
194          * the most recent registry in the case of multiple entries, so
195          * we don't have to check for multiple registries.
196          */
197         LOCKHANDLE(dbmp, dbmp->mutexp);
198         LIST_INSERT_HEAD(&dbmp->dbregq, mpr, q);
199         UNLOCKHANDLE(dbmp, dbmp->mutexp);
200
201         return (0);
202 }