1/*- 2 * See the file LICENSE for redistribution information. 3 * 4 * Copyright (c) 2009 Oracle. All rights reserved. 5 * 6 */ 7using System; 8using System.Collections.Generic; 9using System.Text; 10 11namespace BerkeleyDB { 12 /// <summary> 13 /// A class representing configuration parameters for 14 /// <see cref="RecnoDatabase"/> 15 /// </summary> 16 public class RecnoDatabaseConfig : DatabaseConfig { 17 /* Fields for DB->set_flags() */ 18 /// <summary> 19 /// Cause the logical record numbers to be mutable, and change as 20 /// records are added to and deleted from the database. 21 /// </summary> 22 /// <remarks> 23 /// <para> 24 /// Using <see cref="Database.Put"/> or <see cref="Cursor.Put"/> to 25 /// create new records will cause the creation of multiple records if 26 /// the record number is more than one greater than the largest record 27 /// currently in the database. For example, creating record 28, when 28 /// record 25 was previously the last record in the database, will 29 /// create records 26 and 27 as well as 28. Attempts to retrieve records 30 /// that were created in this manner will throw a 31 /// <see cref="KeyEmptyException"/>. 32 /// </para> 33 /// <para> 34 /// If a created record is not at the end of the database, all records 35 /// following the new record will be automatically renumbered upward by 36 /// one. For example, the creation of a new record numbered 8 causes 37 /// records numbered 8 and greater to be renumbered upward by one. If a 38 /// cursor was positioned to record number 8 or greater before the 39 /// insertion, it will be shifted upward one logical record, continuing 40 /// to refer to the same record as it did before. 41 /// </para> 42 /// <para> 43 /// If a deleted record is not at the end of the database, all records 44 /// following the removed record will be automatically renumbered 45 /// downward by one. For example, deleting the record numbered 8 causes 46 /// records numbered 9 and greater to be renumbered downward by one. If 47 /// a cursor was positioned to record number 9 or greater before the 48 /// removal, it will be shifted downward one logical record, continuing 49 /// to refer to the same record as it did before. 50 /// </para> 51 /// <para> 52 /// If a record is deleted, all cursors that were positioned on that 53 /// record prior to the removal will no longer be positioned on a valid 54 /// entry. This includes cursors used to delete an item. For example, if 55 /// a cursor was positioned to record number 8 before the removal of 56 /// that record, subsequent calls to <see cref="Cursor.Refresh"/> 57 /// will return false until the cursor is moved to another record. A 58 /// call to <see cref="Cursor.MoveNext"/> will return the new record 59 /// numbered 8 - which is the record that was numbered 9 prior to the 60 /// delete (if such a record existed). 61 /// </para> 62 /// <para> 63 /// For these reasons, concurrent access to a 64 /// <see cref="RecnoDatabase"/> with this setting specified may be 65 /// largely meaningless, although it is supported. 66 /// </para> 67 /// <para> 68 /// If the database already exists, this setting must be the same as the 69 /// existing database or an exception will be thrown. 70 /// </para> 71 /// </remarks> 72 public bool Renumber; 73 /// <summary> 74 /// If true, any <see cref="BackingFile"/> file will be read in its 75 /// entirety when <see cref="RecnoDatabase.Open"/> is called. If false, 76 /// <see cref="BackingFile"/> may be read lazily. 77 /// </summary> 78 public bool Snapshot; 79 internal new uint flags { 80 get { 81 uint ret = base.flags; 82 ret |= Renumber ? Internal.DbConstants.DB_RENUMBER : 0; 83 ret |= Snapshot ? Internal.DbConstants.DB_SNAPSHOT : 0; 84 return ret; 85 } 86 } 87 88 /// <summary> 89 /// The policy for how to handle database creation. 90 /// </summary> 91 /// <remarks> 92 /// If the database does not already exist and 93 /// <see cref="CreatePolicy.NEVER"/> is set, 94 /// <see cref="RecnoDatabase.Open"/> will fail. 95 /// </remarks> 96 public CreatePolicy Creation; 97 internal new uint openFlags { 98 get { 99 uint flags = base.openFlags; 100 flags |= (uint)Creation; 101 return flags; 102 } 103 } 104 105 /// <summary> 106 /// A function to call after the record number has been selected but 107 /// before the data has been stored into the database. 108 /// </summary> 109 /// <remarks> 110 /// <para> 111 /// When using <see cref="QueueDatabase.Append"/>, it may be useful to 112 /// modify the stored data based on the generated key. If a delegate is 113 /// specified, it will be called after the record number has been 114 /// selected, but before the data has been stored. 115 /// </para> 116 /// </remarks> 117 public AppendRecordDelegate Append; 118 119 internal bool delimiterIsSet; 120 private int delim; 121 /// <summary> 122 /// The delimiting byte used to mark the end of a record in 123 /// <see cref="BackingFile"/>. 124 /// </summary> 125 /// <remarks> 126 /// <para> 127 /// This byte is used for variable length records if 128 /// <see cref="BackingFile"/> is set. If <see cref="BackingFile"/> is 129 /// specified and no delimiting byte was specified, newline characters 130 /// (that is, ASCII 0x0a) are interpreted as end-of-record markers. 131 /// </para> 132 /// <para> 133 /// If the database already exists, this setting will be ignored. 134 /// </para> 135 /// </remarks> 136 public int Delimiter { 137 get { return delim; } 138 set { 139 delimiterIsSet = true; 140 delim = value; 141 } 142 } 143 144 internal bool lengthIsSet; 145 private uint len; 146 /// <summary> 147 /// Specify that the records are fixed-length, not byte-delimited, and 148 /// are of length Length. 149 /// </summary> 150 /// <remarks> 151 /// <para> 152 /// Any records added to the database that are less than Length bytes 153 /// long are automatically padded (see <see cref="PadByte"/> for more 154 /// information). 155 /// </para> 156 /// <para> 157 /// Any attempt to insert records into the database that are greater 158 /// than Length bytes long will cause the call to fail immediately and 159 /// return an error. 160 /// </para> 161 /// <para> 162 /// If the database already exists, this setting will be ignored. 163 /// </para> 164 /// </remarks> 165 public uint Length { 166 get { return len; } 167 set { 168 lengthIsSet = true; 169 len = value; 170 } 171 } 172 173 internal bool padIsSet; 174 private int pad; 175 /// <summary> 176 /// The padding character for short, fixed-length records. 177 /// </summary> 178 /// <remarks> 179 /// <para> 180 /// If no pad character is specified, space characters (that is, ASCII 181 /// 0x20) are used for padding. 182 /// </para> 183 /// <para> 184 /// If the database already exists, this setting will be ignored. 185 /// </para> 186 /// </remarks> 187 public int PadByte { 188 get { return pad; } 189 set { 190 padIsSet = true; 191 pad = value; 192 } 193 } 194 195 /// <summary> 196 /// The underlying source file for the Recno access method. 197 /// </summary> 198 /// <remarks> 199 /// <para> 200 /// The purpose of the source file is to provide fast access and 201 /// modification to databases that are normally stored as flat text 202 /// files. 203 /// </para> 204 /// <para> 205 /// The source parameter specifies an underlying flat text database file 206 /// that is read to initialize a transient record number index. In the 207 /// case of variable length records, the records are separated, as 208 /// specified by <see cref="Delimiter"/>. For example, standard UNIX 209 /// byte stream files can be interpreted as a sequence of variable 210 /// length records separated by newline characters. 211 /// </para> 212 /// <para> 213 /// In addition, when cached data would normally be written back to the 214 /// underlying database file (for example, 215 /// <see cref="BaseDatabase.Close"/> or 216 /// <see cref="BaseDatabase.Sync"/>), the in-memory copy of the 217 /// database will be written back to the source file. 218 /// </para> 219 /// <para> 220 /// By default, the backing source file is read lazily; that is, records 221 /// are not read from the file until they are requested by the 222 /// application. If multiple processes (not threads) are accessing a 223 /// Recno database concurrently, and are either inserting or deleting 224 /// records, the backing source file must be read in its entirety before 225 /// more than a single process accesses the database, and only that 226 /// process should specify the backing source file as part of the 227 /// <see cref="RecnoDatabase.Open"/> call. See <see cref="Snapshot"/> 228 /// for more information. 229 /// </para> 230 /// <para> 231 /// Reading and writing the backing source file specified by source 232 /// cannot be transaction-protected because it involves filesystem 233 /// operations that are not part of the Db transaction methodology. For 234 /// this reason, if a temporary database is used to hold the records, it 235 /// is possible to lose the contents of the source file, for example, if 236 /// the system crashes at the right instant. If a file is used to hold 237 /// the database, normal database recovery on that file can be used to 238 /// prevent information loss, although it is still possible that the 239 /// contents of source will be lost if the system crashes. 240 /// </para> 241 /// <para> 242 /// The source file must already exist (but may be zero-length) when 243 /// <see cref="RecnoDatabase.Open"/> is called. 244 /// </para> 245 /// <para> 246 /// It is not an error to specify a read-only source file when creating 247 /// a database, nor is it an error to modify the resulting database. 248 /// However, any attempt to write the changes to the backing source file 249 /// using either the <see cref="BaseDatabase.Sync"/> or 250 /// <see cref="BaseDatabase.Close"/> methods will fail, of course. 251 /// Use <see cref="BaseDatabase.Close(bool)"/> to stop it from 252 /// attempting to write the changes to the backing file; instead, they 253 /// will be silently discarded. 254 /// </para> 255 /// <para> 256 /// For all of the previous reasons, the source file is generally used 257 /// to specify databases that are read-only for Berkeley DB 258 /// applications; and that are either generated on the fly by software 259 /// tools or modified using a different mechanism � for example, a text 260 /// editor. 261 /// </para> 262 /// <para> 263 /// If the database already exists, BackingFile must be the same as that 264 /// historically used to create the database or corruption can occur. 265 /// </para> 266 /// </remarks> 267 public string BackingFile; 268 269 /// <summary> 270 /// Instantiate a new RecnoDatabaseConfig object 271 /// </summary> 272 public RecnoDatabaseConfig() { 273 Renumber = false; 274 Snapshot = false; 275 Append = null; 276 delimiterIsSet = false; 277 lengthIsSet = false; 278 padIsSet = false; 279 BackingFile = null; 280 Creation = CreatePolicy.NEVER; 281 } 282 283 } 284}