Update.
[glibc.git] / db2 / mp / mp_open.c
blobfc985bc521fb2dc8bf7aef642fb2b38a49298c0d
1 /*-
2 * See the file LICENSE for redistribution information.
4 * Copyright (c) 1996, 1997, 1998
5 * Sleepycat Software. All rights reserved.
6 */
7 #include "config.h"
9 #ifndef lint
10 static const char sccsid[] = "@(#)mp_open.c 10.23 (Sleepycat) 5/3/98";
11 #endif /* not lint */
13 #ifndef NO_SYSTEM_INCLUDES
14 #include <sys/types.h>
16 #include <errno.h>
17 #include <string.h>
18 #endif
20 #include "db_int.h"
21 #include "shqueue.h"
22 #include "db_shash.h"
23 #include "mp.h"
24 #include "common_ext.h"
27 * memp_open --
28 * Initialize and/or join a memory pool.
30 int
31 memp_open(path, flags, mode, dbenv, retp)
32 const char *path;
33 u_int32_t flags;
34 int mode;
35 DB_ENV *dbenv;
36 DB_MPOOL **retp;
38 DB_MPOOL *dbmp;
39 size_t cachesize;
40 int is_private, ret;
42 /* Validate arguments. */
43 #ifdef HAVE_SPINLOCKS
44 #define OKFLAGS (DB_CREATE | DB_MPOOL_PRIVATE | DB_NOMMAP | DB_THREAD)
45 #else
46 #define OKFLAGS (DB_CREATE | DB_MPOOL_PRIVATE | DB_NOMMAP)
47 #endif
48 if ((ret = __db_fchk(dbenv, "memp_open", flags, OKFLAGS)) != 0)
49 return (ret);
51 /* Extract fields from DB_ENV structure. */
52 cachesize = dbenv == NULL ? 0 : dbenv->mp_size;
54 /* Create and initialize the DB_MPOOL structure. */
55 if ((dbmp = (DB_MPOOL *)__db_calloc(1, sizeof(DB_MPOOL))) == NULL)
56 return (ENOMEM);
57 LIST_INIT(&dbmp->dbregq);
58 TAILQ_INIT(&dbmp->dbmfq);
60 dbmp->dbenv = dbenv;
62 /* Decide if it's possible for anyone else to access the pool. */
63 is_private =
64 (dbenv == NULL && path == NULL) || LF_ISSET(DB_MPOOL_PRIVATE);
67 * Map in the region. We do locking regardless, as portions of it are
68 * implemented in common code (if we put the region in a file, that is).
70 F_SET(dbmp, MP_LOCKREGION);
71 if ((ret = __memp_ropen(dbmp,
72 path, cachesize, mode, is_private, LF_ISSET(DB_CREATE))) != 0)
73 goto err;
74 F_CLR(dbmp, MP_LOCKREGION);
77 * If there's concurrent access, then we have to lock the region.
78 * If it's threaded, then we have to lock both the handles and the
79 * region, and we need to allocate a mutex for that purpose.
81 if (!is_private)
82 F_SET(dbmp, MP_LOCKREGION);
83 if (LF_ISSET(DB_THREAD)) {
84 F_SET(dbmp, MP_LOCKHANDLE | MP_LOCKREGION);
85 LOCKREGION(dbmp);
86 ret = __memp_ralloc(dbmp,
87 sizeof(db_mutex_t), NULL, &dbmp->mutexp);
88 UNLOCKREGION(dbmp);
89 if (ret != 0) {
90 (void)memp_close(dbmp);
91 goto err;
93 LOCKINIT(dbmp, dbmp->mutexp);
96 *retp = dbmp;
97 return (0);
99 err: if (dbmp != NULL)
100 FREE(dbmp, sizeof(DB_MPOOL));
101 return (ret);
105 * memp_close --
106 * Close a memory pool.
109 memp_close(dbmp)
110 DB_MPOOL *dbmp;
112 DB_MPOOLFILE *dbmfp;
113 DB_MPREG *mpreg;
114 int ret, t_ret;
116 ret = 0;
118 /* Discard DB_MPREGs. */
119 while ((mpreg = LIST_FIRST(&dbmp->dbregq)) != NULL) {
120 LIST_REMOVE(mpreg, q);
121 FREE(mpreg, sizeof(DB_MPREG));
124 /* Discard DB_MPOOLFILEs. */
125 while ((dbmfp = TAILQ_FIRST(&dbmp->dbmfq)) != NULL)
126 if ((t_ret = memp_fclose(dbmfp)) != 0 && ret == 0)
127 ret = t_ret;
129 /* Discard thread mutex. */
130 if (F_ISSET(dbmp, MP_LOCKHANDLE)) {
131 LOCKREGION(dbmp);
132 __db_shalloc_free(dbmp->addr, dbmp->mutexp);
133 UNLOCKREGION(dbmp);
136 /* Close the region. */
137 if ((t_ret = __db_rdetach(&dbmp->reginfo)) != 0 && ret == 0)
138 ret = t_ret;
140 if (dbmp->reginfo.path != NULL)
141 FREES(dbmp->reginfo.path);
142 FREE(dbmp, sizeof(DB_MPOOL));
144 return (ret);
148 * memp_unlink --
149 * Exit a memory pool.
152 memp_unlink(path, force, dbenv)
153 const char *path;
154 int force;
155 DB_ENV *dbenv;
157 REGINFO reginfo;
158 int ret;
160 memset(&reginfo, 0, sizeof(reginfo));
161 reginfo.dbenv = dbenv;
162 reginfo.appname = DB_APP_NONE;
163 if (path != NULL && (reginfo.path = __db_strdup(path)) == NULL)
164 return (ENOMEM);
165 reginfo.file = DB_DEFAULT_MPOOL_FILE;
166 ret = __db_runlink(&reginfo, force);
167 if (reginfo.path != NULL)
168 FREES(reginfo.path);
169 return (ret);
173 * memp_register --
174 * Register a file type's pgin, pgout routines.
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 *));
183 DB_MPREG *mpr;
185 if ((mpr = (DB_MPREG *)__db_malloc(sizeof(DB_MPREG))) == NULL)
186 return (ENOMEM);
188 mpr->ftype = ftype;
189 mpr->pgin = pgin;
190 mpr->pgout = pgout;
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.
197 LOCKHANDLE(dbmp, dbmp->mutexp);
198 LIST_INSERT_HEAD(&dbmp->dbregq, mpr, q);
199 UNLOCKHANDLE(dbmp, dbmp->mutexp);
201 return (0);