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