1/*- 2 * See the file LICENSE for redistribution information. 3 * 4 * Copyright (c) 2005-2009 Oracle. All rights reserved. 5 * 6 * $Id$ 7 */ 8 9// File: excxx_example_database_load.cpp 10#include <iostream> 11#include <fstream> 12#include <cstdlib> 13 14#include "MyDb.hpp" 15#include "gettingStartedCommon.hpp" 16 17#ifdef _WIN32 18extern "C" { 19 extern int getopt(int, char * const *, const char *); 20 extern char *optarg; 21} 22#else 23#include <unistd.h> 24#endif 25 26// Forward declarations 27void loadInventoryDB(MyDb &, std::string &); 28void loadVendorDB(MyDb &, std::string &); 29 30using namespace std; 31 32int 33usage() 34{ 35 std::cout << "example_database_load [-b <path to data files>]" 36 << " [-h <database home directory>]" << std::endl; 37 38 std::cout << "Note: If -b -h is specified, then the path must end" 39 << " with your system's path delimiter (/ or \\)" 40 << std::endl; 41 return (-1); 42} 43 44// Loads the contents of vendors.txt and inventory.txt into 45// Berkeley DB databases. 46int 47main (int argc, char *argv[]) 48{ 49 50 char ch, lastChar; 51 52 // Initialize the path to the database files 53 std::string basename("./"); 54 std::string databaseHome("./"); 55 56 // Database names 57 std::string vDbName("vendordb.db"); 58 std::string iDbName("inventorydb.db"); 59 std::string itemSDbName("itemname.sdb"); 60 61 // Parse the command line arguments 62 while ((ch = getopt(argc, argv, "b:h:")) != EOF) 63 switch (ch) { 64 case 'h': 65 databaseHome = optarg; 66 lastChar = databaseHome[databaseHome.size() -1]; 67 if (lastChar != '/' && lastChar != '\\') 68 return (usage()); 69 break; 70 case 'b': 71 basename = optarg; 72 lastChar = basename[basename.size() -1]; 73 if (lastChar != '/' && lastChar != '\\') 74 return (usage()); 75 break; 76 case '?': 77 default: 78 return (usage()); 79 break; 80 } 81 82 // Identify the full name for our input files, which should 83 // also include some path information. 84 std::string inventoryFile = basename + "inventory.txt"; 85 std::string vendorFile = basename + "vendors.txt"; 86 87 try 88 { 89 // Open all databases. 90 MyDb inventoryDB(databaseHome, iDbName); 91 MyDb vendorDB(databaseHome, vDbName); 92 MyDb itemnameSDB(databaseHome, itemSDbName, true); 93 94 // Associate the primary and the secondary 95 inventoryDB.getDb().associate(NULL, 96 &(itemnameSDB.getDb()), 97 get_item_name, 98 0); 99 100 // Load the inventory database 101 loadInventoryDB(inventoryDB, inventoryFile); 102 103 // Load the vendor database 104 loadVendorDB(vendorDB, vendorFile); 105 } catch(DbException &e) { 106 std::cerr << "Error loading databases. " << std::endl; 107 std::cerr << e.what() << std::endl; 108 return (e.get_errno()); 109 } catch(std::exception &e) { 110 std::cerr << "Error loading databases. " << std::endl; 111 std::cerr << e.what() << std::endl; 112 return (-1); 113 } 114 115 // MyDb class constructors will close the databases when they 116 // go out of scope. 117 return (0); 118} // End main 119 120// Used to locate the first pound sign (a field delimiter) 121// in the input string. 122size_t 123getNextPound(std::string &theString, std::string &substring) 124{ 125 size_t pos = theString.find("#"); 126 substring.assign(theString, 0, pos); 127 theString.assign(theString, pos + 1, theString.size()); 128 return (pos); 129} 130 131// Loads the contents of the inventory.txt file into a database 132void 133loadInventoryDB(MyDb &inventoryDB, std::string &inventoryFile) 134{ 135 InventoryData inventoryData; 136 std::string substring; 137 size_t nextPound; 138 139 std::ifstream inFile(inventoryFile.c_str(), std::ios::in); 140 if ( !inFile ) 141 { 142 std::cerr << "Could not open file '" << inventoryFile 143 << "'. Giving up." << std::endl; 144 throw std::exception(); 145 } 146 147 while (!inFile.eof()) 148 { 149 inventoryData.clear(); 150 std::string stringBuf; 151 std::getline(inFile, stringBuf); 152 153 // Now parse the line 154 if (!stringBuf.empty()) 155 { 156 nextPound = getNextPound(stringBuf, substring); 157 inventoryData.setName(substring); 158 159 nextPound = getNextPound(stringBuf, substring); 160 inventoryData.setSKU(substring); 161 162 nextPound = getNextPound(stringBuf, substring); 163 inventoryData.setPrice(strtod(substring.c_str(), 0)); 164 165 nextPound = getNextPound(stringBuf, substring); 166 inventoryData.setQuantity(strtol(substring.c_str(), 0, 10)); 167 168 nextPound = getNextPound(stringBuf, substring); 169 inventoryData.setCategory(substring); 170 171 nextPound = getNextPound(stringBuf, substring); 172 inventoryData.setVendor(substring); 173 174 void *buff = (void *)inventoryData.getSKU().c_str(); 175 size_t size = inventoryData.getSKU().size()+1; 176 Dbt key(buff, (u_int32_t)size); 177 178 buff = inventoryData.getBuffer(); 179 size = inventoryData.getBufferSize(); 180 Dbt data(buff, (u_int32_t)size); 181 182 inventoryDB.getDb().put(NULL, &key, &data, 0); 183 } 184 185 } 186 187 inFile.close(); 188 189} 190 191// Loads the contents of the vendors.txt file into a database 192void 193loadVendorDB(MyDb &vendorDB, std::string &vendorFile) 194{ 195 std::ifstream inFile(vendorFile.c_str(), std::ios::in); 196 if ( !inFile ) 197 { 198 std::cerr << "Could not open file '" << vendorFile 199 << "'. Giving up." << std::endl; 200 throw std::exception(); 201 } 202 203 VENDOR my_vendor; 204 while (!inFile.eof()) 205 { 206 std::string stringBuf; 207 std::getline(inFile, stringBuf); 208 memset(&my_vendor, 0, sizeof(VENDOR)); 209 210 // Scan the line into the structure. 211 // Convenient, but not particularly safe. 212 // In a real program, there would be a lot more 213 // defensive code here. 214 sscanf(stringBuf.c_str(), 215 "%20[^#]#%20[^#]#%20[^#]#%3[^#]#%6[^#]#%13[^#]#%20[^#]#%20[^\n]", 216 my_vendor.name, my_vendor.street, 217 my_vendor.city, my_vendor.state, 218 my_vendor.zipcode, my_vendor.phone_number, 219 my_vendor.sales_rep, my_vendor.sales_rep_phone); 220 221 Dbt key(my_vendor.name, (u_int32_t)strlen(my_vendor.name) + 1); 222 Dbt data(&my_vendor, sizeof(VENDOR)); 223 224 vendorDB.getDb().put(NULL, &key, &data, 0); 225 } 226 227 inFile.close(); 228} 229