1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
|
/*-
* See the file LICENSE for redistribution information.
*
* Copyright (c) 2009, 2015 Oracle and/or its affiliates. All rights reserved.
*
*/
using System;
using System.Collections.Generic;
using System.Text;
using BerkeleyDB.Internal;
namespace BerkeleyDB {
/// <summary>
/// A class that provides an arbitrary number of persistent objects that
/// return an increasing or decreasing sequence of integers.
/// </summary>
public class Sequence : IDisposable {
private DB_SEQUENCE seq;
private bool isOpen;
/// <summary>
/// Instantiate a new Sequence object.
/// </summary>
/// <param name="cfg">Configuration parameters for the Sequence</param>
public Sequence(SequenceConfig cfg) : this(cfg, null) { }
/// <summary>
/// Instantiate a new Sequence object.
/// </summary>
/// <remarks>
/// If <paramref name="txn"/> is null and the operation occurs in a
/// transactional database, the operation will be implicitly transaction
/// protected.
/// </remarks>
/// <param name="cfg">Configuration parameters for the Sequence</param>
/// <param name="txn">
/// If the operation is part of an application-specified transaction,
/// <paramref name="txn"/> is a Transaction object returned from
/// <see cref="DatabaseEnvironment.BeginTransaction"/>; if
/// the operation is part of a Berkeley DB Concurrent Data Store group,
/// <paramref name="txn"/> is a handle returned from
/// <see cref="DatabaseEnvironment.BeginCDSGroup"/>; otherwise null.
/// </param>
public Sequence(SequenceConfig cfg, Transaction txn) {
seq = new DB_SEQUENCE(cfg.BackingDatabase.db, 0);
if (cfg.initialValIsSet)
seq.initial_value(cfg.InitialValue);
seq.set_flags(cfg.flags);
if (cfg.rangeIsSet)
seq.set_range(cfg.Min, cfg.Max);
if (cfg.cacheSzIsSet)
seq.set_cachesize(cfg.CacheSize);
seq.open(Transaction.getDB_TXN(txn),
cfg.key, cfg.openFlags);
isOpen = true;
}
/// <summary>
/// Close the sequence handle. Any unused cached values are lost.
/// </summary>
public void Close() {
isOpen = false;
seq.close(0);
}
/// <summary>
/// Return the next available element in the sequence and change the
/// sequence value by <paramref name="Delta"/>.
/// </summary>
/// <overloads>
/// <para>
/// If there are enough cached values in the sequence handle then they
/// will be returned. Otherwise the next value will be fetched from the
/// database and incremented (decremented) by enough to cover the delta
/// and the next batch of cached values.
/// </para>
/// <para>
/// By default, sequence ranges do not wrap; to cause the sequence to
/// wrap around the beginning or end of its range, set
/// <see cref="SequenceConfig.Wrap"/> to true.
/// </para>
/// </overloads>
/// <param name="Delta">
/// The amount by which to increment the sequence value. Must be
/// greater than 0.
/// </param>
/// <returns>The next available element in the sequence.</returns>
public Int64 Get(uint Delta) {
return Get(Delta, false, null);
}
/// <summary>
/// Return the next available element in the sequence and change the
/// sequence value by <paramref name="Delta"/>.
/// </summary>
/// <param name="Delta">
/// The amount by which to increment the sequence value. Must be
/// greater than 0.
/// </param>
/// <param name="NoSync">
/// If true, and if the operation is implicitly transaction protected,
/// do not synchronously flush the log when the transaction commits.
/// </param>
/// <returns>The next available element in the sequence.</returns>
public Int64 Get(uint Delta, bool NoSync) {
return Get(Delta, NoSync, null);
}
/// <summary>
/// Return the next available element in the sequence and change the
/// sequence value by <paramref name="Delta"/>.
/// </summary>
/// <param name="Delta">
/// The amount by which to increment the sequence value. Must be
/// greater than 0.
/// </param>
/// <param name="txn">
/// If the operation is part of an application-specified transaction,
/// <paramref name="txn"/> is a Transaction object returned from
/// <see cref="DatabaseEnvironment.BeginTransaction"/>; if
/// the operation is part of a Berkeley DB Concurrent Data Store group,
/// <paramref name="txn"/> is a handle returned from
/// <see cref="DatabaseEnvironment.BeginCDSGroup"/>; otherwise null.
/// Must be null if the sequence was opened with a non-zero cache size.
/// </param>
/// <returns>The next available element in the sequence.</returns>
public Int64 Get(uint Delta, Transaction txn) {
return Get(Delta, false, txn);
}
private Int64 Get(uint Delta, bool NoSync, Transaction txn) {
Int64 ret = DbConstants.DB_AUTO_COMMIT;
uint flags = NoSync ? DbConstants.DB_TXN_NOSYNC : 0;
seq.get(Transaction.getDB_TXN(txn), Delta, ref ret, flags);
return ret;
}
/// <summary>
/// The database used by the sequence.
/// </summary>
public Database BackingDatabase {
get { return Database.fromDB(seq.get_db()); }
}
/// <summary>
/// The key for the sequence.
/// </summary>
public DatabaseEntry Key {
get {
DatabaseEntry ret = new DatabaseEntry();
seq.get_key(ret);
return ret;
}
}
/// <summary>
/// Print diagnostic information.
/// </summary>
public void PrintStats() {
PrintStats(false);
}
/// <summary>
/// Print diagnostic information.
/// </summary>
/// <overloads>
/// The diagnostic information is described by
/// <see cref="SequenceStats"/>.
/// </overloads>
/// <param name="ClearStats">
/// If true, reset statistics after printing.
/// </param>
public void PrintStats(bool ClearStats) {
uint flags = 0;
flags |= ClearStats ? DbConstants.DB_STAT_CLEAR : 0;
seq.stat_print(flags);
}
/// <summary>
/// Remove the sequence from the database.
/// </summary>
public void Remove() {
Remove(false, null);
}
/// <summary>
/// Remove the sequence from the database.
/// </summary>
/// <param name="NoSync">
/// If true, and if the operation is implicitly transaction protected,
/// do not synchronously flush the log when the transaction commits.
/// </param>
public void Remove(bool NoSync) {
Remove(NoSync, null);
}
/// <summary>
/// Remove the sequence from the database.
/// </summary>
/// <param name="txn">
/// If the operation is part of an application-specified transaction,
/// <paramref name="txn"/> is a Transaction object returned from
/// <see cref="DatabaseEnvironment.BeginTransaction"/>; if
/// the operation is part of a Berkeley DB Concurrent Data Store group,
/// <paramref name="txn"/> is a handle returned from
/// <see cref="DatabaseEnvironment.BeginCDSGroup"/>; otherwise null.
/// </param>
public void Remove(Transaction txn) {
Remove(false, txn);
}
private void Remove(bool NoSync, Transaction txn) {
uint flags = NoSync ? DbConstants.DB_TXN_NOSYNC : 0;
isOpen = false;
seq.remove(Transaction.getDB_TXN(txn), flags);
}
/// <summary>
/// Return statistical information for this sequence.
/// </summary>
/// <returns>Statistical information for this sequence.</returns>
public SequenceStats Stats() {
return Stats(false);
}
/// <summary>
/// Return statistical information for this sequence.
/// </summary>
/// <overloads>
/// <para>
/// In the presence of multiple threads or processes accessing an active
/// sequence, the information returned by DB_SEQUENCE->stat() may be
/// out-of-date.
/// </para>
/// <para>
/// The DB_SEQUENCE->stat() method cannot be transaction-protected. For
/// this reason, it should be called in a thread of control that has no
/// open cursors or active transactions.
/// </para>
/// </overloads>
/// <param name="clear">If true, reset statistics.</param>
/// <returns>Statistical information for this sequence.</returns>
public SequenceStats Stats(bool clear) {
uint flags = 0;
flags |= clear ? DbConstants.DB_STAT_CLEAR : 0;
SequenceStatStruct st = seq.stat(flags);
return new SequenceStats(st);
}
/// <summary>
/// Release the resources held by this object, and close the sequence if
/// it is still open.
/// </summary>
public void Dispose() {
if (isOpen)
seq.close(0);
seq.Dispose();
GC.SuppressFinalize(this);
}
/// <summary>
/// The current cache size.
/// </summary>
public uint Cachesize {
get {
uint ret = 0;
seq.get_cachesize(ref ret);
return ret;
}
}
/// <summary>
/// The minimum value in the sequence.
/// </summary>
public Int64 Min {
get {
Int64 ret = 0;
Int64 tmp = 0;
seq.get_range(ref ret, ref tmp);
return ret;
}
}
/// <summary>
/// The maximum value in the sequence.
/// </summary>
public Int64 Max {
get {
Int64 ret = 0;
Int64 tmp = 0;
seq.get_range(ref tmp, ref ret);
return ret;
}
}
/// <summary>
/// If true, the sequence should wrap around when it is incremented
/// (decremented) past the specified maximum (minimum) value.
/// </summary>
public bool Wrap {
get {
uint flags = 0;
seq.get_flags(ref flags);
return (flags & DbConstants.DB_SEQ_WRAP) != 0;
}
}
/// <summary>
/// If true, the sequence is incremented. This is the default.
/// </summary>
public bool Increment {
get {
uint flags = 0;
seq.get_flags(ref flags);
return (flags & DbConstants.DB_SEQ_INC) != 0;
}
}
/// <summary>
/// If true, the sequence is decremented.
/// </summary>
public bool Decrement {
get {
uint flags = 0;
seq.get_flags(ref flags);
return (flags & DbConstants.DB_SEQ_DEC) != 0;
}
}
}
}
|