1<?xml version="1.0" encoding="UTF-8" standalone="no"?> 2<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> 3<html xmlns="http://www.w3.org/1999/xhtml"> 4 <head> 5 <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> 6 <title>Using C Structures with DB</title> 7 <link rel="stylesheet" href="gettingStarted.css" type="text/css" /> 8 <meta name="generator" content="DocBook XSL Stylesheets V1.73.2" /> 9 <link rel="start" href="index.html" title="Getting Started with Berkeley DB" /> 10 <link rel="up" href="DBEntry.html" title="Chapter��3.��Database Records" /> 11 <link rel="prev" href="usingDbt.html" title="Reading and Writing Database Records" /> 12 <link rel="next" href="DbUsage.html" title="Database Usage Example" /> 13 </head> 14 <body> 15 <div class="navheader"> 16 <table width="100%" summary="Navigation header"> 17 <tr> 18 <th colspan="3" align="center">Using C Structures with DB</th> 19 </tr> 20 <tr> 21 <td width="20%" align="left"><a accesskey="p" href="usingDbt.html">Prev</a>��</td> 22 <th width="60%" align="center">Chapter��3.��Database Records</th> 23 <td width="20%" align="right">��<a accesskey="n" href="DbUsage.html">Next</a></td> 24 </tr> 25 </table> 26 <hr /> 27 </div> 28 <div class="sect1" lang="en" xml:lang="en"> 29 <div class="titlepage"> 30 <div> 31 <div> 32 <h2 class="title" style="clear: both"><a id="cstructs"></a>Using C Structures with DB</h2> 33 </div> 34 </div> 35 </div> 36 <div class="toc"> 37 <dl> 38 <dt> 39 <span class="sect2"> 40 <a href="cstructs.html#cstructdynamic">C Structures with Pointers</a> 41 </span> 42 </dt> 43 </dl> 44 </div> 45 <p> 46 Storing data in structures is a handy way to pack varied types of 47 information into each database record. DB databases are sometimes 48 thought of as a two column table where column 1 is the key and column 2 is 49 the data. By using structures, you can effectively turn this table into 50 <span class="emphasis"><em>n</em></span> columns where <span class="emphasis"><em>n-1</em></span> columns 51 are contained in the structure. 52 </p> 53 <p> 54 So long as a C structure contains fields that are not pointers, you can safely 55 store and retrieve them in the same way as you would any primitive 56 datatype. The following code fragment illustrates this: 57 </p> 58 <a id="c_dbt6"></a> 59 <pre class="programlisting">#include <db.h> 60#include <string.h> 61 62typedef struct my_struct { 63 int id; 64 char familiar_name[MAXLINE]; /* Some suitably large value */ 65 char surname[MAXLINE]; 66} MY_STRUCT; 67 68... 69 70DBT key, data; 71DB *my_database; 72MY_STRUCT user; 73char *fname = "David"; 74char *sname = "Rider"; 75 76/* Database open omitted for clarity */ 77 78user.id = 1; 79strncpy(user.familiar_name, fname, strlen(fname)+1); 80strncpy(user.surname, sname, strlen(sname)+1); 81 82/* Zero out the DBTs before using them. */ 83memset(&key, 0, sizeof(DBT)); 84memset(&data, 0, sizeof(DBT)); 85 86key.data = &(user.id); 87key.size = sizeof(int); 88 89data.data = &user; 90data.size = sizeof(MY_STRUCT); 91 92my_database->put(my_database, NULL, &key, &data, DB_NOOVERWRITE);</pre> 93 <p> 94 To retrieve the structure, make sure you supply your own 95 memory. The reason why is that like real numbers, some systems require 96 structures to be aligned in a specific way. Because it is possible that 97 the memory DB provides is not aligned properly, for safest result simply 98 use your own memory: 99 </p> 100 <a id="c_dbt7"></a> 101 <pre class="programlisting">#include <db.h> 102#include <string.h> 103 104... 105 106DBT key, data; 107DB *my_database; 108MY_STRUCT user; 109 110/* Database open omitted for clarity */ 111 112/* Zero out the DBTs before using them. */ 113memset(&key, 0, sizeof(DBT)); 114memset(&data, 0, sizeof(DBT)); 115 116/* Initialize the structure */ 117memset(&user, 0, sizeof(MY_STRUCT)); 118user.id = 1; 119 120key.data = &user.id; 121key.size = sizeof(int); 122 123/* Use our memory to retrieve the structure */ 124data.data = &user; 125data.ulen = sizeof(MY_STRUCT); 126data.flags = DB_DBT_USERMEM; 127 128my_database->get(my_database, NULL, &key, &data, 0); 129 130printf("Familiar name: %s\n", user.familiar_name); 131printf("Surname: %s\n", user.surname); </pre> 132 <p> 133 Be aware that while this is the easiest way to manage structures stored 134 in DB databases, this approach does suffer from causing your 135 database to be larger than is strictly necessary. Each structure stored 136 in the database is of a fixed size, and you do not see any space savings 137 from storing a (for example) 5 character surname versus a 20 character 138 surname. 139 </p> 140 <p> 141 For a simple example such as this, the padding stored with each record 142 is probably not critical. However, if you are storing structures that 143 contain a very large number of character arrays, or if you are simply 144 storing millions of records, then you may want to avoid this approach. 145 The wasted space in each record will only serve to make your databases 146 larger than need be, which will in turn require a larger cache and more 147 disk I/O than you would ordinarily need. 148 </p> 149 <p> 150 An alternative approach is described next. 151 </p> 152 <div class="sect2" lang="en" xml:lang="en"> 153 <div class="titlepage"> 154 <div> 155 <div> 156 <h3 class="title"><a id="cstructdynamic"></a>C Structures with Pointers</h3> 157 </div> 158 </div> 159 </div> 160 <p> 161 It is often necessary in C structures 162 163 164 to use fields 165 166 167 that are pointers to 168 dynamically allocated memory. This is particularly 169 true if you want to store character strings (or any kind of an array for 170 that matter), and you want to avoid any overhead caused by 171 pre-designating the size of the array. 172 </p> 173 <p> 174 When storing structures 175 176 like these you need to make sure that all of 177 the data pointed to and contained by the structure 178 179 180 is lined up in a 181 single contiguous block of memory. Remember that DB stores data 182 located at a specific address and of a particular size. If your structure 183 184 includes fields 185 186 that are pointing to dynamically allocated memory, then 187 the data that you want to store can be located in different, not 188 necessarily contiguous, locations on the heap. 189 </p> 190 <p> 191 The easiest way to solve this problem is to pack your data 192 into a single memory location and then store the data in that location. 193 (This process is sometimes called <span class="emphasis"><em>marshalling the 194 data</em></span>.) 195 For example: 196 </p> 197 <a id="c_dbt8"></a> 198 <pre class="programlisting">#include <db.h> 199#include <string.h> 200#include <stdlib.h> 201 202typedef struct my_struct { 203 int id; 204 char *familiar_name; 205 char *surname; 206} MY_STRUCT; 207 208... 209 210DBT key, data; 211DB *my_database; 212MY_STRUCT user; 213int buffsize, bufflen; 214char fname[ ] = "Pete"; 215char sname[10]; 216char *databuff; 217 218strncpy(sname, "Oar", strlen("Oar")+1); 219 220/* Database open omitted for clarity */ 221 222user.id = 1; 223user.familiar_name = fname; 224user.surname = sname; 225 226/* Some of the structure's data is on the stack, and 227 * some is on the heap. To store this structure's data, we 228 * need to marshall it -- pack it all into a single location 229 * in memory. 230 */ 231 232/* Get the buffer */ 233buffsize = sizeof(int) + 234 (strlen(user.familiar_name) + strlen(user.surname) + 2); 235databuff = malloc(buffsize); 236memset(databuff, 0, buffsize); 237 238/* copy everything to the buffer */ 239memcpy(databuff, &(user.id), sizeof(int)); 240bufflen = sizeof(int); 241 242memcpy(databuff + bufflen, user.familiar_name, 243 strlen(user.familiar_name) + 1); 244bufflen += strlen(user.familiar_name) + 1; 245 246memcpy(databuff + bufflen, user.surname, 247 strlen(user.surname) + 1); 248bufflen += strlen(user.surname) + 1; 249 250/* Now store it */ 251 252/* Zero out the DBTs before using them. */ 253memset(&key, 0, sizeof(DBT)); 254memset(&data, 0, sizeof(DBT)); 255 256key.data = &(user.id); 257key.size = sizeof(int); 258 259data.data = databuff; 260data.size = bufflen; 261 262my_database->put(my_database, NULL, &key, &data, DB_NOOVERWRITE); 263free(sname); 264free(databuff);</pre> 265 <p> 266 To retrieve the stored structure: 267 </p> 268 <a id="c_dbt9"></a> 269 <pre class="programlisting">#include <db.h> 270#include <string.h> 271#include <stdlib.h> 272 273typedef struct my_struct { 274 char *familiar_name; 275 char *surname; 276 int id; 277} MY_STRUCT; 278 279... 280 281int id; 282DBT key, data; 283DB *my_database; 284MY_STRUCT user; 285char *buffer; 286 287/* Database open omitted for clarity */ 288 289 290/* Zero out the DBTs before using them. */ 291memset(&key, 0, sizeof(DBT)); 292memset(&data, 0, sizeof(DBT)); 293 294id = 1; 295key.data = &id; 296key.size = sizeof(int); 297 298my_database->get(my_database, NULL, &key, &data, 0); 299 300/* 301 * Some compilers won't allow pointer arithmetic on void *'s, 302 * so use a char * instead. 303 */ 304buffer = data.data; 305 306user.id = *((int *)data.data); 307user.familiar_name = buffer + sizeof(int); 308user.surname = buffer + sizeof(int) + strlen(user.familiar_name) + 1; </pre> 309 </div> 310 </div> 311 <div class="navfooter"> 312 <hr /> 313 <table width="100%" summary="Navigation footer"> 314 <tr> 315 <td width="40%" align="left"><a accesskey="p" href="usingDbt.html">Prev</a>��</td> 316 <td width="20%" align="center"> 317 <a accesskey="u" href="DBEntry.html">Up</a> 318 </td> 319 <td width="40%" align="right">��<a accesskey="n" href="DbUsage.html">Next</a></td> 320 </tr> 321 <tr> 322 <td width="40%" align="left" valign="top">Reading and Writing Database Records��</td> 323 <td width="20%" align="center"> 324 <a accesskey="h" href="index.html">Home</a> 325 </td> 326 <td width="40%" align="right" valign="top">��Database Usage Example</td> 327 </tr> 328 </table> 329 </div> 330 </body> 331</html> 332