Update NEWS for 1.6.22
[pkg-k5-afs_openafs.git] / src / budb / database.c
blob8341161b6f6cae7261cac5d4d456349ad4f5c4c8
1 /*
2 * Copyright 2000, International Business Machines Corporation and others.
3 * All Rights Reserved.
5 * This software has been released under the terms of the IBM Public
6 * License. For details, see the LICENSE file in the top-level source
7 * directory or online at http://www.openafs.org/dl/license10.html
8 */
10 #include <afsconfig.h>
11 #include <afs/param.h>
14 #ifdef AFS_NT40_ENV
15 #include <winsock2.h>
16 #else
17 #include <netinet/in.h>
18 #endif
19 #include <sys/types.h>
20 #include <afs/stds.h>
21 #include <ubik.h>
22 #include <afs/bubasics.h>
23 #include "budb_errs.h"
24 #include "database.h"
25 #include "error_macros.h"
26 #include "budb_internal.h"
27 #include "afs/audit.h"
28 #include <string.h>
30 int pollCount;
31 struct memoryDB db; /* really allocate it here */
33 void
34 db_panic(char *reason)
36 LogError(0, "db_panic: %s\n", reason);
37 BUDB_EXIT(-1);
40 afs_int32
41 InitDB(void)
43 afs_int32 code;
45 pollCount = 0;
47 memset(&db, 0, sizeof(db));
48 if ((code = InitDBalloc()) || (code = InitDBhash()))
49 return code;
50 return 0;
53 /* package up seek and write into one procedure for ease of use */
55 /* dbwrite
56 * write a portion of the database
57 * entry:
58 * pos - offset into the database (disk address). If this is in the
59 * database header, then buff must be a ptr to a portion of
60 * the in-core header
61 * buff - the information to write
62 * len - size of the write
65 afs_int32
66 dbwrite(struct ubik_trans *ut, afs_int32 pos, void *buff, afs_int32 len)
68 afs_int32 code = 0;
70 if (((pos < sizeof(db.h)) && (buff != (char *)&db.h + pos))
71 || (pos >= ntohl(db.h.eofPtr))) {
72 Log("dbwrite: Illegal attempt to write at location 0 or past EOF\n");
73 ERROR(BUDB_IO);
76 code = ubik_Seek(ut, 0, pos);
77 if (code) {
78 LogError(code, "dbwrite: ubik_Seek to %d failed\n", pos);
79 ERROR(code);
81 code = ubik_Write(ut, buff, len);
82 if (code) {
83 LogError(code, "dbwrite: ubik_Write failed\n");
84 ERROR(code);
87 error_exit:
88 if (((++pollCount) % 4) == 0) { /* Poll every 4 reads/writes */
89 #ifndef AFS_PTHREAD_ENV
90 IOMGR_Poll();
91 #endif
92 pollCount = 0;
94 return code;
97 /* same thing for read */
99 afs_int32
100 dbread(struct ubik_trans *ut, afs_int32 pos, void *buff, afs_int32 len)
102 afs_int32 code = 0;
104 if (pos >= ntohl(db.h.eofPtr)) {
105 LogError(0, "dbread: Attempt to read @%d (past EOF)\n", pos);
106 ERROR(BUDB_IO);
109 code = ubik_Seek(ut, 0, pos);
110 if (code) {
111 LogError(code, "dbread: ubik_Seek to %d failed\n", pos);
112 ERROR(code);
114 code = ubik_Read(ut, buff, len);
115 if (code) {
116 LogError(code, "dbread: ubik_Read pos %d, buff %"AFS_PTR_FMT
117 ", len %d\n", pos, buff, len);
118 ERROR(code);
121 error_exit:
122 if (((++pollCount) % 4) == 0) { /* Poll every 4 reads/writes */
123 #ifndef AFS_PTHREAD_ENV
124 IOMGR_Poll();
125 #endif
126 pollCount = 0;
128 return code;
131 /* Same as dbread excepts it does checking */
132 afs_int32
133 cdbread(struct ubik_trans *ut, int type, afs_int32 pos, void *buff, afs_int32 len)
135 afs_int32 code = 0;
137 code = checkDiskAddress(pos, type, 0, 0);
138 if (code) {
139 LogError(code, "cdbread: Bad Address for block %d (addr 0x%x)\n",
140 type, pos);
141 ERROR(code);
144 code = ubik_Seek(ut, 0, pos);
145 if (code) {
146 LogError(code, "cdbread: ubik_Seek to 0x%x failed\n", pos);
147 ERROR(code);
149 code = ubik_Read(ut, buff, len);
150 if (code) {
151 LogError(code, "cdbread: ubik_Read pos 0x%x, buff %"AFS_PTR_FMT
152 ", len %d\n", pos, buff, len);
153 ERROR(code);
156 error_exit:
157 if (((++pollCount) % 4) == 0) { /* Poll every 4 reads/writes */
158 #ifndef AFS_PTHREAD_ENV
159 IOMGR_Poll();
160 #endif
161 pollCount = 0;
163 return code;
166 /* check that the database has been initialized. Be careful to fail in a safe
167 manner, to avoid bogusly reinitializing the db. */
170 * reads in db cache from ubik.
172 * @param[in] ut ubik transaction
173 * @param[in] rock opaque pointer to an int (*) (struct ubik_trans *), which
174 * will be called on rebuilding the database (or NULL to not
175 * rebuild the db)
177 * @return operation status
178 * @retval 0 success
180 static afs_int32
181 UpdateCache(struct ubik_trans *ut, void *rock)
183 int (*db_init) (struct ubik_trans *ut) = rock;
184 afs_int32 code;
186 db.h.eofPtr = htonl(sizeof(db.h)); /* for sanity check in dbread */
187 code = dbread(ut, 0, (char *)&db.h, sizeof(db.h));
188 if (code)
189 ERROR(code);
191 if ((ntohl(db.h.version) != BUDB_VERSION)
192 || (ntohl(db.h.checkVersion) != BUDB_VERSION)) {
194 if ((ntohl(db.h.version) == 0) || (ntohl(db.h.checkVersion) == 0))
195 ERROR(BUDB_EMPTY);
197 LogError(0, "DB version should be %d; Initial = %d; Terminal = %d\n",
198 BUDB_VERSION, ntohl(db.h.version), ntohl(db.h.checkVersion));
199 ERROR(BUDB_IO);
202 db.readTime = time(0);
203 ht_Reset(&db.volName);
204 ht_Reset(&db.tapeName);
205 ht_Reset(&db.dumpName);
206 ht_Reset(&db.dumpIden);
208 error_exit:
209 if (code) {
210 if ((code == UEOF) || (code == BUDB_EMPTY)) {
211 if (db_init) {
212 LogDebug(0, "No data base - Building new one\n");
214 /* try to write a good header */
215 memset(&db.h, 0, sizeof(db.h));
216 db.h.version = htonl(BUDB_VERSION);
217 db.h.checkVersion = htonl(BUDB_VERSION);
218 db.h.lastUpdate = db.h.lastDumpId = htonl(time(0));
219 db.h.eofPtr = htonl(sizeof(db.h));
221 /* text ptrs cleared by bzero */
222 ht_DBInit();
224 code = dbwrite(ut, 0, (char *)&db.h, sizeof(db.h));
225 if (code)
226 code = BUDB_IO; /* return the error code */
227 else
228 code = db_init(ut); /* initialize the db */
229 } else {
230 LogDebug(0, "No data base\n");
231 code = BUDB_EMPTY;
233 } else {
234 LogDebug(0, "I/O Error\n");
235 code = BUDB_IO;
238 return code;
241 afs_int32
242 CheckInit(struct ubik_trans *ut,
243 int (*db_init) (struct ubik_trans *ut)) /* call if rebuilding DB */
245 return ubik_CheckCache(ut, UpdateCache, db_init);