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