1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package org.apache.directory.mitosis.store.derby;
21
22
23 import java.io.File;
24 import java.io.IOException;
25 import java.util.ArrayList;
26 import java.util.HashMap;
27 import java.util.HashSet;
28 import java.util.Iterator;
29 import java.util.List;
30 import java.util.Map;
31 import java.util.Set;
32 import java.util.UUID;
33
34 import javax.naming.Name;
35 import javax.naming.ldap.LdapName;
36
37 import junit.framework.Assert;
38 import junit.framework.TestCase;
39
40 import org.apache.commons.io.FileUtils;
41 import org.apache.directory.server.core.DefaultDirectoryService;
42 import org.apache.directory.server.core.entry.DefaultServerAttribute;
43 import org.apache.directory.server.core.entry.DefaultServerEntry;
44 import org.apache.directory.server.schema.registries.AttributeTypeRegistry;
45 import org.apache.directory.shared.ldap.entry.EntryAttribute;
46 import org.apache.directory.shared.ldap.name.LdapDN;
47 import org.apache.directory.shared.ldap.schema.AttributeType;
48 import org.apache.directory.shared.ldap.schema.DeepTrimToLowerNormalizer;
49 import org.apache.directory.shared.ldap.schema.OidNormalizer;
50 import org.apache.directory.mitosis.common.CSN;
51 import org.apache.directory.mitosis.common.CSNFactory;
52 import org.apache.directory.mitosis.common.CSNVector;
53 import org.apache.directory.mitosis.common.DefaultCSN;
54 import org.apache.directory.mitosis.common.DefaultCSNFactory;
55 import org.apache.directory.mitosis.configuration.ReplicationConfiguration;
56 import org.apache.directory.mitosis.operation.AddAttributeOperation;
57 import org.apache.directory.mitosis.operation.AddEntryOperation;
58 import org.apache.directory.mitosis.operation.CompositeOperation;
59 import org.apache.directory.mitosis.operation.DeleteAttributeOperation;
60 import org.apache.directory.mitosis.operation.Operation;
61 import org.apache.directory.mitosis.operation.ReplaceAttributeOperation;
62 import org.apache.directory.mitosis.store.ReplicationLogIterator;
63 import org.apache.directory.mitosis.store.ReplicationStoreException;
64
65
66 public class DerbyReplicationStoreTest extends TestCase
67 {
68 private static final String REPLICA_ID = "TEST_REPLICA";
69 private static final String OTHER_REPLICA_ID = "OTHER_REPLICA";
70 private static final String OTHER_REPLICA_ID_2 = "OTHER_REPLICA_2";
71 private static final File DB_PATH = new File( "target/testDB" );
72
73 private final CSNFactory csnFactory = new DefaultCSNFactory();
74 private DerbyReplicationStore store;
75 private int testCount;
76 private long startTime;
77 private DefaultDirectoryService service;
78
79
80 public void setUp() throws Exception
81 {
82 dropDatabase();
83 startupDatabase( REPLICA_ID );
84 initStopWatch();
85 }
86
87
88 private void startupDatabase( String replicaId ) throws Exception
89 {
90
91 ReplicationConfiguration cfg = new ReplicationConfiguration();
92 cfg.setReplicaId( replicaId );
93
94
95 store = new DerbyReplicationStore();
96 store.setTablePrefix( "TEST_" );
97 service = new DefaultDirectoryService();
98 service.setWorkingDirectory( DB_PATH );
99 store.open( service, cfg );
100 }
101
102
103 public void tearDown() throws Exception
104 {
105 store.close();
106 dropDatabase();
107 }
108
109
110 private void dropDatabase() throws IOException
111 {
112 FileUtils.deleteDirectory( DB_PATH );
113 File logFile = new File( "derby.log" );
114 if ( !logFile.delete() )
115 {
116 logFile.deleteOnExit();
117 }
118 }
119
120
121 public void testOperations() throws Exception
122 {
123 subTestReopen();
124 printElapsedTime( "Reopen" );
125 subTestUUID();
126 printElapsedTime( "UUID" );
127 subTestEmptyLog();
128 printElapsedTime( "EmptyLog" );
129 subTestWriteLog();
130 printElapsedTime( "WriteLog" );
131 subTestRemoveLogs();
132 printElapsedTime( "RemoveLogs" );
133 subTestVectors();
134 printElapsedTime( "Vectors" );
135 }
136
137
138 private void subTestReopen() throws Exception
139 {
140 store.close();
141 try
142 {
143 startupDatabase( OTHER_REPLICA_ID );
144 Assert.fail( "Store cannot start up with wrong replica ID." );
145 }
146 catch ( ReplicationStoreException e )
147 {
148 }
149 startupDatabase( REPLICA_ID );
150 }
151
152
153 private void subTestUUID() throws Exception
154 {
155 UUID uuid = UUID.randomUUID();
156 Name name = new LdapName( "ou=a, ou=b" );
157 Assert.assertTrue( store.putUUID( uuid, name ) );
158 Assert.assertEquals( name, store.getDN( uuid ) );
159 Assert.assertTrue( store.removeUUID( uuid ) );
160 Assert.assertFalse( store.removeUUID( uuid ) );
161 Assert.assertNull( store.getDN( uuid ) );
162 }
163
164
165 private void subTestEmptyLog() throws Exception
166 {
167 ReplicationLogIterator it;
168
169 it = store.getLogs( csnFactory.newInstance( REPLICA_ID ), true );
170 Assert.assertFalse( it.next() );
171 it.close();
172 it = store.getLogs( csnFactory.newInstance( REPLICA_ID ), false );
173 Assert.assertFalse( it.next() );
174 it.close();
175 it = store.getLogs( csnFactory.newInstance( OTHER_REPLICA_ID ), true );
176 Assert.assertFalse( it.next() );
177 it.close();
178 it = store.getLogs( csnFactory.newInstance( OTHER_REPLICA_ID ), false );
179 Assert.assertFalse( it.next() );
180 it.close();
181
182 Assert.assertEquals( 0, store.getLogSize() );
183 }
184
185
186 private void subTestWriteLog() throws Exception
187 {
188 Map<String, OidNormalizer> oids = new HashMap<String, OidNormalizer>();
189
190 oids.put( "ou", new OidNormalizer( "ou", new DeepTrimToLowerNormalizer() ) );
191 oids.put( "organizationalUnitName", new OidNormalizer( "ou", new DeepTrimToLowerNormalizer() ) );
192 oids.put( "2.5.4.11", new OidNormalizer( "ou", new DeepTrimToLowerNormalizer() ) );
193
194 AttributeTypeRegistry atRegistry = service.getRegistries().getAttributeTypeRegistry();
195
196 CSN csn = csnFactory.newInstance( REPLICA_ID );
197 CompositeOperation op1 = new CompositeOperation( service.getRegistries(), csn );
198 LdapDN ouA = new LdapDN( "ou=a" ).normalize( oids );
199 op1.add( new AddEntryOperation( service.getRegistries(), csn,
200 new DefaultServerEntry( service.getRegistries(), ouA ) ) );
201
202 op1.add( new AddAttributeOperation( service.getRegistries(), csn, ouA,
203 new DefaultServerAttribute( "ou", atRegistry.lookup( "ou" ), "valie" ) ) );
204
205 op1.add( new ReplaceAttributeOperation( service.getRegistries(), csn, ouA,
206 new DefaultServerAttribute( "ou", atRegistry.lookup( "ou" ), "valie" ) ) );
207
208 op1.add( new DeleteAttributeOperation( service.getRegistries(), csn, ouA,
209 new DefaultServerAttribute( "ou", atRegistry.lookup( "ou" ), "valie" ) ) );
210
211 store.putLog( op1 );
212 testGetLogs( csn, op1 );
213
214 csn = csnFactory.newInstance( OTHER_REPLICA_ID );
215 CompositeOperation op2 = new CompositeOperation( service.getRegistries(), csn );
216 op2.add( new AddEntryOperation( service.getRegistries(), csn,
217 new DefaultServerEntry( service.getRegistries(), ouA ) ) );
218
219 op2.add( new AddAttributeOperation( service.getRegistries(), csn, ouA,
220 new DefaultServerAttribute( "ou", atRegistry.lookup( "ou" ), "valie" ) ) );
221
222 op2.add( new ReplaceAttributeOperation( service.getRegistries(), csn, ouA,
223 new DefaultServerAttribute( "ou", atRegistry.lookup( "ou" ), "valie" ) ) );
224
225 op2.add( new DeleteAttributeOperation( service.getRegistries(), csn, ouA,
226 new DefaultServerAttribute( "ou", atRegistry.lookup( "ou" ), "valie" ) ) );
227
228 store.putLog( op2 );
229 testGetLogs( csn, op2 );
230
231 Assert.assertEquals( 2, store.getLogSize() );
232 Assert.assertEquals( 1, store.getLogSize( REPLICA_ID ) );
233 Assert.assertEquals( 1, store.getLogSize( OTHER_REPLICA_ID ) );
234
235
236 List<Operation> expected = new ArrayList<Operation>();
237 expected.add( op1 );
238 expected.add( op2 );
239 CSNVector updateVector = new CSNVector();
240 testGetLogs( updateVector, true, expected );
241
242 updateVector = new CSNVector();
243 updateVector.setCSN( op1.getCSN() );
244 testGetLogs( updateVector, true, expected );
245
246 updateVector = new CSNVector();
247 updateVector.setCSN( op2.getCSN() );
248 testGetLogs( updateVector, true, expected );
249
250 updateVector = new CSNVector();
251 updateVector.setCSN( op1.getCSN() );
252 updateVector.setCSN( op2.getCSN() );
253 testGetLogs( updateVector, true, expected );
254
255
256 expected = new ArrayList<Operation>();
257 expected.add( op1 );
258 expected.add( op2 );
259 updateVector = new CSNVector();
260 testGetLogs( updateVector, false, expected );
261 expected = new ArrayList<Operation>();
262 expected.add( op2 );
263 updateVector = new CSNVector();
264 updateVector.setCSN( op1.getCSN() );
265 testGetLogs( updateVector, false, expected );
266 expected = new ArrayList<Operation>();
267 expected.add( op1 );
268 updateVector = new CSNVector();
269 updateVector.setCSN( op2.getCSN() );
270 testGetLogs( updateVector, false, expected );
271 expected = new ArrayList<Operation>();
272 updateVector = new CSNVector();
273 updateVector.setCSN( op1.getCSN() );
274 updateVector.setCSN( op2.getCSN() );
275 testGetLogs( updateVector, false, expected );
276 }
277
278
279 private void subTestRemoveLogs()
280 {
281 CSN csn;
282 ReplicationLogIterator it;
283
284 it = store.getLogs( new DefaultCSN( 0, REPLICA_ID, 0 ), false );
285 it.next();
286 csn = it.getOperation( service.getRegistries() ).getCSN();
287 it.close();
288
289 Assert.assertEquals( 0, store.removeLogs( csn, false ) );
290 Assert.assertEquals( 1, store.removeLogs( csn, true ) );
291 Assert.assertEquals( 0, store.getLogSize( REPLICA_ID ) );
292
293 it = store.getLogs( new DefaultCSN( 0, OTHER_REPLICA_ID, 0 ), false );
294 Assert.assertTrue( it.next() );
295 csn = it.getOperation( service.getRegistries() ).getCSN();
296 it.close();
297
298 Assert.assertEquals( 0, store.removeLogs( csn, false ) );
299 Assert.assertEquals( 1, store.removeLogs( csn, true ) );
300 Assert.assertEquals( 0, store.getLogSize( OTHER_REPLICA_ID ) );
301
302 Assert.assertEquals( 0, store.getLogSize() );
303 }
304
305
306 private void subTestVectors() throws Exception
307 {
308 CSN csnA = new DefaultCSN( 0, REPLICA_ID, 0 );
309 CSN csnB = new DefaultCSN( 1, REPLICA_ID, 0 );
310 CSN csnC = new DefaultCSN( 0, OTHER_REPLICA_ID_2, 0 );
311 CSN csnD = new DefaultCSN( 0, OTHER_REPLICA_ID_2, 1 );
312 AttributeType at = service.getRegistries().getAttributeTypeRegistry().lookup( "ou" );
313 EntryAttribute attribute = new DefaultServerAttribute( at, "test" );
314 store.putLog( new AddAttributeOperation( service.getRegistries(), csnA, LdapDN.EMPTY_LDAPDN, attribute ) );
315 store.putLog( new AddAttributeOperation( service.getRegistries(), csnB, LdapDN.EMPTY_LDAPDN, attribute ) );
316 store.putLog( new AddAttributeOperation( service.getRegistries(), csnC, LdapDN.EMPTY_LDAPDN, attribute ) );
317 store.putLog( new AddAttributeOperation( service.getRegistries(), csnD, LdapDN.EMPTY_LDAPDN, attribute ) );
318
319 Set<String> expectedKnownReplicaIds = new HashSet<String>();
320 expectedKnownReplicaIds.add( REPLICA_ID );
321 expectedKnownReplicaIds.add( OTHER_REPLICA_ID );
322 expectedKnownReplicaIds.add( OTHER_REPLICA_ID_2 );
323
324 Assert.assertEquals( expectedKnownReplicaIds, store.getKnownReplicaIds() );
325
326 CSNVector expectedUpdateVector = new CSNVector();
327 expectedUpdateVector.setCSN( csnB );
328 expectedUpdateVector.setCSN( csnD );
329
330 Assert.assertEquals( expectedUpdateVector, store.getUpdateVector() );
331
332 CSNVector expectedPurgeVector = new CSNVector();
333 expectedPurgeVector.setCSN( csnA );
334 expectedPurgeVector.setCSN( csnC );
335
336 Assert.assertEquals( expectedPurgeVector, store.getPurgeVector() );
337 }
338
339
340 private void testGetLogs( CSN csn, Operation operation )
341 {
342 List<Operation> operations = new ArrayList<Operation>();
343 operations.add( operation );
344 testGetLogs( csn, operations );
345 }
346
347
348 private void testGetLogs( CSN csn, List<Operation> operations )
349 {
350 Iterator<Operation> it = operations.iterator();
351 ReplicationLogIterator rit = store.getLogs( csn, true );
352 testGetLogs( it, rit );
353
354 rit = store.getLogs( csn, false );
355 Assert.assertFalse( rit.next() );
356 rit.close();
357 }
358
359
360 private void testGetLogs( CSNVector updateVector, boolean inclusive, List<Operation> operations )
361 {
362 Iterator<Operation> it = operations.iterator();
363 ReplicationLogIterator rit = store.getLogs( updateVector, inclusive );
364 testGetLogs( it, rit );
365 }
366
367
368 private void testGetLogs( Iterator<Operation> expectedIt, ReplicationLogIterator actualIt )
369 {
370 while ( expectedIt.hasNext() )
371 {
372 Operation expected = expectedIt.next();
373 Assert.assertTrue( actualIt.next() );
374
375 Operation actual = actualIt.getOperation( service.getRegistries() );
376 Assert.assertEquals( expected.getCSN(), actual.getCSN() );
377 assertEquals( expected, actual );
378 }
379 Assert.assertFalse( actualIt.next() );
380 actualIt.close();
381 }
382
383
384 private void initStopWatch()
385 {
386 startTime = System.currentTimeMillis();
387 }
388
389
390 private void printElapsedTime( String testName )
391 {
392 long endTime = System.currentTimeMillis();
393 System.out.println( "Subtest #" + ( ++testCount ) + " [" + testName + "]: " + ( endTime - startTime ) + " ms" );
394 startTime = System.currentTimeMillis();
395 }
396
397
398 private static void assertEquals( Operation expected, Operation actual )
399 {
400 Assert.assertEquals( expected.toString(), actual.toString() );
401 }
402 }