1/*- 2 * See the file LICENSE for redistribution information. 3 * 4 * Copyright (c) 1997,2008 Oracle. All rights reserved. 5 * 6 * $Id: BtRecExample.java,v 12.8 2008/01/08 20:58:32 bostic Exp $ 7 */ 8 9 10package db; 11 12import com.sleepycat.db.*; 13import java.io.BufferedReader; 14import java.io.File; 15import java.io.FileNotFoundException; 16import java.io.FileReader; 17import java.io.InputStreamReader; 18import java.io.IOException; 19import java.io.PrintStream; 20 21public class BtRecExample { 22 static final String progname = "BtRecExample"; // Program name. 23 static final String database = "access.db"; 24 static final String wordlist = "../test/wordlist"; 25 26 BtRecExample(BufferedReader reader) 27 throws DatabaseException, IOException, FileNotFoundException { 28 29 OperationStatus status; 30 31 // Remove the previous database. 32 File f = new File(database); 33 f.delete(); 34 35 DatabaseConfig config = new DatabaseConfig(); 36 37 config.setErrorStream(System.err); 38 config.setErrorPrefix(progname); 39 config.setPageSize(1024); // 1K page sizes. 40 41 config.setBtreeRecordNumbers(true); 42 config.setType(DatabaseType.BTREE); 43 config.setAllowCreate(true); 44 db = new Database(database, null, config); 45 46 // 47 // Insert records into the database, where the key is the word 48 // preceded by its record number, and the data is the same, but 49 // in reverse order. 50 // 51 52 for (int cnt = 1; cnt <= 1000; ++cnt) { 53 String numstr = String.valueOf(cnt); 54 while (numstr.length() < 4) 55 numstr = "0" + numstr; 56 String buf = numstr + '_' + reader.readLine(); 57 StringBuffer rbuf = new StringBuffer(buf).reverse(); 58 59 StringEntry key = new StringEntry(buf); 60 StringEntry data = new StringEntry(rbuf.toString()); 61 62 status = db.putNoOverwrite(null, key, data); 63 if (status != OperationStatus.SUCCESS && 64 status!= OperationStatus.KEYEXIST) 65 throw new DatabaseException("Database.put failed " + status); 66 } 67 } 68 69 void run() throws DatabaseException { 70 int recno; 71 OperationStatus status; 72 73 // Acquire a cursor for the database. 74 cursor = db.openCursor(null, null); 75 76 // 77 // Prompt the user for a record number, then retrieve and display 78 // that record. 79 // 80 InputStreamReader reader = new InputStreamReader(System.in); 81 82 for (;;) { 83 // Get a record number. 84 String line = askForLine(reader, System.out, "recno #> "); 85 if (line == null) 86 break; 87 88 try { 89 recno = Integer.parseInt(line); 90 } catch (NumberFormatException nfe) { 91 System.err.println("Bad record number: " + nfe); 92 continue; 93 } 94 95 // 96 // Start with a fresh key each time, the db.get() routine returns 97 // the key and data pair, not just the key! 98 // 99 RecnoStringEntry key = new RecnoStringEntry(recno, 100); 100 RecnoStringEntry data = new RecnoStringEntry(100); 101 102 status = cursor.getSearchRecordNumber(key, data, null); 103 if (status != OperationStatus.SUCCESS) 104 throw new DatabaseException("Cursor.setRecno failed: " + status); 105 106 // Display the key and data. 107 show("k/d\t", key, data); 108 109 // Move the cursor a record forward. 110 status = cursor.getNext(key, data, null); 111 if (status != OperationStatus.SUCCESS) 112 throw new DatabaseException("Cursor.getNext failed: " + status); 113 114 // Display the key and data. 115 show("next\t", key, data); 116 117 RecnoStringEntry datano = new RecnoStringEntry(100); 118 119 // 120 // Retrieve the record number for the following record into 121 // local memory. 122 // 123 status = cursor.getRecordNumber(datano, null); 124 if (status != OperationStatus.SUCCESS && 125 status != OperationStatus.NOTFOUND && 126 status != OperationStatus.KEYEMPTY) 127 throw new DatabaseException("Cursor.get failed: " + status); 128 else { 129 recno = datano.getRecordNumber(); 130 System.out.println("retrieved recno: " + recno); 131 } 132 } 133 134 cursor.close(); 135 cursor = null; 136 } 137 138 // 139 // Print out the number of records in the database. 140 // 141 void stats() throws DatabaseException { 142 BtreeStats stats; 143 144 stats = (BtreeStats)db.getStats(null, null); 145 System.out.println(progname + ": database contains " + 146 stats.getNumData() + " records"); 147 } 148 149 void show(String msg, RecnoStringEntry key, RecnoStringEntry data) 150 throws DatabaseException { 151 152 System.out.println(msg + key.getString() + ": " + data.getString()); 153 } 154 155 public void shutdown() throws DatabaseException { 156 if (cursor != null) { 157 cursor.close(); 158 cursor = null; 159 } 160 if (db != null) { 161 db.close(); 162 db = null; 163 } 164 } 165 166 public static void main(String[] argv) { 167 try { 168 // Open the word database. 169 FileReader freader = new FileReader(wordlist); 170 171 BtRecExample app = new BtRecExample(new BufferedReader(freader)); 172 173 // Close the word database. 174 freader.close(); 175 freader = null; 176 177 app.stats(); 178 app.run(); 179 } catch (FileNotFoundException fnfe) { 180 System.err.println(progname + ": unexpected open error " + fnfe); 181 System.exit (1); 182 } catch (IOException ioe) { 183 System.err.println(progname + ": open " + wordlist + ": " + ioe); 184 System.exit (1); 185 } catch (DatabaseException dbe) { 186 System.err.println("Exception: " + dbe); 187 System.exit(dbe.getErrno()); 188 } 189 190 System.exit(0); 191 } 192 193 // Prompts for a line, and keeps prompting until a non blank 194 // line is returned. Returns null on error. 195 // 196 public static String askForLine(InputStreamReader reader, 197 PrintStream out, String prompt) { 198 String result = ""; 199 while (result != null && result.length() == 0) { 200 out.print(prompt); 201 out.flush(); 202 result = getLine(reader); 203 } 204 return result; 205 } 206 207 // Not terribly efficient, but does the job. 208 // Works for reading a line from stdin or a file. 209 // Returns null on EOF. If EOF appears in the middle 210 // of a line, returns that line, then null on next call. 211 // 212 public static String getLine(InputStreamReader reader) { 213 StringBuffer b = new StringBuffer(); 214 int c; 215 try { 216 while ((c = reader.read()) != -1 && c != '\n') { 217 if (c != '\r') 218 b.append((char)c); 219 } 220 } catch (IOException ioe) { 221 c = -1; 222 } 223 224 if (c == -1 && b.length() == 0) 225 return null; 226 else 227 return b.toString(); 228 } 229 230 private Cursor cursor; 231 private Database db; 232 233 // Here's an example of how you can extend DatabaseEntry in a 234 // straightforward way to allow easy storage/retrieval of strings. 235 // We've declared it as a static inner class, but it need not be. 236 // 237 static class StringEntry extends DatabaseEntry { 238 StringEntry() {} 239 240 StringEntry(String value) { 241 setString(value); 242 } 243 244 void setString(String value) { 245 byte[] data = value.getBytes(); 246 setData(data); 247 setSize(data.length); 248 } 249 250 String getString() { 251 return new String(getData(), 0, getSize()); 252 } 253 } 254 255 // Here's an example of how you can extend DatabaseEntry to store 256 // (potentially) both recno's and strings in the same structure. 257 // 258 static class RecnoStringEntry extends DatabaseEntry { 259 RecnoStringEntry(int maxsize) { 260 this(0, maxsize); // let other constructor do most of the work 261 } 262 263 RecnoStringEntry(int value, int maxsize) { 264 arr = new byte[maxsize]; 265 setData(arr); // use our local array for data 266 setUserBuffer(maxsize, true); 267 setRecordNumber(value); 268 } 269 270 RecnoStringEntry(String value) { 271 byte[] data = value.getBytes(); 272 setData(data); // use our local array for data 273 setUserBuffer(data.length, true); 274 } 275 276 void setString(String value) { 277 byte[] data = value.getBytes(); 278 setData(data); 279 setSize(data.length); 280 } 281 282 String getString() { 283 return new String(getData(), getOffset(), getSize()); 284 } 285 286 byte[] arr; 287 } 288} 289