BRL-CAD
db_alloc.c
Go to the documentation of this file.
1 /* D B _ A L L O C . C
2  * BRL-CAD
3  *
4  * Copyright (c) 1988-2014 United States Government as represented by
5  * the U.S. Army Research Laboratory.
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public License
9  * version 2.1 as published by the Free Software Foundation.
10  *
11  * This library is distributed in the hope that it will be useful, but
12  * WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this file; see the file named COPYING for more
18  * information.
19  */
20 /** @addtogroup db4 */
21 /** @{ */
22 /** @file librt/db_alloc.c
23  *
24  * v4 granule allocation routines
25  *
26  */
27 
28 #include "common.h"
29 
30 #include <string.h>
31 #include "bio.h"
32 
33 #include "vmath.h"
34 #include "db.h"
35 #include "raytrace.h"
36 
37 
38 /**
39  * Find a block of database storage of "count" granules.
40  *
41  * Returns:
42  * 0 OK
43  * non-0 failure
44  */
45 int
46 db_alloc(register struct db_i *dbip, register struct directory *dp, size_t count)
47 {
48  size_t len;
49  union record rec;
50 
51  RT_CK_DBI(dbip);
52  RT_CK_DIR(dp);
53  if (RT_G_DEBUG&DEBUG_DB) bu_log("db_alloc(%s) %p, %p, count=%zu\n",
54  dp->d_namep, (void *)dbip, (void *)dp, count);
55  if (count <= 0) {
56  bu_log("db_alloc(0)\n");
57  return -1;
58  }
59 
60  if (dp->d_flags & RT_DIR_INMEM) {
61  if (dp->d_un.ptr) {
62  dp->d_un.ptr = bu_realloc(dp->d_un.ptr,
63  count * sizeof(union record), "db_alloc() d_un.ptr");
64  } else {
65  dp->d_un.ptr = bu_malloc(count * sizeof(union record), "db_alloc() d_un.ptr");
66  }
67  dp->d_len = count;
68  return 0;
69  }
70 
71  if (dbip->dbi_read_only) {
72  bu_log("db_alloc on READ-ONLY file\n");
73  return -1;
74  }
75  while (1) {
76  len = rt_memalloc(&(dbip->dbi_freep), (unsigned)count);
77  if (len == 0L) {
78  /* No contiguous free block, append to file */
79  if ((dp->d_addr = dbip->dbi_eof) == RT_DIR_PHONY_ADDR) {
80  bu_log("db_alloc: bad EOF\n");
81  return -1;
82  }
83  dp->d_len = count;
84  dbip->dbi_eof += (off_t)(count * sizeof(union record));
85  dbip->dbi_nrec += count;
86  break;
87  }
88  dp->d_addr = (off_t)(len * sizeof(union record));
89  dp->d_len = count;
90  if (db_get(dbip, dp, &rec, 0, 1) < 0)
91  return -1;
92  if (rec.u_id != ID_FREE) {
93  bu_log("db_alloc(): len %ld non-FREE (id %d), skipping\n",
94  len, rec.u_id);
95  continue;
96  }
97  }
98 
99  /* Clear out ALL the granules, for safety */
100  return db_zapper(dbip, dp, 0);
101 }
102 
103 
104 /**
105  * Delete a specific record from database entry
106  * No longer supported.
107  */
108 int
109 db_delrec(struct db_i *dbip, register struct directory *dp, int recnum)
110 {
111 
112  RT_CK_DBI(dbip);
113  RT_CK_DIR(dp);
114  if (RT_G_DEBUG&DEBUG_DB) bu_log("db_delrec(%s) %p, %p, recnum=%d\n",
115  dp->d_namep, (void *)dbip, (void *)dp, recnum);
116 
117  bu_log("ERROR db_delrec() is no longer supported. Use combination import/export routines.\n");
118  return -1;
119 }
120 
121 
122 /**
123  * Delete the indicated database record(s).
124  * Arrange to write "free storage" database markers in its place,
125  * positively erasing what had been there before.
126  *
127  * Returns:
128  * 0 on success
129  * non-zero on failure
130  */
131 int
132 db_delete(struct db_i *dbip, struct directory *dp)
133 {
134  int i = 0;
135 
136  RT_CK_DBI(dbip);
137  RT_CK_DIR(dp);
138  if (RT_G_DEBUG&DEBUG_DB) bu_log("db_delete(%s) %p, %p\n",
139  dp->d_namep, (void *)dbip, (void *)dp);
140 
141  if (dp->d_flags & RT_DIR_INMEM) {
142  bu_free(dp->d_un.ptr, "db_delete d_un.ptr");
143  dp->d_un.ptr = NULL;
144  dp->d_len = 0;
145  return 0;
146  }
147 
148  if (db_version(dbip) == 4) {
149  i = db_zapper(dbip, dp, 0);
150  rt_memfree(&(dbip->dbi_freep), (unsigned)dp->d_len, dp->d_addr/(sizeof(union record)));
151  } else if (db_version(dbip) == 5) {
152  i = db5_write_free(dbip, dp, dp->d_len);
153  rt_memfree(&(dbip->dbi_freep), dp->d_len, dp->d_addr);
154  } else {
155  bu_bomb("db_delete() unsupported database version\n");
156  }
157 
158  dp->d_len = 0;
159  dp->d_addr = RT_DIR_PHONY_ADDR;
160  return i;
161 }
162 
163 
164 /**
165  * Using a single call to db_put(), write multiple zeroed records out,
166  * all with u_id field set to ID_FREE.
167  * This will zap all records from "start" to the end of this entry.
168  *
169  * Returns:
170  * 0 on success (from db_put())
171  * non-zero on failure
172  */
173 int
174 db_zapper(struct db_i *dbip, struct directory *dp, size_t start)
175 {
176  union record *rp;
177  size_t i;
178  size_t todo;
179  int ret;
180 
181  RT_CK_DBI(dbip);
182  RT_CK_DIR(dp);
183  if (RT_G_DEBUG&DEBUG_DB) bu_log("db_zapper(%s) %p, %p, start=%zu\n",
184  dp->d_namep, (void *)dbip, (void *)dp, start);
185 
186  if (dp->d_flags & RT_DIR_INMEM) bu_bomb("db_zapper() called on RT_DIR_INMEM object\n");
187 
188  if (dbip->dbi_read_only)
189  return -1;
190 
191  BU_ASSERT_LONG(dbip->dbi_version, ==, 4);
192 
193  if (dp->d_len < start)
194  return -1;
195 
196  if ((todo = dp->d_len - start) == 0)
197  return 0; /* OK -- trivial */
198 
199  rp = (union record *)bu_malloc(todo * sizeof(union record), "db_zapper buf");
200  memset((char *)rp, 0, todo * sizeof(union record));
201 
202  for (i=0; i < todo; i++)
203  rp[i].u_id = ID_FREE;
204  ret = db_put(dbip, dp, rp, (off_t)start, todo);
205  bu_free((char *)rp, "db_zapper buf");
206  return ret;
207 }
208 
209 
210 void
212 {
213  struct directory *dp;
214  size_t bytes;
215 
216  RT_CK_RESOURCE(resp);
218 
219  BU_ASSERT_PTR(resp->re_directory_hd, ==, NULL);
220 
221  /* Get a BIG block */
222  bytes = (size_t)bu_malloc_len_roundup(1024*sizeof(struct directory));
223  dp = (struct directory *)bu_calloc(1, bytes, "re_directory_blocks from db_alloc_directory_block() " BU_FLSTR);
224 
225  /* Record storage for later */
226  bu_ptbl_ins(&resp->re_directory_blocks, (long *)dp);
227 
228  while (bytes >= sizeof(struct directory)) {
229  dp->d_magic = RT_DIR_MAGIC;
230  dp->d_forw = resp->re_directory_hd;
231  resp->re_directory_hd = dp;
232  dp++;
233  bytes -= sizeof(struct directory);
234  }
235 }
236 
237 
238 void
239 rt_alloc_seg_block(register struct resource *res)
240 {
241  register struct seg *sp;
242  size_t bytes;
243 
244  RT_CK_RESOURCE(res);
245 
246  if (!BU_LIST_IS_INITIALIZED(&res->re_seg)) {
247  BU_LIST_INIT(&(res->re_seg));
248  bu_ptbl_init(&res->re_seg_blocks, 64, "re_seg_blocks ptbl");
249  }
250  bytes = bu_malloc_len_roundup(64*sizeof(struct seg));
251  sp = (struct seg *)bu_malloc(bytes, "rt_alloc_seg_block()");
252  bu_ptbl_ins(&res->re_seg_blocks, (long *)sp);
253  while (bytes >= sizeof(struct seg)) {
254  sp->l.magic = RT_SEG_MAGIC;
255  BU_LIST_INSERT(&(res->re_seg), &(sp->l));
256  res->re_seglen++;
257  sp++;
258  bytes -= sizeof(struct seg);
259  }
260 }
261 
262 
263 /** @} */
264 
265 /*
266  * Local Variables:
267  * mode: C
268  * tab-width: 8
269  * indent-tabs-mode: t
270  * c-file-style: "stroustrup"
271  * End:
272  * ex: shiftwidth=4 tabstop=8
273  */
char * d_namep
pointer to name string
Definition: raytrace.h:859
Definition: raytrace.h:800
void bu_log(const char *,...) _BU_ATTR_PRINTF12
Definition: log.c:176
#define BU_LIST_INSERT(old, new)
Definition: list.h:183
int db_alloc(register struct db_i *dbip, register struct directory *dp, size_t count)
Definition: db_alloc.c:46
size_t d_len
of db granules used
Definition: raytrace.h:867
#define RT_DIR_INMEM
object is in memory (only)
Definition: raytrace.h:889
long re_seglen
Definition: raytrace.h:1445
void bu_ptbl_init(struct bu_ptbl *b, size_t len, const char *str)
Definition: ptbl.c:32
Definition: raytrace.h:368
#define BU_LIST_IS_INITIALIZED(_hp)
Definition: list.h:175
#define BU_ASSERT_LONG(_lhs, _relation, _rhs)
Definition: defines.h:240
int db_version(struct db_i *dbip)
Definition: db5_scan.c:414
Header file for the BRL-CAD common definitions.
#define BU_CK_PTBL(_p)
Definition: ptbl.h:74
void db_alloc_directory_block(struct resource *resp)
Definition: db_alloc.c:211
uint32_t d_magic
Magic number.
Definition: raytrace.h:858
int bu_ptbl_ins(struct bu_ptbl *b, long *p)
struct directory * d_forw
link to next dir entry
Definition: raytrace.h:864
struct bu_list l
Definition: raytrace.h:369
int db_get(const struct db_i *, const struct directory *dp, union record *where, off_t offset, size_t len)
Definition: db_io.c:134
void * bu_malloc(size_t siz, const char *str)
Definition: malloc.c:314
int db_delete(struct db_i *dbip, struct directory *dp)
Definition: db_alloc.c:132
struct bu_ptbl re_seg_blocks
Table of malloc'ed blocks of segs.
Definition: raytrace.h:1444
size_t dbi_nrec
PRIVATE: # records after db_scan()
Definition: raytrace.h:817
void * memset(void *s, int c, size_t n)
#define RT_G_DEBUG
Definition: raytrace.h:1718
int db5_write_free(struct db_i *dbip, struct directory *dp, size_t length)
Definition: db5_alloc.c:40
void * bu_calloc(size_t nelem, size_t elsize, const char *str)
Definition: malloc.c:321
int db_zapper(struct db_i *dbip, struct directory *dp, size_t start)
Definition: db_alloc.c:174
#define RT_CK_DIR(_dp)
Definition: raytrace.h:876
off_t dbi_eof
PRIVATE: End+1 pos after db_scan()
Definition: raytrace.h:816
int db_delrec(struct db_i *dbip, register struct directory *dp, int recnum)
Definition: db_alloc.c:109
#define RT_DIR_PHONY_ADDR
Special marker for d_addr field.
Definition: raytrace.h:879
#define BU_FLSTR
Definition: defines.h:142
void * bu_realloc(void *ptr, size_t siz, const char *str)
struct mem_map * dbi_freep
PRIVATE: map of free granules.
Definition: raytrace.h:819
size_t rt_memalloc(struct mem_map **pp, size_t size)
uint32_t magic
Magic # for mem id/check.
Definition: list.h:119
struct bu_ptbl re_directory_blocks
Table of malloc'ed blocks.
Definition: raytrace.h:1482
#define RT_CK_DBI(_p)
Definition: raytrace.h:829
int dbi_read_only
!0 => read only file
Definition: raytrace.h:806
union directory::@8 d_un
#define BU_LIST_INIT(_hp)
Definition: list.h:148
#define RT_SEG_MAGIC
Definition: magic.h:167
#define DEBUG_DB
5 Database debugging
Definition: raytrace.h:88
#define RT_CK_RESOURCE(_p)
Definition: raytrace.h:1490
#define BU_ASSERT_PTR(_lhs, _relation, _rhs)
Definition: defines.h:227
int db_put(struct db_i *, const struct directory *dp, union record *where, off_t offset, size_t len)
Definition: db_io.c:212
struct directory * re_directory_hd
Definition: raytrace.h:1481
void * ptr
ptr to in-memory-only obj
Definition: raytrace.h:862
void rt_alloc_seg_block(register struct resource *res)
Definition: db_alloc.c:239
int bu_malloc_len_roundup(int nbytes)
int dbi_version
PRIVATE: use db_version()
Definition: raytrace.h:824
void bu_free(void *ptr, const char *str)
Definition: malloc.c:328
#define RT_DIR_MAGIC
Definition: magic.h:159
void rt_memfree(struct mem_map **pp, size_t size, off_t addr)
Definition: memalloc.c:228
int d_flags
flags
Definition: raytrace.h:869
void bu_bomb(const char *str) _BU_ATTR_NORETURN
Definition: bomb.c:91
struct bu_list re_seg
Head of segment freelist.
Definition: raytrace.h:1443