Revision 47609

View differences:

trunk/org.gvsig.desktop/org.gvsig.desktop.plugin/org.gvsig.sqlite/org.gvsig.sqlite.provider/src/test/java/org/gvsig/sqlite/dal/TestMultiThread.java
1
package org.gvsig.sqlite.dal;
2

  
3
import java.io.File;
4
import java.net.URL;
5
import java.util.HashMap;
6
import java.util.Map;
7
import junit.framework.TestCase;
8
import static junit.framework.TestCase.assertEquals;
9
import org.apache.commons.io.IOUtils;
10
import org.gvsig.fmap.dal.DALLocator;
11
import org.gvsig.fmap.dal.DataManager;
12
import org.gvsig.fmap.dal.DataTransaction;
13
import org.gvsig.fmap.dal.exception.ValidateDataParametersException;
14
import org.gvsig.fmap.dal.feature.Feature;
15
import org.gvsig.fmap.dal.feature.FeatureSet;
16
import org.gvsig.fmap.dal.feature.FeatureStore;
17
import org.gvsig.fmap.dal.store.jdbc.JDBCStoreParameters;
18
import org.gvsig.fmap.dal.store.jdbc2.JDBCServerExplorer;
19
import org.gvsig.tools.dispose.DisposeUtils;
20
import org.gvsig.tools.library.impl.DefaultLibrariesInitializer;
21
import org.slf4j.Logger;
22
import org.slf4j.LoggerFactory;
23

  
24
@SuppressWarnings("UseSpecificCatch")
25
public class TestMultiThread extends TestCase {
26
    private static final Logger LOGGER = LoggerFactory.getLogger(TestMultiThread.class);
27
    
28
    public static final String DBNAME = "rte";
29
    
30
    public TestMultiThread(String testName) {
31
        super(testName);
32
    }
33
    
34
    @Override
35
    protected void setUp() throws Exception {
36
        super.setUp();
37
        new DefaultLibrariesInitializer().fullInitialize();
38
    }
39
    
40
    @Override
41
    protected void tearDown() throws Exception {
42
        super.tearDown();
43
    }
44

  
45
    private TestUtilsSQLite utils = null;
46
    
47
    public TestUtilsSQLite utils() {
48
        if( this.utils == null ) {
49
            this.utils = new TestUtilsSQLite();
50
        }
51
        return this.utils;
52
    }
53
    
54
    // TODO add test methods here. The name must begin with 'test'. For example:
55
    // public void testHello() {}
56
    
57
    protected FeatureStore openStore1(JDBCServerExplorer explorer) throws Exception {
58
        JDBCStoreParameters params = explorer.get("cats_feature");
59
        
60
        DataManager dataManager = DALLocator.getDataManager();
61
        FeatureStore store;
62
        try {
63
            store = (FeatureStore) dataManager.openStore(
64
                    utils().getProviderName(), 
65
                    params
66
            );
67
        } catch(ValidateDataParametersException ex) {
68
            LOGGER.warn(ex.getLocalizedMessageStack());
69
            throw ex;
70
        }
71
        return store;
72
    }
73

  
74
    private static class TaskTrans extends Thread {
75

  
76
        private final FeatureStore store;
77
        private final Object mon;
78
        private Map<Integer,Boolean> waitmon;
79
        private Throwable exception;
80
        
81
        public TaskTrans(String name, FeatureStore store) {
82
            this(name, store,null);
83
        }
84
        
85
        public TaskTrans(String name, FeatureStore store, Object mon) {
86
            this.setName(name);
87
            this.store = store;
88
            this.mon = mon;
89
            this.waitmon = new HashMap<>();
90
        }
91

  
92
        @Override
93
        @SuppressWarnings("null")
94
        public void run() {
95
            // Ojo, solo puede haber un waitmon activo, o ver que se hace
96
            // para hacer tantos notify como waitmon.
97

  
98
            DataManager dataManager = DALLocator.getDataManager();
99
            DataTransaction trans = dataManager.createTransaction();
100
            try {
101
                trans.begin();
102
                trans.add(this.store, false);
103
    
104
                this.waitmon(1);
105
                int n=1;
106
                LOGGER.info("Create featureset");
107
                FeatureSet set = this.store.getFeatureSet();
108
                LOGGER.info("for");
109
                for (Feature feature : set) {
110
                    LOGGER.info("for block "+n);
111
                    assertEquals("feature "+n+" id mismatch", feature.get("id"), n);
112
                    n++;
113
                    if( n == (int)(set.size()/2) ) {
114
                        this.waitmon(2);
115
                    }
116
                }
117
                LOGGER.info("Dispose featureset");
118
                DisposeUtils.dispose(set);
119
                LOGGER.info("Commit");
120
                trans.commit();
121
            } catch(Exception ex) {
122
                this.exception = ex;
123
                LOGGER.info("Rollback");
124
                trans.rollbackQuietly();
125
                LOGGER.warn("Task error",ex);
126
            } finally {
127
                LOGGER.info("Close");
128
                DataTransaction.close(trans);
129
            }
130
        }
131

  
132
        private void waitmon(int n) throws InterruptedException {
133
            if( this.mon!=null ) {
134
                if( !this.waitmon.getOrDefault(n,true) ) {
135
                    LOGGER.info("wait mon "+n+" skip");
136
                    return;
137
                }
138
                LOGGER.info("wait mon "+n);
139
                synchronized(this.mon) {                                
140
                    this.mon.wait(20*1000);
141
                }
142
            }
143
        }
144
        
145
        public void throwError() throws Throwable {
146
            if( this.exception!= null ) {
147
                throw this.exception;
148
            }
149
        }
150

  
151
        public void setWaitmonEnabled(int i, boolean b) {
152
            this.waitmon.put(i,b);
153
        }
154
    }
155
    
156
    private static class TaskNoTrans extends Thread {
157

  
158
        private final FeatureStore store;
159
        private final Object mon;
160
        private Map<Integer,Boolean> waitmon;
161
        private Throwable exception;
162
        
163
        public TaskNoTrans(String name, FeatureStore store) {
164
            this(name, store,null);
165
        }
166
        
167
        public TaskNoTrans(String name, FeatureStore store, Object mon) {
168
            this.setName(name);
169
            this.store = store;
170
            this.mon = mon;
171
            this.waitmon = new HashMap<>();
172
        }
173

  
174
        @Override
175
        @SuppressWarnings("null")
176
        public void run() {
177
            // Ojo, solo puede haber un waitmon activo, o ver que se hace
178
            // para hacer tantos notify como waitmon.
179
            try {
180
                this.waitmon(1);
181
                int n=1;
182
                LOGGER.info("Create featureset");
183
                FeatureSet set = this.store.getFeatureSet();
184
                LOGGER.info("for");
185
                for (Feature feature : set) {
186
                    LOGGER.info("for block "+n);
187
                    assertEquals("feature "+n+" id mismatch", feature.get("id"), n);
188
                    n++;
189
                    if( n == (int)(set.size()/2) ) {
190
                        this.waitmon(2);
191
                    }
192
                }
193
                LOGGER.info("Dispose featureset");
194
                DisposeUtils.dispose(set);
195
            } catch(Exception ex) {
196
                this.exception = ex;
197
                LOGGER.warn("Task error",ex);
198
            } finally {
199
                LOGGER.info("terminate");
200
            }
201
        }
202

  
203
        private void waitmon(int n) throws InterruptedException {
204
            if( this.mon!=null ) {
205
                if( !this.waitmon.getOrDefault(n,true) ) {
206
                    LOGGER.info("wait mon "+n+" skip");
207
                    return;
208
                }
209
                LOGGER.info("wait mon "+n);
210
                synchronized(this.mon) {                                
211
                    this.mon.wait(20*1000);
212
                }
213
            }
214
        }
215
        
216
        public void throwError() throws Throwable {
217
            if( this.exception!= null ) {
218
                throw this.exception;
219
            }
220
        }
221

  
222
        public void setWaitmonEnabled(int i, boolean b) {
223
            this.waitmon.put(i,b);
224
        }
225
    }
226

  
227
    public void testMultiThreadBasic1() throws Throwable {
228
        FeatureStore store = null;
229
        JDBCServerExplorer explorer = null;
230
        try {
231
            String dbfilename = DBNAME+".gpkg";
232
            URL url = this.getClass().getResource(dbfilename);
233
            File tmp = new File( utils().getTargetFolder(), dbfilename);
234
            IOUtils.copy(url, tmp);
235
        
236
            explorer = utils().openServerExplorer(tmp);
237

  
238
            LOGGER.info("Open store");
239
            store = openStore1(explorer);
240

  
241
            LOGGER.info("Creating task1");
242
            TaskTrans task = new TaskTrans("task1", store);
243
            LOGGER.info("Starting task1");
244
            task.start();
245
            LOGGER.info("join task1");
246
            task.join();
247
            task.throwError();
248
            
249
            DisposeUtils.dispose(store);
250
            
251
        } catch(Throwable t) {
252
            LOGGER.warn("",t);
253
            throw t;
254
        } finally {
255
            DisposeUtils.disposeQuietly(store);
256
            DisposeUtils.disposeQuietly(explorer);
257
        }
258
    }
259

  
260
    public void testMultiThreadBasic2() throws Throwable {
261
        FeatureStore store = null;
262
        JDBCServerExplorer explorer = null;
263
        try {
264
            String dbfilename = DBNAME+".gpkg";
265
            URL url = this.getClass().getResource(dbfilename);
266
            File tmp = new File( utils().getTargetFolder(), dbfilename);
267
            IOUtils.copy(url, tmp);
268
        
269
            Object mon = new Object();
270
            explorer = utils().openServerExplorer(tmp);
271

  
272
            LOGGER.info("Open store");
273
            store = openStore1(explorer);
274

  
275
            LOGGER.info("Creating task1");
276
            TaskTrans task1 = new TaskTrans("task1", store);
277
            task1.setWaitmonEnabled(1, false);
278

  
279
            LOGGER.info("Creating task2");
280
            TaskTrans task2 = new TaskTrans("task2", store, mon);
281
            task2.setWaitmonEnabled(1, false);
282

  
283
            LOGGER.info("Starting task1");
284
            task1.start();
285
            LOGGER.info("Starting task2");
286
            task2.start();
287

  
288
            LOGGER.info("join task1");
289
            task1.join();
290
            task1.throwError();
291

  
292
            LOGGER.info("notifyAll");
293
            synchronized(mon) {
294
                mon.notify();
295
            }
296

  
297
            LOGGER.info("join task2");
298
            task2.join();
299
            task2.throwError();
300

  
301
            LOGGER.info("Dispose store");
302
            DisposeUtils.dispose(store);
303
            
304
        } catch(Throwable t) {
305
            LOGGER.warn("",t);
306
            throw t;
307
        } finally {
308
            LOGGER.info("finally");
309
            DisposeUtils.disposeQuietly(store);
310
            DisposeUtils.disposeQuietly(explorer);
311
        }
312
    }
313
    
314
    public void testMultiThreadBasic2b() throws Throwable {
315
        FeatureStore store = null;
316
        JDBCServerExplorer explorer = null;
317
        try {
318
            String dbfilename = DBNAME+".gpkg";
319
            URL url = this.getClass().getResource(dbfilename);
320
            File tmp = new File( utils().getTargetFolder(), dbfilename);
321
            IOUtils.copy(url, tmp);
322
        
323
            Object mon = new Object();
324
            explorer = utils().openServerExplorer(tmp);
325

  
326
            LOGGER.info("Open store");
327
            store = openStore1(explorer);
328

  
329
            LOGGER.info("Creating task1");
330
            TaskTrans task1 = new TaskTrans("task1", store);
331
            task1.setWaitmonEnabled(2, false);
332

  
333
            LOGGER.info("Creating task2");
334
            TaskTrans task2 = new TaskTrans("task2", store, mon);
335
            task2.setWaitmonEnabled(2, false);
336

  
337
            LOGGER.info("Starting task1");
338
            task1.start();
339
            LOGGER.info("Starting task2");
340
            task2.start();
341

  
342
            LOGGER.info("join task1");
343
            task1.join();
344
            task1.throwError();
345

  
346
            LOGGER.info("notifyAll");
347
            synchronized(mon) {
348
                mon.notifyAll();
349
            }
350

  
351
            LOGGER.info("join task2");
352
            task2.join();
353
            task2.throwError();
354

  
355
            LOGGER.info("Dispose store");
356
            DisposeUtils.dispose(store);
357
            
358
        } catch(Throwable t) {
359
            LOGGER.warn("",t);
360
            throw t;
361
        } finally {
362
            LOGGER.info("finally");
363
            DisposeUtils.disposeQuietly(store);
364
            DisposeUtils.disposeQuietly(explorer);
365
        }
366
    }
367
    
368
    public void testMultiThreadBasic3() throws Throwable {
369
        FeatureStore store = null;
370
        JDBCServerExplorer explorer = null;
371
        try {
372
            String dbfilename = DBNAME+".gpkg";
373
            URL url = this.getClass().getResource(dbfilename);
374
            File tmp = new File( utils().getTargetFolder(), dbfilename);
375
            IOUtils.copy(url, tmp);
376
        
377
            Object mon = new Object();
378
            explorer = utils().openServerExplorer(tmp);
379

  
380
            LOGGER.info("Open store");
381
            store = openStore1(explorer);
382

  
383
            LOGGER.info("Creating task1");
384
            TaskTrans task1 = new TaskTrans("task1", store);
385
            task1.setWaitmonEnabled(1, false);
386

  
387
            LOGGER.info("Creating task2");
388
            TaskNoTrans task2 = new TaskNoTrans("task2", store, mon);
389
            task2.setWaitmonEnabled(1, false);
390

  
391
            LOGGER.info("Starting task1");
392
            task1.start();
393
            LOGGER.info("Starting task2");
394
            task2.start();
395

  
396
            LOGGER.info("join task1");
397
            task1.join();
398
            task1.throwError();
399

  
400
            LOGGER.info("notifyAll");
401
            synchronized(mon) {
402
                mon.notifyAll();
403
            }
404

  
405
            LOGGER.info("join task2");
406
            task2.join();
407
            task2.throwError();
408

  
409
            LOGGER.info("Dispose store");
410
            DisposeUtils.dispose(store);
411
            
412
        } catch(Throwable t) {
413
            LOGGER.warn("",t);
414
            throw t;
415
        } finally {
416
            LOGGER.info("finally");
417
            DisposeUtils.disposeQuietly(store);
418
            DisposeUtils.disposeQuietly(explorer);
419
        }
420
    }
421
}

Also available in: Unified diff