257ce1b9e93106d9ae56ed0d01d4c9541108d358
[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.12 (Sleepycat) 7/6/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         LOCKINIT(dbmp, &dbmp->mutex);
60         LIST_INIT(&dbmp->dbregq);
61         TAILQ_INIT(&dbmp->dbmfq);
62
63         dbmp->dbenv = dbenv;
64
65         /* Decide if it's possible for anyone else to access the pool. */
66         if ((dbenv == NULL && path == NULL) ||
67             (dbenv != NULL && F_ISSET(dbenv, DB_MPOOL_PRIVATE)))
68                 F_SET(dbmp, MP_ISPRIVATE);
69
70         /*
71          * Map in the region.  We do locking regardless, as portions of it are
72          * implemented in common code (if we put the region in a file, that is).
73          */
74         F_SET(dbmp, MP_LOCKREGION);
75         if ((ret = __memp_ropen(dbmp, path, cachesize, mode, flags)) != 0)
76                 goto err;
77         F_CLR(dbmp, MP_LOCKREGION);
78
79         /*
80          * If there's concurrent access, then we have to lock the region.
81          * If it's threaded, then we have to lock both the handles and the
82          * region.
83          */
84         if (!F_ISSET(dbmp, MP_ISPRIVATE))
85                 F_SET(dbmp, MP_LOCKREGION);
86         if (LF_ISSET(DB_THREAD))
87                 F_SET(dbmp, MP_LOCKHANDLE | MP_LOCKREGION);
88
89         *retp = dbmp;
90         return (0);
91
92 err:    if (dbmp != NULL)
93                 FREE(dbmp, sizeof(DB_MPOOL));
94         return (ret);
95 }
96
97 /*
98  * memp_close --
99  *      Close a memory pool.
100  */
101 int
102 memp_close(dbmp)
103         DB_MPOOL *dbmp;
104 {
105         DB_MPOOLFILE *dbmfp;
106         DB_MPREG *mpreg;
107         int ret, t_ret;
108
109         ret = 0;
110
111         /* Discard DB_MPREGs. */
112         while ((mpreg = LIST_FIRST(&dbmp->dbregq)) != NULL) {
113                 LIST_REMOVE(mpreg, q);
114                 FREE(mpreg, sizeof(DB_MPREG));
115         }
116
117         /* Discard DB_MPOOLFILEs. */
118         while ((dbmfp = TAILQ_FIRST(&dbmp->dbmfq)) != NULL)
119                 if ((t_ret = memp_fclose(dbmfp)) != 0 && ret == 0)
120                         ret = t_ret;
121
122         /* Close the region. */
123         if ((t_ret = __memp_rclose(dbmp)) && ret == 0)
124                 ret = t_ret;
125
126         /* Free the structure. */
127         FREE(dbmp, sizeof(DB_MPOOL));
128
129         return (ret);
130 }
131
132 /*
133  * memp_unlink --
134  *      Exit a memory pool.
135  */
136 int
137 memp_unlink(path, force, dbenv)
138         const char *path;
139         int force;
140         DB_ENV *dbenv;
141 {
142         return (__db_runlink(dbenv,
143             DB_APP_NONE, path, DB_DEFAULT_MPOOL_FILE, force));
144 }
145
146 /*
147  * memp_register --
148  *      Register a file type's pgin, pgout routines.
149  */
150 int
151 memp_register(dbmp, ftype, pgin, pgout)
152         DB_MPOOL *dbmp;
153         int ftype;
154         int (*pgin) __P((db_pgno_t, void *, DBT *));
155         int (*pgout) __P((db_pgno_t, void *, DBT *));
156 {
157         DB_MPREG *mpr;
158
159         if ((mpr = (DB_MPREG *)malloc(sizeof(DB_MPREG))) == NULL)
160                 return (ENOMEM);
161
162         mpr->ftype = ftype;
163         mpr->pgin = pgin;
164         mpr->pgout = pgout;
165
166         /*
167          * Insert at the head.  Because we do a linear walk, we'll find
168          * the most recent registry in the case of multiple entries, so
169          * we don't have to check for multiple registries.
170          */
171         LOCKHANDLE(dbmp, &dbmp->mutex);
172         LIST_INSERT_HEAD(&dbmp->dbregq, mpr, q);
173         UNLOCKHANDLE(dbmp, &dbmp->mutex);
174
175         return (0);
176 }