auth-cleanup-20070208
[openafs.git] / src / budb / db_alloc.c
1 /*
2  * Copyright 2000, International Business Machines Corporation and others.
3  * All Rights Reserved.
4  * 
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  */
9
10 #include <afsconfig.h>
11 #include <afs/param.h>
12
13 RCSID
14     ("$Header$");
15
16 #ifdef AFS_NT40_ENV
17 #include <winsock2.h>
18 #else
19 #include <netinet/in.h>
20 #endif
21 #ifdef HAVE_STRING_H
22 #include <string.h>
23 #else
24 #ifdef HAVE_STRINGS_H
25 #include <strings.h>
26 #endif
27 #endif
28 #include <sys/types.h>
29 #include <afs/stds.h>
30 #include <ubik.h>
31 #include <afs/bubasics.h>
32 #include "budb_errs.h"
33 #include "database.h"
34
35
36 /* block and structure allocation routines */
37
38 static int nEntries[NBLOCKTYPES];
39 static int sizeEntries[NBLOCKTYPES];
40
41 afs_int32
42 InitDBalloc()
43 {
44     nEntries[0] = 0;
45     sizeEntries[0] = 0;
46
47     nEntries[volFragment_BLOCK] = NvolFragmentS;
48     nEntries[volInfo_BLOCK] = NvolInfoS;
49     nEntries[tape_BLOCK] = NtapeS;
50     nEntries[dump_BLOCK] = NdumpS;
51
52     sizeEntries[volFragment_BLOCK] = sizeof(((struct vfBlock *) NULL)->a[0]);
53     sizeEntries[volInfo_BLOCK] = sizeof(((struct viBlock *) NULL)->a[0]);
54     sizeEntries[tape_BLOCK] = sizeof(((struct tBlock *) NULL)->a[0]);
55     sizeEntries[dump_BLOCK] = sizeof(((struct dBlock *) NULL)->a[0]);
56
57     return 0;
58 }
59
60 /* AllocBlock
61  *      allocate a (basic) database block. Extends the database if
62  *      no free blocks are available.
63  * exit:
64  *      0 - aP points to a cleared block
65  *      n - error
66  */
67
68 afs_int32
69 AllocBlock(ut, block, aP)
70      struct ubik_trans *ut;
71      struct block *block;       /* copy of data */
72      dbadr *aP;                 /* db addr of block */
73 {
74     dbadr a;
75
76     if (db.h.freePtrs[0] == 0) {
77         /* if there are no free blocks, extend the database */
78         LogDebug(2, "AllocBlock: extending db\n");
79
80         a = ntohl(db.h.eofPtr);
81         if (set_header_word(ut, eofPtr, htonl(a + BLOCKSIZE)))
82             return BUDB_IO;
83     } else {
84         a = ntohl(db.h.freePtrs[0]);
85         if (dbread(ut, a, (char *)block, sizeof(block->h))      /* read hdr */
86             ||set_header_word(ut, freePtrs[0], block->h.next)   /* set next */
87             )
88             return BUDB_IO;
89     }
90
91     /* clear and return the block */
92     memset(block, 0, sizeof(*block));
93     *aP = a;
94     return 0;
95 }
96
97 /* FreeBlock
98  *      Free a basic block
99  * entry:
100  *      bh - block header ptr. Memory copy of the block header.
101  *      a - disk address of the block
102  */
103
104 afs_int32
105 FreeBlock(ut, bh, a)
106      struct ubik_trans *ut;
107      struct blockHeader *bh;    /* copy of data */
108      dbadr a;                   /* db address of block */
109 {
110     if (a != BlockBase(a))
111         db_panic("Block addr no good");
112     memset(bh, 0, sizeof(*bh));
113     bh->next = db.h.freePtrs[0];
114     if (set_header_word(ut, freePtrs[0], htonl(a))
115         || dbwrite(ut, a, (char *)bh, sizeof(*bh)))
116         return BUDB_IO;
117     return 0;
118 }
119
120
121 /* AllocStructure
122  * entry:
123  *      type - type of structure to allocate
124  *      related - address of related block
125  *      saP - db addr of structure
126  *      s -  structure data
127  */
128
129 afs_int32
130 AllocStructure(ut, type, related, saP, s)
131      struct ubik_trans *ut;
132      char type;
133      dbadr related;
134      dbadr *saP;
135      char *s;
136 {
137     dbadr a;                    /* block addr */
138     struct block b;             /* copy of data */
139     int i;                      /* block structure array index */
140     afs_int32 *bs;              /* ptr to first word of structure */
141     int nFree;
142
143     if ((type == 0)
144         || (type > MAX_STRUCTURE_BLOCK_TYPE)
145         ) {
146         db_panic("bad structure type");
147     }
148     bs = (afs_int32 *) b.a;     /* ptr to first structure of block */
149
150     if (db.h.freePtrs[type] == 0) {
151         /* no free items of specified type */
152
153         if (AllocBlock(ut, &b, &a)
154             || set_header_word(ut, freePtrs[type], htonl(a))
155             ) {
156             return BUDB_IO;
157         }
158
159         b.h.next = 0;
160         b.h.type = type;
161         b.h.flags = 0;
162         b.h.nFree = ntohs(nEntries[type] - 1);
163         *bs = 1;                /* not free anymore */
164
165         if (dbwrite(ut, a, (char *)&b, sizeof(b)))
166             return BUDB_IO;
167         LogDebug(2, "AllocStructure: allocated new block\n");
168     } else {
169         int count = 10;
170
171         /* Only do 10 (or so) at a time, to avoid transactions which modify
172          * many buffer.
173          */
174
175         while (1) {
176             a = ntohl(db.h.freePtrs[type]);
177             if (dbread(ut, a, (char *)&b, sizeof(b)))
178                 return BUDB_IO;
179
180             nFree = ntohs(b.h.nFree);
181             if (nFree == 0)
182                 db_panic("nFree is zero");
183
184             /* Completely empty blocks go to generic free list if there are
185              * more blocks on this free list 
186              */
187             if (b.h.next && (nFree == nEntries[type]) && (count-- > 0)) {
188                 if (set_header_word(ut, freePtrs[type], b.h.next)
189                     || FreeBlock(ut, &b.h, a)
190                     ) {
191                     return BUDB_IO;
192                 }
193                 LogDebug(2, "AllocStrucure: add to free block list\n");
194             } else {
195                 /* we found a free structure */
196                 if (nFree == 1) {
197                     /* if last free one: unthread block */
198                     if (set_header_word(ut, freePtrs[type], b.h.next))
199                         return BUDB_IO;
200                 }
201                 break;
202             }
203         }
204
205         /* find the free structure - arbitrarily uses first word as
206          * allocated/free status. PA.
207          */
208         i = 0;
209         while (*bs) {
210             i++;
211             bs = (afs_int32 *) ((char *)bs + sizeEntries[type]);
212         }
213
214         if (i >= nEntries[type])
215             db_panic("free count inconsistent with block");
216
217         b.h.nFree = htons(nFree - 1);
218         if (dbwrite(ut, a, (char *)&b, sizeof(b.h)))
219             return BUDB_IO;
220     }
221     *(afs_int32 *) s = 1;       /* make sure structure is not free */
222     *saP = a + ((char *)bs - (char *)&b);
223
224     LogDebug(3, "allocated at %d, block at %d, offset %d\n", *saP, a,
225              ((char *)bs - (char *)&b));
226     /* caller must write back at least first word of structure */
227     return 0;
228 }
229
230
231
232 afs_int32
233 FreeStructure(ut, type, sa)
234      struct ubik_trans *ut;
235      char type;                 /* type of structure to allocate */
236      dbadr sa;                  /* db addr of structure */
237 {
238     struct blockHeader bh;      /* header of containing block */
239     dbadr a;                    /* db address of block */
240     int nFree;                  /* new free structures count */
241     afs_int32 freeWord;
242
243     if ((type == 0) || (type > MAX_STRUCTURE_BLOCK_TYPE))
244         db_panic("bad structure type");
245
246     a = BlockBase(sa);
247     if (dbread(ut, a, (char *)&bh, sizeof(bh)))
248         return BUDB_IO;
249     if (type != bh.type)
250         db_panic("block and structure of different types");
251
252     bh.nFree = htons(nFree = ntohs(bh.nFree) + 1);
253     if (nFree > nEntries[type])
254         db_panic("free count too large");
255     if (nFree == 1) {           /* add to free list for type */
256         bh.next = db.h.freePtrs[type];
257         if (set_header_word(ut, freePtrs[type], htonl(a)))
258             return BUDB_IO;
259     }
260
261     /* mark the structure as free, and write out block header */
262     if (set_word_offset(ut, sa, &freeWord, 0, 0)
263         || dbwrite(ut, a, (char *)&bh, sizeof(bh)))
264         return BUDB_IO;
265     return 0;
266 }