Update from db-2.3.12.
[kopensolaris-gnu/glibc.git] / db2 / log / log_register.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[] = "@(#)log_register.c        10.12 (Sleepycat) 9/29/97";
11 #endif /* not lint */
12
13 #ifndef NO_SYSTEM_INCLUDES
14 #include <sys/types.h>
15
16 #include <errno.h>
17 #include <stdlib.h>
18 #include <string.h>
19 #endif
20
21 #include "db_int.h"
22 #include "shqueue.h"
23 #include "log.h"
24 #include "common_ext.h"
25
26 /*
27  * log_register --
28  *      Register a file name.
29  */
30 int
31 log_register(dblp, dbp, name, type, idp)
32         DB_LOG *dblp;
33         DB *dbp;
34         const char *name;
35         DBTYPE type;
36         u_int32_t *idp;
37 {
38         DBT r_name;
39         DBT fid_dbt;
40         DB_LSN r_unused;
41         FNAME *fnp;
42         size_t len;
43         u_int32_t fid;
44         int inserted, ret;
45         char *fullname;
46         void *fidp, *namep;
47
48         fid = 0;
49         inserted = 0;
50         fullname = NULL;
51         fnp = fidp = namep = NULL;
52
53         /* Check the arguments. */
54         if (type != DB_BTREE && type != DB_HASH && type != DB_RECNO) {
55                 __db_err(dblp->dbenv, "log_register: unknown DB file type");
56                 return (EINVAL);
57         }
58
59         /* Get the log file id. */
60         if ((ret = __db_appname(dblp->dbenv,
61             DB_APP_DATA, NULL, name, NULL, &fullname)) != 0)
62                 return (ret);
63
64         LOCK_LOGREGION(dblp);
65
66         /*
67          * See if we've already got this file in the log, finding the
68          * next-to-lowest file id currently in use as we do it.
69          */
70         for (fid = 1, fnp = SH_TAILQ_FIRST(&dblp->lp->fq, __fname);
71             fnp != NULL; fnp = SH_TAILQ_NEXT(fnp, q, __fname)) {
72                 if (fid <= fnp->id)
73                         fid = fnp->id + 1;
74                 if (!memcmp(dbp->lock.fileid,
75                     R_ADDR(dblp, fnp->fileid_off), DB_FILE_ID_LEN)) {
76                         ++fnp->ref;
77                         fid = fnp->id;
78                         if (!F_ISSET(dblp, DB_AM_RECOVER) &&
79                             (ret = __log_add_logid(dblp, dbp, fid) != 0))
80                                 goto err;
81                         goto ret1;
82                 }
83         }
84
85         /* Allocate a new file name structure. */
86         if ((ret = __db_shalloc(dblp->addr, sizeof(FNAME), 0, &fnp)) != 0)
87                 goto err;
88         fnp->ref = 1;
89         fnp->id = fid;
90         fnp->s_type = type;
91
92         if ((ret = __db_shalloc(dblp->addr, DB_FILE_ID_LEN, 0, &fidp)) != 0)
93                 goto err;
94         /*
95          * XXX Now that uids are fixed size, we can put them in the fnp
96          * structure.
97          */
98         fnp->fileid_off = R_OFFSET(dblp, fidp);
99         memcpy(fidp, dbp->lock.fileid, DB_FILE_ID_LEN);
100
101         len = strlen(name) + 1;
102         if ((ret = __db_shalloc(dblp->addr, len, 0, &namep)) != 0)
103                 goto err;
104         fnp->name_off = R_OFFSET(dblp, namep);
105         memcpy(namep, name, len);
106
107         SH_TAILQ_INSERT_HEAD(&dblp->lp->fq, fnp, q, __fname);
108         inserted = 1;
109
110         /* Log the registry. */
111         if (!F_ISSET(dblp, DB_AM_RECOVER)) {
112                 r_name.data = (void *)name;             /* XXX: Yuck! */
113                 r_name.size = strlen(name) + 1;
114                 memset(&fid_dbt, 0, sizeof(fid_dbt));
115                 fid_dbt.data = dbp->lock.fileid;
116                 fid_dbt.size = DB_FILE_ID_LEN;
117                 if ((ret = __log_register_log(dblp, NULL, &r_unused,
118                     0, &r_name, &fid_dbt, fid, type)) != 0)
119                         goto err;
120                 if ((ret = __log_add_logid(dblp, dbp, fid)) != 0)
121                         goto err;
122         }
123
124         if (0) {
125 err:            /*
126                  * XXX
127                  * We should grow the region.
128                  */
129                 if (inserted)
130                         SH_TAILQ_REMOVE(&dblp->lp->fq, fnp, q, __fname);
131                 if (namep != NULL)
132                         __db_shalloc_free(dblp->addr, namep);
133                 if (fidp != NULL)
134                         __db_shalloc_free(dblp->addr, fidp);
135                 if (fnp != NULL)
136                         __db_shalloc_free(dblp->addr, fnp);
137         }
138
139 ret1:   UNLOCK_LOGREGION(dblp);
140
141         if (fullname != NULL)
142                 FREES(fullname);
143
144         if (idp != NULL)
145                 *idp = fid;
146         return (ret);
147 }
148
149 /*
150  * log_unregister --
151  *      Discard a registered file name.
152  */
153 int
154 log_unregister(dblp, fid)
155         DB_LOG *dblp;
156         u_int32_t fid;
157 {
158         DB_LSN r_unused;
159         FNAME *fnp;
160         int ret;
161
162         ret = 0;
163         LOCK_LOGREGION(dblp);
164
165         /* Unlog the registry. */
166         if (!F_ISSET(dblp, DB_AM_RECOVER) &&
167             (ret = __log_unregister_log(dblp, NULL, &r_unused, 0, fid)) != 0)
168                 return (ret);
169
170         /* Find the entry in the log. */
171         for (fnp = SH_TAILQ_FIRST(&dblp->lp->fq, __fname);
172             fnp != NULL; fnp = SH_TAILQ_NEXT(fnp, q, __fname))
173                 if (fid == fnp->id)
174                         break;
175         if (fnp == NULL) {
176                 __db_err(dblp->dbenv, "log_unregister: non-existent file id");
177                 ret = EINVAL;
178                 goto ret1;
179         }
180
181         /* If more than 1 reference, decrement the reference and return. */
182         if (fnp->ref > 1) {
183                 --fnp->ref;
184                 goto ret1;
185         }
186
187         /* Free the unique file information, name and structure. */
188         __db_shalloc_free(dblp->addr, R_ADDR(dblp, fnp->fileid_off));
189         __db_shalloc_free(dblp->addr, R_ADDR(dblp, fnp->name_off));
190         SH_TAILQ_REMOVE(&dblp->lp->fq, fnp, q, __fname);
191         __db_shalloc_free(dblp->addr, fnp);
192
193         /*
194          * Remove from the process local table.  If this operation is taking
195          * place during recovery, then the logid was never added to the table,
196          * so do not remove it.
197          */
198         if (!F_ISSET(dblp, DB_AM_RECOVER))
199                 __log_rem_logid(dblp, fid);
200
201 ret1:   UNLOCK_LOGREGION(dblp);
202
203         return (ret);
204 }