1 /*-
2 * Copyright (c) 2004, 2020 Oracle and/or its affiliates. All rights reserved.
3 *
4 * See the file EXAMPLES-LICENSE for license information.
5 */
6
7 #include "gettingstarted_common.h"
8
9 int get_item_name(DB *, const DBT *, const DBT *, DBT *);
10
11 /*
12 * Used to extract an inventory item's name from an
13 * inventory database record. This function is used to create
14 * keys for secondary database records.
15 */
16 int
get_item_name(DB * dbp,const DBT * pkey,const DBT * pdata,DBT * skey)17 get_item_name(DB *dbp, const DBT *pkey, const DBT *pdata, DBT *skey)
18 {
19 u_int offset;
20
21 COMPQUIET(dbp, NULL); /* Not needed, unused. */
22 COMPQUIET(pkey, NULL);
23
24 /*
25 * First, obtain the buffer location where we placed the
26 * item's name. In this example, the item's name is located
27 * in the primary data. It is the first string in the
28 * buffer after the price (a float) and the quantity (an int).
29 *
30 * See load_inventory_database() in example_database_load.c
31 * for how we packed the inventory information into the
32 * data DBT.
33 */
34 offset = sizeof(float) + sizeof(int);
35
36 /* Check to make sure there's data */
37 if (pdata->size < offset)
38 return (-1); /* Returning non-zero means that the
39 * secondary record is not created/updated.
40 */
41
42 /* Now set the secondary key's data to be the item name */
43 memset(skey, 0, sizeof(DBT));
44 skey->data = (u_int8_t *)pdata->data + offset;
45 skey->size = (u_int32_t)strlen(skey->data) + 1;
46
47 return (0);
48 }
49
50 /* Opens a database */
51 int
open_database(DB ** dbpp,const char * file_name,const char * program_name,FILE * error_file_pointer,int is_secondary)52 open_database(DB **dbpp, /* The DB handle that we are opening */
53 const char *file_name, /* The file in which the db lives */
54 const char *program_name, /* Name of the program */
55 FILE *error_file_pointer,
56 int is_secondary)
57 {
58 DB *dbp; /* For convenience */
59 u_int32_t open_flags;
60 int ret;
61
62 /* Initialize the DB handle */
63 ret = db_create(&dbp, NULL, 0);
64 if (ret != 0) {
65 fprintf(error_file_pointer, "%s: %s\n", program_name,
66 db_strerror(ret));
67 return (ret);
68 }
69 /* Point to the memory malloc'd by db_create() */
70 *dbpp = dbp;
71
72 /* Set up error handling for this database */
73 dbp->set_errfile(dbp, error_file_pointer);
74 dbp->set_errpfx(dbp, program_name);
75
76 /*
77 * If this is a secondary database, then we want to allow
78 * sorted duplicates.
79 */
80 if (is_secondary) {
81 ret = dbp->set_flags(dbp, DB_DUPSORT);
82 if (ret != 0) {
83 dbp->err(dbp, ret, "Attempt to set DUPSORT flags failed.",
84 file_name);
85 return (ret);
86 }
87 }
88
89 /* Set the open flags */
90 open_flags = DB_CREATE; /* Allow database creation */
91
92 /* Now open the database */
93 ret = dbp->open(dbp, /* Pointer to the database */
94 NULL, /* Txn pointer */
95 file_name, /* File name */
96 NULL, /* Logical db name */
97 DB_BTREE, /* Database type (using btree) */
98 open_flags, /* Open flags */
99 0); /* File mode. Using defaults */
100 if (ret != 0) {
101 dbp->err(dbp, ret, "Database '%s' open failed.", file_name);
102 return (ret);
103 }
104
105 return (0);
106 }
107
108 /* opens all databases */
109 int
databases_setup(STOCK_DBS * my_stock,const char * program_name,FILE * error_file_pointer)110 databases_setup(STOCK_DBS *my_stock, const char *program_name,
111 FILE *error_file_pointer)
112 {
113 int ret;
114
115 /* Open the vendor database */
116 ret = open_database(&(my_stock->vendor_dbp),
117 my_stock->vendor_db_name,
118 program_name, error_file_pointer,
119 PRIMARY_DB);
120 if (ret != 0)
121 /*
122 * Error reporting is handled in open_database() so just return
123 * the return code.
124 */
125 return (ret);
126
127 /* Open the inventory database */
128 ret = open_database(&(my_stock->inventory_dbp),
129 my_stock->inventory_db_name,
130 program_name, error_file_pointer,
131 PRIMARY_DB);
132 if (ret != 0)
133 /*
134 * Error reporting is handled in open_database() so just return
135 * the return code.
136 */
137 return (ret);
138
139 /*
140 * Open the itemname secondary database. This is used to
141 * index the product names found in the inventory
142 * database.
143 */
144 ret = open_database(&(my_stock->itemname_sdbp),
145 my_stock->itemname_db_name,
146 program_name, error_file_pointer,
147 SECONDARY_DB);
148 if (ret != 0)
149 /*
150 * Error reporting is handled in open_database() so just return
151 * the return code.
152 */
153 return (ret);
154
155 /*
156 * Associate the itemname db with its primary db
157 * (inventory db).
158 */
159 my_stock->inventory_dbp->associate(
160 my_stock->inventory_dbp, /* Primary db */
161 NULL, /* txn id */
162 my_stock->itemname_sdbp, /* Secondary db */
163 get_item_name, /* Secondary key creator */
164 0); /* Flags */
165
166 printf("databases opened successfully\n");
167 return (0);
168 }
169
170 /* Initializes the STOCK_DBS struct.*/
171 void
initialize_stockdbs(STOCK_DBS * my_stock)172 initialize_stockdbs(STOCK_DBS *my_stock)
173 {
174 my_stock->db_home_dir = DEFAULT_HOMEDIR;
175 my_stock->inventory_dbp = NULL;
176 my_stock->vendor_dbp = NULL;
177 my_stock->itemname_sdbp = NULL;
178 my_stock->inventory_db_name = NULL;
179 my_stock->vendor_db_name = NULL;
180 my_stock->itemname_db_name = NULL;
181 }
182
183 /* Identify all the files that will hold our databases. */
184 void
set_db_filenames(STOCK_DBS * my_stock)185 set_db_filenames(STOCK_DBS *my_stock)
186 {
187 size_t size;
188
189 /* Create the Inventory DB file name */
190 size = strlen(my_stock->db_home_dir) + strlen(INVENTORYDB) + 1;
191 my_stock->inventory_db_name = malloc(size);
192 snprintf(my_stock->inventory_db_name, size, "%s%s",
193 my_stock->db_home_dir, INVENTORYDB);
194
195 /* Create the Vendor DB file name */
196 size = strlen(my_stock->db_home_dir) + strlen(VENDORDB) + 1;
197 my_stock->vendor_db_name = malloc(size);
198 snprintf(my_stock->vendor_db_name, size, "%s%s",
199 my_stock->db_home_dir, VENDORDB);
200
201 /* Create the itemname DB file name */
202 size = strlen(my_stock->db_home_dir) + strlen(ITEMNAMEDB) + 1;
203 my_stock->itemname_db_name = malloc(size);
204 snprintf(my_stock->itemname_db_name, size, "%s%s",
205 my_stock->db_home_dir, ITEMNAMEDB);
206
207 }
208
209 /* Closes all the databases and secondary databases. */
210 int
databases_close(STOCK_DBS * my_stock)211 databases_close(STOCK_DBS *my_stock)
212 {
213 int ret;
214 /*
215 * Note that closing a database automatically flushes its cached data
216 * to disk, so no sync is required here.
217 */
218 if (my_stock->itemname_sdbp != NULL) {
219 ret = my_stock->itemname_sdbp->close(my_stock->itemname_sdbp, 0);
220 if (ret != 0)
221 fprintf(stderr, "Itemname database close failed: %s\n",
222 db_strerror(ret));
223 }
224
225 if (my_stock->inventory_dbp != NULL) {
226 ret = my_stock->inventory_dbp->close(my_stock->inventory_dbp, 0);
227 if (ret != 0)
228 fprintf(stderr, "Inventory database close failed: %s\n",
229 db_strerror(ret));
230 }
231
232 if (my_stock->vendor_dbp != NULL) {
233 ret = my_stock->vendor_dbp->close(my_stock->vendor_dbp, 0);
234 if (ret != 0)
235 fprintf(stderr, "Vendor database close failed: %s\n",
236 db_strerror(ret));
237 }
238
239 printf("databases closed.\n");
240 return (0);
241 }
242