Imported Upstream version 5.3.21
[platform/upstream/libdb.git] / examples / c / getting_started / example_database_load.c
1 /*-
2  * See the file LICENSE for redistribution information.
3  *
4  * Copyright (c) 2004, 2012 Oracle and/or its affiliates.  All rights reserved.
5  */
6
7 #include "gettingstarted_common.h"
8
9 /* Forward declarations */
10 int usage(void);
11 int load_vendors_database(STOCK_DBS, char *);
12 size_t pack_string(char *, char *, size_t);
13 int load_inventory_database(STOCK_DBS, char *);
14
15 int
16 usage()
17 {
18     fprintf(stderr, "example_database_load [-b <path to data files>]");
19     fprintf(stderr, " [-h <database_home_directory>]\n");
20
21     fprintf(stderr, "\tNote: Any path specified must end with your");
22     fprintf(stderr, " system's path delimiter (/ or \\)\n");
23     return (-1);
24 }
25
26 /*
27  * Loads the contents of vendors.txt and inventory.txt into
28  * Berkeley DB databases. Also causes the itemname secondary
29  * database to be created and loaded.
30  */
31 int
32 main(int argc, char *argv[])
33 {
34     STOCK_DBS my_stock;
35     int ch, ret;
36     size_t size;
37     char *basename, *inventory_file, *vendor_file;
38
39     /* Initialize the STOCK_DBS struct */
40     initialize_stockdbs(&my_stock);
41
42    /* Initialize the base path. */
43     basename = "./";
44
45     /* Parse the command line arguments */
46     while ((ch = getopt(argc, argv, "b:h:")) != EOF)
47         switch (ch) {
48         case 'h':
49             if (optarg[strlen(optarg)-1] != '/' &&
50                 optarg[strlen(optarg)-1] != '\\')
51                 return (usage());
52             my_stock.db_home_dir = optarg;
53             break;
54         case 'b':
55             if (basename[strlen(basename)-1] != '/' &&
56                 basename[strlen(basename)-1] != '\\')
57                 return (usage());
58             basename = optarg;
59             break;
60         case '?':
61         default:
62             return (usage());
63         }
64
65     /* Identify the files that will hold our databases */
66     set_db_filenames(&my_stock);
67
68     /* Find our input files */
69     size = strlen(basename) + strlen(INVENTORY_FILE) + 1;
70     inventory_file = malloc(size);
71     snprintf(inventory_file, size, "%s%s", basename, INVENTORY_FILE);
72
73     size = strlen(basename) + strlen(VENDORS_FILE) + 1;
74     vendor_file = malloc(size);
75     snprintf(vendor_file, size, "%s%s", basename, VENDORS_FILE);
76
77     /* Open all databases */
78     ret = databases_setup(&my_stock, "example_database_load", stderr);
79     if (ret) {
80         fprintf(stderr, "Error opening databases\n");
81         databases_close(&my_stock);
82         return (ret);
83     }
84
85     ret = load_vendors_database(my_stock, vendor_file);
86     if (ret) {
87         fprintf(stderr, "Error loading vendors database.\n");
88         databases_close(&my_stock);
89         return (ret);
90     }
91     ret = load_inventory_database(my_stock, inventory_file);
92     if (ret) {
93         fprintf(stderr, "Error loading inventory database.\n");
94         databases_close(&my_stock);
95         return (ret);
96     }
97
98     /* close our environment and databases */
99     databases_close(&my_stock);
100
101     printf("Done loading databases.\n");
102     return (ret);
103 }
104
105 /*
106  * Loads the contents of the vendors.txt file into
107  * a database.
108  */
109 int
110 load_vendors_database(STOCK_DBS my_stock, char *vendor_file)
111 {
112     DBT key, data;
113     char buf[MAXLINE];
114     FILE *ifp;
115     VENDOR my_vendor;
116
117     /* Load the vendors database */
118     ifp = fopen(vendor_file, "r");
119     if (ifp == NULL) {
120         fprintf(stderr, "Error opening file '%s'\n", vendor_file);
121         return (-1);
122     }
123
124     while (fgets(buf, MAXLINE, ifp) != NULL) {
125         /* zero out the structure */
126         memset(&my_vendor, 0, sizeof(VENDOR));
127         /* Zero out the DBTs */
128         memset(&key, 0, sizeof(DBT));
129         memset(&data, 0, sizeof(DBT));
130
131         /*
132          * Scan the line into the structure.
133          * Convenient, but not particularly safe.
134          * In a real program, there would be a lot more
135          * defensive code here.
136          */
137         sscanf(buf,
138           "%20[^#]#%20[^#]#%20[^#]#%3[^#]#%6[^#]#%13[^#]#%20[^#]#%20[^\n]",
139           my_vendor.name, my_vendor.street,
140           my_vendor.city, my_vendor.state,
141           my_vendor.zipcode, my_vendor.phone_number,
142           my_vendor.sales_rep, my_vendor.sales_rep_phone);
143
144         /* Now that we have our structure we can load it into the database. */
145
146         /* Set up the database record's key */
147         key.data = my_vendor.name;
148         key.size = (u_int32_t)strlen(my_vendor.name) + 1;
149
150         /* Set up the database record's data */
151         data.data = &my_vendor;
152         data.size = sizeof(VENDOR);
153
154         /*
155          * Note that given the way we built our struct, there's extra
156          * bytes in it. Essentially we're using fixed-width fields with
157          * the unused portion of some fields padded with zeros. This
158          * is the easiest thing to do, but it does result in a bloated
159          * database. Look at load_inventory_data() for an example of how
160          * to avoid this.
161          */
162
163         /* Put the data into the database */
164         my_stock.vendor_dbp->put(my_stock.vendor_dbp, 0, &key, &data, 0);
165     } /* end vendors database while loop */
166
167     fclose(ifp);
168     return (0);
169 }
170
171 /*
172  * Simple little convenience function that takes a buffer, a string,
173  * and an offset and copies that string into the buffer at the
174  * appropriate location. Used to ensure that all our strings
175  * are contained in a single contiguous chunk of memory.
176  */
177 size_t
178 pack_string(char *buffer, char *string, size_t start_pos)
179 {
180     size_t string_size;
181
182     string_size = strlen(string) + 1;
183     memcpy(buffer+start_pos, string, string_size);
184
185     return (start_pos + string_size);
186 }
187
188 /*
189  * Loads the contents of the inventory.txt file into
190  * a database. Note that because the itemname
191  * secondary database is associated to the inventorydb
192  * (see env_setup() in gettingstarted_common.c), the
193  * itemname index is automatically created when this
194  * database is loaded.
195  */
196 int
197 load_inventory_database(STOCK_DBS my_stock, char *inventory_file)
198 {
199     DBT key, data;
200     char buf[MAXLINE];
201     char databuf[MAXDATABUF];
202     size_t bufLen, dataLen;
203     FILE *ifp;
204
205     /*
206      * Rather than lining everything up nicely in a struct, we're being
207      * deliberately a bit sloppy here. This function illustrates how to
208      * store mixed data that might be obtained from various locations
209      * in your application.
210      */
211     float price;
212     int quantity;
213     char category[MAXFIELD], name[MAXFIELD];
214     char vendor[MAXFIELD], sku[MAXFIELD];
215
216     /* Load the inventory database */
217     ifp = fopen(inventory_file, "r");
218     if (ifp == NULL) {
219         fprintf(stderr, "Error opening file '%s'\n", inventory_file);
220             return (-1);
221     }
222
223     while (fgets(buf, MAXLINE, ifp) != NULL) {
224         /*
225          * Scan the line into the appropriate buffers and variables.
226          * Convenient, but not particularly safe. In a real
227          * program, there would be a lot more defensive code here.
228          */
229         sscanf(buf,
230           "%20[^#]#%20[^#]#%f#%i#%20[^#]#%20[^\n]",
231           name, sku, &price, &quantity, category, vendor);
232
233         /*
234          * Now pack it into a single contiguous memory location for
235          * storage.
236          */
237         memset(databuf, 0, MAXDATABUF);
238         bufLen = 0;
239         dataLen = 0;
240
241         dataLen = sizeof(float);
242         memcpy(databuf, &price, dataLen);
243         bufLen += dataLen;
244
245         dataLen = sizeof(int);
246         memcpy(databuf + bufLen, &quantity, dataLen);
247         bufLen += dataLen;
248
249         bufLen = pack_string(databuf, name, bufLen);
250         bufLen = pack_string(databuf, sku, bufLen);
251         bufLen = pack_string(databuf, category, bufLen);
252         bufLen = pack_string(databuf, vendor, bufLen);
253
254         /* Zero out the DBTs */
255         memset(&key, 0, sizeof(DBT));
256         memset(&data, 0, sizeof(DBT));
257
258         /* The key is the item's SKU */
259         key.data = sku;
260         key.size = (u_int32_t)strlen(sku) + 1;
261
262         /* The data is the information that we packed into databuf. */
263         data.data = databuf;
264         data.size = (u_int32_t)bufLen;
265
266         /* Put the data into the database */
267         my_stock.vendor_dbp->put(my_stock.inventory_dbp, 0, &key, &data, 0);
268     } /* end vendors database while loop */
269
270     /* Cleanup */
271     fclose(ifp);
272
273     return (0);
274 }