1/*- 2 * See the file LICENSE for redistribution information. 3 * 4 * Copyright (c) 2004,2008 Oracle. All rights reserved. 5 */ 6 7#include "gettingstarted_common.h" 8 9/* Forward declarations */ 10int usage(void); 11char *show_inventory_item(void *); 12int show_all_records(STOCK_DBS *); 13int show_records(STOCK_DBS *, char *); 14int show_vendor_record(char *, DB *); 15 16int 17usage() 18{ 19 fprintf(stderr, "example_database_read [-i <item name>]"); 20 fprintf(stderr, " [-h <database home>]\n"); 21 22 fprintf(stderr, 23 "\tNote: Any path specified to the -h parameter must end\n"); 24 fprintf(stderr, " with your system's path delimiter (/ or \\)\n"); 25 return (-1); 26} 27 28/* 29 * Searches for a inventory item based on that item's name. The search is 30 * performed using the item name secondary database. Displays all 31 * inventory items that use the specified name, as well as the vendor 32 * associated with that inventory item. 33 * 34 * If no item name is provided, then all inventory items are displayed. 35 */ 36int 37main(int argc, char *argv[]) 38{ 39 STOCK_DBS my_stock; 40 int ch, ret; 41 char *itemname; 42 43 /* Initialize the STOCK_DBS struct */ 44 initialize_stockdbs(&my_stock); 45 46 /* Parse the command line arguments */ 47 itemname = NULL; 48 while ((ch = getopt(argc, argv, "h:i:?")) != EOF) 49 switch (ch) { 50 case 'h': 51 if (optarg[strlen(optarg)-1] != '/' && 52 optarg[strlen(optarg)-1] != '\\') 53 return (usage()); 54 my_stock.db_home_dir = optarg; 55 break; 56 case 'i': 57 itemname = optarg; 58 break; 59 case '?': 60 default: 61 return (usage()); 62 } 63 64 /* Identify the files that hold our databases */ 65 set_db_filenames(&my_stock); 66 67 /* Open all databases */ 68 ret = databases_setup(&my_stock, "example_database_read", stderr); 69 if (ret != 0) { 70 fprintf(stderr, "Error opening databases\n"); 71 databases_close(&my_stock); 72 return (ret); 73 } 74 75 if (itemname == NULL) 76 ret = show_all_records(&my_stock); 77 else 78 ret = show_records(&my_stock, itemname); 79 80 /* close our databases */ 81 databases_close(&my_stock); 82 return (ret); 83} 84 85int show_all_records(STOCK_DBS *my_stock) 86{ 87 DBC *inventory_cursorp; 88 DBT key, data; 89 char *the_vendor; 90 int exit_value, ret; 91 92 /* Initialize our DBTs. */ 93 memset(&key, 0, sizeof(DBT)); 94 memset(&data, 0, sizeof(DBT)); 95 96 /* Get a cursor to the inventory db */ 97 my_stock->inventory_dbp->cursor(my_stock->inventory_dbp, NULL, 98 &inventory_cursorp, 0); 99 100 /* 101 * Iterate over the inventory database, from the first record 102 * to the last, displaying each in turn. 103 */ 104 exit_value = 0; 105 while ((ret = 106 inventory_cursorp->get(inventory_cursorp, &key, &data, DB_NEXT)) == 0) 107 { 108 the_vendor = show_inventory_item(data.data); 109 ret = show_vendor_record(the_vendor, my_stock->vendor_dbp); 110 if (ret) { 111 exit_value = ret; 112 break; 113 } 114 } 115 116 /* Close the cursor */ 117 inventory_cursorp->close(inventory_cursorp); 118 return (exit_value); 119} 120 121/* 122 * Search for an inventory item given its name (using the inventory item 123 * secondary database) and display that record and any duplicates that may 124 * exist. 125 */ 126int 127show_records(STOCK_DBS *my_stock, char *itemname) 128{ 129 DBC *itemname_cursorp; 130 DBT key, data; 131 char *the_vendor; 132 int ret, exit_value; 133 134 /* Initialize our DBTs. */ 135 memset(&key, 0, sizeof(DBT)); 136 memset(&data, 0, sizeof(DBT)); 137 138 /* Get a cursor to the itemname db */ 139 my_stock->itemname_sdbp->cursor(my_stock->itemname_sdbp, NULL, 140 &itemname_cursorp, 0); 141 142 /* 143 * Get the search key. This is the name on the inventory 144 * record that we want to examine. 145 */ 146 key.data = itemname; 147 key.size = (u_int32_t)strlen(itemname) + 1; 148 149 /* 150 * Position our cursor to the first record in the secondary 151 * database that has the appropriate key. 152 */ 153 exit_value = 0; 154 ret = itemname_cursorp->get(itemname_cursorp, &key, &data, DB_SET); 155 if (!ret) { 156 do { 157 /* 158 * Show the inventory record and the vendor responsible 159 * for this inventory item. 160 */ 161 the_vendor = show_inventory_item(data.data); 162 ret = show_vendor_record(the_vendor, my_stock->vendor_dbp); 163 if (ret) { 164 exit_value = ret; 165 break; 166 } 167 /* 168 * Our secondary allows duplicates, so we need to loop over 169 * the next duplicate records and show them all. This is done 170 * because an inventory item's name is not a unique value. 171 */ 172 } while (itemname_cursorp->get(itemname_cursorp, &key, &data, 173 DB_NEXT_DUP) == 0); 174 } else { 175 printf("No records found for '%s'\n", itemname); 176 } 177 178 /* Close the cursor */ 179 itemname_cursorp->close(itemname_cursorp); 180 181 return (exit_value); 182} 183 184/* 185 * Shows an inventory item. How we retrieve the inventory 186 * item values from the provided buffer is strictly dependent 187 * on the order that those items were originally stored in the 188 * DBT. See load_inventory_database in example_database_load 189 * for how this was done. 190 */ 191char * 192show_inventory_item(void *vBuf) 193{ 194 float price; 195 int quantity; 196 size_t buf_pos; 197 char *category, *name, *sku, *vendor_name; 198 char *buf = (char *)vBuf; 199 200 price = *((float *)buf); 201 buf_pos = sizeof(float); 202 203 quantity = *((int *)(buf + buf_pos)); 204 buf_pos += sizeof(int); 205 206 name = buf + buf_pos; 207 buf_pos += strlen(name) + 1; 208 209 sku = buf + buf_pos; 210 buf_pos += strlen(sku) + 1; 211 212 category = buf + buf_pos; 213 buf_pos += strlen(category) + 1; 214 215 vendor_name = buf + buf_pos; 216 217 printf("name: %s\n", name); 218 printf("\tSKU: %s\n", sku); 219 printf("\tCategory: %s\n", category); 220 printf("\tPrice: %.2f\n", price); 221 printf("\tQuantity: %i\n", quantity); 222 printf("\tVendor:\n"); 223 224 return (vendor_name); 225} 226 227/* 228 * Shows a vendor record. Each vendor record is an instance of 229 * a vendor structure. See load_vendor_database() in 230 * example_database_load for how this structure was originally 231 * put into the database. 232 */ 233int 234show_vendor_record(char *vendor_name, DB *vendor_dbp) 235{ 236 DBT key, data; 237 VENDOR my_vendor; 238 int ret; 239 240 /* Zero our DBTs */ 241 memset(&key, 0, sizeof(DBT)); 242 memset(&data, 0, sizeof(DBT)); 243 244 /* Set the search key to the vendor's name */ 245 key.data = vendor_name; 246 key.size = (u_int32_t)strlen(vendor_name) + 1; 247 248 /* 249 * Make sure we use the memory we set aside for the VENDOR 250 * structure rather than the memory that DB allocates. 251 * Some systems may require structures to be aligned in memory 252 * in a specific way, and DB may not get it right. 253 */ 254 255 data.data = &my_vendor; 256 data.ulen = sizeof(VENDOR); 257 data.flags = DB_DBT_USERMEM; 258 259 /* Get the record */ 260 ret = vendor_dbp->get(vendor_dbp, NULL, &key, &data, 0); 261 if (ret != 0) { 262 vendor_dbp->err(vendor_dbp, ret, "Error searching for vendor: '%s'", 263 vendor_name); 264 return (ret); 265 } else { 266 printf("\t\t%s\n", my_vendor.name); 267 printf("\t\t%s\n", my_vendor.street); 268 printf("\t\t%s, %s\n", my_vendor.city, my_vendor.state); 269 printf("\t\t%s\n\n", my_vendor.zipcode); 270 printf("\t\t%s\n\n", my_vendor.phone_number); 271 printf("\t\tContact: %s\n", my_vendor.sales_rep); 272 printf("\t\t%s\n", my_vendor.sales_rep_phone); 273 } 274 return (0); 275} 276