Main Page | Class Hierarchy | Data Structures | Directories | File List | Data Fields | Related Pages

example_database_load.c

00001 /*-
00002  * See the file LICENSE for redistribution information.
00003  *
00004  * Copyright (c) 2004-2005
00005  *      Sleepycat Software.  All rights reserved.
00006  */
00007 
00008 #include "gettingstarted_common.h"
00009 
00010 /* Forward declarations */
00011 int usage(void);
00012 int load_vendors_database(STOCK_DBS, char *);
00013 size_t pack_string(char *, char *, size_t);
00014 int load_inventory_database(STOCK_DBS, char *);
00015 
00016 int
00017 usage()
00018 {
00019     fprintf(stderr, "example_database_load [-b <path to data files>]");
00020     fprintf(stderr, " [-h <database_home_directory>]\n");
00021 
00022     fprintf(stderr, "\tNote: Any path specified must end with your");
00023     fprintf(stderr, " system's path delimiter (/ or \\)\n");
00024     return (-1);
00025 }
00026 
00027 /*
00028  * Loads the contents of vendors.txt and inventory.txt into
00029  * Berkeley DB databases. Also causes the itemname secondary
00030  * database to be created and loaded.
00031  */
00032 int
00033 main(int argc, char *argv[])
00034 {
00035     STOCK_DBS my_stock;
00036     int ch, ret;
00037     size_t size;
00038     char *basename, *inventory_file, *vendor_file;
00039 
00040     /* Initialize the STOCK_DBS struct */
00041     initialize_stockdbs(&my_stock);
00042 
00043    /* Initialize the base path. */
00044     basename = "./";
00045 
00046     /* Parse the command line arguments */
00047     while ((ch = getopt(argc, argv, "b:h:")) != EOF)
00048         switch (ch) {
00049         case 'h':
00050             if (optarg[strlen(optarg)-1] != '/' &&
00051                 optarg[strlen(optarg)-1] != '\\')
00052                 return (usage());
00053             my_stock.db_home_dir = optarg;
00054             break;
00055         case 'b':
00056             if (basename[strlen(basename)-1] != '/' &&
00057                 basename[strlen(basename)-1] != '\\')
00058                 return (usage());
00059             basename = optarg;
00060             break;
00061         case '?':
00062         default:
00063             return (usage());
00064         }
00065 
00066     /* Identify the files that will hold our databases */
00067     set_db_filenames(&my_stock);
00068 
00069     /* Find our input files */
00070     size = strlen(basename) + strlen(INVENTORY_FILE) + 1;
00071     inventory_file = malloc(size);
00072     snprintf(inventory_file, size, "%s%s", basename, INVENTORY_FILE);
00073 
00074     size = strlen(basename) + strlen(VENDORS_FILE) + 1;
00075     vendor_file = malloc(size);
00076     snprintf(vendor_file, size, "%s%s", basename, VENDORS_FILE);
00077 
00078     /* Open all databases */
00079     ret = databases_setup(&my_stock, "example_database_load", stderr);
00080     if (ret) {
00081         fprintf(stderr, "Error opening databases\n");
00082         databases_close(&my_stock);
00083         return (ret);
00084     }
00085 
00086     ret = load_vendors_database(my_stock, vendor_file);
00087     if (ret) {
00088         fprintf(stderr, "Error loading vendors database.\n");
00089         databases_close(&my_stock);
00090         return (ret);
00091     }
00092     ret = load_inventory_database(my_stock, inventory_file);
00093     if (ret) {
00094         fprintf(stderr, "Error loading inventory database.\n");
00095         databases_close(&my_stock);
00096         return (ret);
00097     }
00098 
00099     /* close our environment and databases */
00100     databases_close(&my_stock);
00101 
00102     printf("Done loading databases.\n");
00103     return (ret);
00104 }
00105 
00106 /*
00107  * Loads the contents of the vendors.txt file into
00108  * a database.
00109  */
00110 int
00111 load_vendors_database(STOCK_DBS my_stock, char *vendor_file)
00112 {
00113     DBT key, data;
00114     char buf[MAXLINE];
00115     FILE *ifp;
00116     VENDOR my_vendor;
00117 
00118     /* Load the vendors database */
00119     ifp = fopen(vendor_file, "r");
00120     if (ifp == NULL) {
00121         fprintf(stderr, "Error opening file '%s'\n", vendor_file);
00122         return (-1);
00123     }
00124 
00125     while (fgets(buf, MAXLINE, ifp) != NULL) {
00126         /* zero out the structure */
00127         memset(&my_vendor, 0, sizeof(VENDOR));
00128         /* Zero out the DBTs */
00129         memset(&key, 0, sizeof(DBT));
00130         memset(&data, 0, sizeof(DBT));
00131 
00132         /*
00133          * Scan the line into the structure.
00134          * Convenient, but not particularly safe.
00135          * In a real program, there would be a lot more
00136          * defensive code here.
00137          */
00138         sscanf(buf,
00139           "%20[^#]#%20[^#]#%20[^#]#%3[^#]#%6[^#]#%13[^#]#%20[^#]#%20[^\n]",
00140           my_vendor.name, my_vendor.street,
00141           my_vendor.city, my_vendor.state,
00142           my_vendor.zipcode, my_vendor.phone_number,
00143           my_vendor.sales_rep, my_vendor.sales_rep_phone);
00144 
00145         /* Now that we have our structure we can load it into the database. */
00146 
00147         /* Set up the database record's key */
00148         key.data = my_vendor.name;
00149         key.size = (u_int32_t)strlen(my_vendor.name) + 1;
00150 
00151         /* Set up the database record's data */
00152         data.data = &my_vendor;
00153         data.size = sizeof(VENDOR);
00154 
00155         /*
00156          * Note that given the way we built our struct, there's extra
00157          * bytes in it. Essentially we're using fixed-width fields with
00158          * the unused portion of some fields padded with zeros. This
00159          * is the easiest thing to do, but it does result in a bloated
00160          * database. Look at load_inventory_data() for an example of how
00161          * to avoid this.
00162          */
00163 
00164         /* Put the data into the database */
00165         my_stock.vendor_dbp->put(my_stock.vendor_dbp, 0, &key, &data, 0);
00166     } /* end vendors database while loop */
00167 
00168     fclose(ifp);
00169     return (0);
00170 }
00171 
00172 /*
00173  * Simple little convenience function that takes a buffer, a string,
00174  * and an offset and copies that string into the buffer at the
00175  * appropriate location. Used to ensure that all our strings
00176  * are contained in a single contiguous chunk of memory.
00177  */
00178 size_t
00179 pack_string(char *buffer, char *string, size_t start_pos)
00180 {
00181     size_t string_size;
00182 
00183     string_size = strlen(string) + 1;
00184     memcpy(buffer+start_pos, string, string_size);
00185 
00186     return (start_pos + string_size);
00187 }
00188 
00189 /*
00190  * Loads the contents of the inventory.txt file into
00191  * a database. Note that because the itemname
00192  * secondary database is associated to the inventorydb
00193  * (see env_setup() in gettingstarted_common.c), the
00194  * itemname index is automatically created when this
00195  * database is loaded.
00196  */
00197 int
00198 load_inventory_database(STOCK_DBS my_stock, char *inventory_file)
00199 {
00200     DBT key, data;
00201     char buf[MAXLINE];
00202     char databuf[MAXDATABUF];
00203     size_t bufLen, dataLen;
00204     FILE *ifp;
00205 
00206     /*
00207      * Rather than lining everything up nicely in a struct, we're being
00208      * deliberately a bit sloppy here. This function illustrates how to
00209      * store mixed data that might be obtained from various locations
00210      * in your application.
00211      */
00212     float price;
00213     int quantity;
00214     char category[MAXFIELD], name[MAXFIELD];
00215     char vendor[MAXFIELD], sku[MAXFIELD];
00216 
00217     /* Load the inventory database */
00218     ifp = fopen(inventory_file, "r");
00219     if (ifp == NULL) {
00220         fprintf(stderr, "Error opening file '%s'\n", inventory_file);
00221             return (-1);
00222     }
00223 
00224     while (fgets(buf, MAXLINE, ifp) != NULL) {
00225         /*
00226          * Scan the line into the appropriate buffers and variables.
00227          * Convenient, but not particularly safe. In a real
00228          * program, there would be a lot more defensive code here.
00229          */
00230         sscanf(buf,
00231           "%20[^#]#%20[^#]#%f#%i#%20[^#]#%20[^\n]",
00232           name, sku, &price, &quantity, category, vendor);
00233 
00234         /*
00235          * Now pack it into a single contiguous memory location for
00236          * storage.
00237          */
00238         memset(databuf, 0, MAXDATABUF);
00239         bufLen = 0;
00240         dataLen = 0;
00241 
00242         dataLen = sizeof(float);
00243         memcpy(databuf, &price, dataLen);
00244         bufLen += dataLen;
00245 
00246         dataLen = sizeof(int);
00247         memcpy(databuf + bufLen, &quantity, dataLen);
00248         bufLen += dataLen;
00249 
00250         bufLen = pack_string(databuf, name, bufLen);
00251         bufLen = pack_string(databuf, sku, bufLen);
00252         bufLen = pack_string(databuf, category, bufLen);
00253         bufLen = pack_string(databuf, vendor, bufLen);
00254 
00255         /* Zero out the DBTs */
00256         memset(&key, 0, sizeof(DBT));
00257         memset(&data, 0, sizeof(DBT));
00258 
00259         /* The key is the item's SKU */
00260         key.data = sku;
00261         key.size = (u_int32_t)strlen(sku) + 1;
00262 
00263         /* The data is the information that we packed into databuf. */
00264         data.data = databuf;
00265         data.size = (u_int32_t)bufLen;
00266 
00267         /* Put the data into the database */
00268         my_stock.vendor_dbp->put(my_stock.inventory_dbp, 0, &key, &data, 0);
00269     } /* end vendors database while loop */
00270 
00271     /* Cleanup */
00272     fclose(ifp);
00273 
00274     return (0);
00275 }

Generated on Sun Dec 25 12:14:25 2005 for Berkeley DB 4.4.16 by  doxygen 1.4.2