1/*-
2 * See the file LICENSE for redistribution information.
3 *
4 * Copyright (c) 2002,2008 Oracle.  All rights reserved.
5 *
6 * $Id: TestStore.java,v 12.8 2008/02/07 17:12:31 mark Exp $
7 */
8
9package com.sleepycat.collections.test;
10
11import java.io.IOException;
12import java.util.ArrayList;
13import java.util.List;
14
15import com.sleepycat.bind.EntityBinding;
16import com.sleepycat.bind.EntryBinding;
17import com.sleepycat.bind.RecordNumberBinding;
18import com.sleepycat.collections.CurrentTransaction;
19import com.sleepycat.compat.DbCompat;
20import com.sleepycat.db.Database;
21import com.sleepycat.db.DatabaseException;
22import com.sleepycat.db.Environment;
23import com.sleepycat.db.SecondaryConfig;
24
25/**
26 * @author Mark Hayes
27 */
28class TestStore {
29
30    static final TestKeyCreator BYTE_EXTRACTOR = new TestKeyCreator(false);
31    static final TestKeyCreator RECNO_EXTRACTOR = new TestKeyCreator(true);
32    static final EntryBinding VALUE_BINDING = new TestDataBinding();
33    static final EntryBinding BYTE_KEY_BINDING = VALUE_BINDING;
34    static final EntryBinding RECNO_KEY_BINDING = new RecordNumberBinding();
35    static final EntityBinding BYTE_ENTITY_BINDING =
36            new TestEntityBinding(false);
37    static final EntityBinding RECNO_ENTITY_BINDING =
38            new TestEntityBinding(true);
39    static final TestKeyAssigner BYTE_KEY_ASSIGNER =
40            new TestKeyAssigner(false);
41    static final TestKeyAssigner RECNO_KEY_ASSIGNER =
42            new TestKeyAssigner(true);
43
44    static final TestStore BTREE_UNIQ;
45    static final TestStore BTREE_DUP;
46    static final TestStore BTREE_DUPSORT;
47    static final TestStore BTREE_RECNUM;
48    static final TestStore HASH_UNIQ;
49    static final TestStore HASH_DUP;
50    static final TestStore HASH_DUPSORT;
51    static final TestStore QUEUE;
52    static final TestStore RECNO;
53    static final TestStore RECNO_RENUM;
54
55    static final TestStore[] ALL;
56    static {
57        List list = new ArrayList();
58        SecondaryConfig config;
59
60        config = new SecondaryConfig();
61        DbCompat.setTypeBtree(config);
62        BTREE_UNIQ = new TestStore("btree-uniq", config);
63        BTREE_UNIQ.indexOf = BTREE_UNIQ;
64        list.add(BTREE_UNIQ);
65
66        if (DbCompat.INSERTION_ORDERED_DUPLICATES) {
67            config = new SecondaryConfig();
68            DbCompat.setTypeBtree(config);
69            DbCompat.setUnsortedDuplicates(config, true);
70            BTREE_DUP = new TestStore("btree-dup", config);
71            BTREE_DUP.indexOf = null; // indexes must use sorted dups
72            list.add(BTREE_DUP);
73        } else {
74            BTREE_DUP = null;
75        }
76
77        config = new SecondaryConfig();
78        DbCompat.setTypeBtree(config);
79        DbCompat.setSortedDuplicates(config, true);
80        BTREE_DUPSORT = new TestStore("btree-dupsort", config);
81        BTREE_DUPSORT.indexOf = BTREE_UNIQ;
82        list.add(BTREE_DUPSORT);
83
84        if (DbCompat.BTREE_RECNUM_METHOD) {
85            config = new SecondaryConfig();
86            DbCompat.setTypeBtree(config);
87            DbCompat.setBtreeRecordNumbers(config, true);
88            BTREE_RECNUM = new TestStore("btree-recnum", config);
89            BTREE_RECNUM.indexOf = BTREE_RECNUM;
90            list.add(BTREE_RECNUM);
91        } else {
92            BTREE_RECNUM = null;
93        }
94
95        if (DbCompat.HASH_METHOD) {
96            config = new SecondaryConfig();
97            DbCompat.setTypeHash(config);
98            HASH_UNIQ = new TestStore("hash-uniq", config);
99            HASH_UNIQ.indexOf = HASH_UNIQ;
100            list.add(HASH_UNIQ);
101
102            if (DbCompat.INSERTION_ORDERED_DUPLICATES) {
103                config = new SecondaryConfig();
104                DbCompat.setTypeHash(config);
105                DbCompat.setUnsortedDuplicates(config, true);
106                HASH_DUP = new TestStore("hash-dup", config);
107                HASH_DUP.indexOf = null; // indexes must use sorted dups
108                list.add(HASH_DUP);
109            } else {
110                HASH_DUP = null;
111            }
112
113            config = new SecondaryConfig();
114            DbCompat.setTypeHash(config);
115            DbCompat.setSortedDuplicates(config, true);
116            HASH_DUPSORT = new TestStore("hash-dupsort", config);
117            HASH_DUPSORT.indexOf = HASH_UNIQ;
118            list.add(HASH_DUPSORT);
119        } else {
120            HASH_UNIQ = null;
121            HASH_DUP = null;
122            HASH_DUPSORT = null;
123        }
124
125        if (DbCompat.QUEUE_METHOD) {
126            config = new SecondaryConfig();
127            DbCompat.setTypeQueue(config);
128            QUEUE = new TestStore("queue", config);
129            QUEUE.indexOf = QUEUE;
130            list.add(QUEUE);
131        } else {
132            QUEUE = null;
133        }
134
135        if (DbCompat.RECNO_METHOD) {
136            config = new SecondaryConfig();
137            DbCompat.setTypeRecno(config);
138            RECNO = new TestStore("recno", config);
139            RECNO.indexOf = RECNO;
140            list.add(RECNO);
141
142            config = new SecondaryConfig();
143            DbCompat.setTypeRecno(config);
144            DbCompat.setRenumbering(config, true);
145            RECNO_RENUM = new TestStore("recno-renum", config);
146            RECNO_RENUM.indexOf = null; // indexes must have stable keys
147            list.add(RECNO_RENUM);
148        } else {
149            RECNO = null;
150            RECNO_RENUM = null;
151        }
152
153        ALL = new TestStore[list.size()];
154        list.toArray(ALL);
155    }
156
157    private String name;
158    private SecondaryConfig config;
159    private TestStore indexOf;
160    private boolean isRecNumFormat;
161
162    private TestStore(String name, SecondaryConfig config) {
163
164        this.name = name;
165        this.config = config;
166
167        isRecNumFormat = isQueueOrRecno() ||
168                            (DbCompat.isTypeBtree(config) &&
169                             DbCompat.getBtreeRecordNumbers(config));
170    }
171
172    EntryBinding getValueBinding() {
173
174        return VALUE_BINDING;
175    }
176
177    EntryBinding getKeyBinding() {
178
179        return isRecNumFormat ? RECNO_KEY_BINDING : BYTE_KEY_BINDING;
180    }
181
182    EntityBinding getEntityBinding() {
183
184        return isRecNumFormat ? RECNO_ENTITY_BINDING : BYTE_ENTITY_BINDING;
185    }
186
187    TestKeyAssigner getKeyAssigner() {
188
189        if (isQueueOrRecno()) {
190            return null;
191        } else {
192            if (isRecNumFormat) {
193                return RECNO_KEY_ASSIGNER;
194            } else {
195                return BYTE_KEY_ASSIGNER;
196            }
197        }
198    }
199
200    String getName() {
201
202        return name;
203    }
204
205    boolean isOrdered() {
206
207        return !DbCompat.isTypeHash(config);
208    }
209
210    boolean isQueueOrRecno() {
211
212        return DbCompat.isTypeQueue(config) || DbCompat.isTypeRecno(config);
213    }
214
215    boolean areKeyRangesAllowed() {
216        return isOrdered() && !isQueueOrRecno();
217    }
218
219    boolean areDuplicatesAllowed() {
220
221        return DbCompat.getSortedDuplicates(config) ||
222               DbCompat.getUnsortedDuplicates(config);
223    }
224
225    boolean hasRecNumAccess() {
226
227        return isRecNumFormat;
228    }
229
230    boolean areKeysRenumbered() {
231
232        return hasRecNumAccess() &&
233                (DbCompat.isTypeBtree(config) ||
234                 DbCompat.getRenumbering(config));
235    }
236
237    TestStore getIndexOf() {
238
239        return DbCompat.SECONDARIES ? indexOf : null;
240    }
241
242    Database open(Environment env, String fileName)
243        throws IOException, DatabaseException {
244
245        int fixedLen = (isQueueOrRecno() ? 1 : 0);
246        return openDb(env, fileName, fixedLen, null);
247    }
248
249    Database openIndex(Database primary, String fileName)
250        throws IOException, DatabaseException {
251
252        int fixedLen = (isQueueOrRecno() ? 4 : 0);
253        config.setKeyCreator(isRecNumFormat ? RECNO_EXTRACTOR
254                                            : BYTE_EXTRACTOR);
255        Environment env = primary.getEnvironment();
256        return openDb(env, fileName, fixedLen, primary);
257    }
258
259    private Database openDb(Environment env, String fileName, int fixedLen,
260                            Database primary)
261        throws IOException, DatabaseException {
262
263        if (fixedLen > 0) {
264            DbCompat.setRecordLength(config, fixedLen);
265            DbCompat.setRecordPad(config, 0);
266        } else {
267            DbCompat.setRecordLength(config, 0);
268        }
269        config.setAllowCreate(true);
270        DbCompat.setReadUncommitted(config, true);
271        config.setTransactional(CurrentTransaction.getInstance(env) != null);
272        if (primary != null) {
273            return DbCompat.testOpenSecondaryDatabase
274                (env, null, fileName, null, primary, config);
275        } else {
276            return DbCompat.testOpenDatabase
277                (env, null, fileName, null, config);
278        }
279    }
280}
281