1   
2   
3   
4   
5   
6   
7   
8   
9   
10  
11  
12  
13  
14  
15  
16  package net.sourceforge.domian.test.benchmark;
17  
18  
19  import java.text.SimpleDateFormat;
20  import java.util.Date;
21  import java.util.Iterator;
22  
23  import net.sourceforge.domian.repository.PartitionRepository;
24  import net.sourceforge.domian.repository.PersistentRepository;
25  import net.sourceforge.domian.repository.Repository;
26  import net.sourceforge.domian.util.StopWatch;
27  import net.sourceforge.domian.util.concurrent.task.ConcurrentRepositoryTaskExecutor;
28  import net.sourceforge.domian.util.concurrent.task.RepositoryTask;
29  
30  import static net.sourceforge.domian.specification.SpecificationFactory.all;
31  import static net.sourceforge.domian.test.benchmark.QueenPuzzleUtils.conditionalLogging;
32  import static org.apache.commons.lang.math.RandomUtils.nextInt;
33  
34  
35  
36  
37  
38  
39  
40  
41  
42  
43  
44  
45  
46  
47  
48  
49  
50  
51  class ConcurrentQueenPuzzle extends AbstractQueenPuzzle {
52  
53      ConcurrentQueenPuzzle(final SequentialQueenPuzzle.RepositoryType repositoryType,
54                            final long numberOfConstellations,
55                            final int numberOfWorkers,
56                            final long logInterval) {
57          super(repositoryType, numberOfConstellations, numberOfWorkers, logInterval);
58      }
59  
60  
61      void solvePuzzle() {
62          System.out.println();
63          System.out.println("Solving the \"Queen Puzzle\" concurrently... [start time: " + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss,SSS").format(new Date()) + "]");
64          System.out.println("Processors      : " + Runtime.getRuntime().availableProcessors());
65          System.out.println("Worker threads  : " + this.numberOfWorkers);
66          System.out.println("Constellations  : " + this.numberOfConstellations + " + 1 correct one for completion control");
67          System.out.println("Repository type : " + this.repositoryType);
68          System.out.println();
69  
70          
71          final Repository<QueenPuzzleConstellation> repo = createRepository(this.repositoryType);
72          if (repo instanceof PersistentRepository) {
73              PersistentRepository persistentRepository = (PersistentRepository) repo;
74              repo.remove(all(QueenPuzzleConstellation.class));
75              if (persistentRepository.getPersistenceDefinition().supportsAsynchronousPersistence()) {
76                  persistentRepository.persist();
77              }
78          }
79  
80          final StopWatch stopWatch = new StopWatch().start();
81  
82          
83          if (repo instanceof PartitionRepository) {
84              
85              ((PartitionRepository<QueenPuzzleConstellation>) repo).addPartitionFor(queenPuzzleConstellationsThatIsProcessedAndMarkedAsToSolveTheQueenPuzzle, "approved-queenpuzzle-constellations");
86              ((PartitionRepository<QueenPuzzleConstellation>) repo).addPartitionFor(unProcessedQueenPuzzleConstellations, "unprocessed-queenpuzzle-constellations");
87          }
88  
89          
90          addOneWellKnownSuccessfulQueenPuzzleConstellationInto(repo);
91  
92          
93          final ConcurrentRepositoryTaskExecutor concurrentTaskExecutor = new ConcurrentRepositoryTaskExecutor(repo);
94          for (int producerNumber = 0; producerNumber < this.numberOfWorkers; ++producerNumber) {
95              concurrentTaskExecutor.addTask(new RandomPermutationQueenPuzzleConstellationProducer(this.numberOfConstellations / this.numberOfWorkers,
96                                                                                                   this.logInterval));
97          }
98          System.out.println("Starting concurrent execution of " + this.numberOfWorkers + " worker threads...");
99          try {
100             concurrentTaskExecutor.execute();
101         } catch (Exception e) {
102             e.printStackTrace();
103             throw new RuntimeException(e);
104         }
105         System.out.println("Concurrent execution of worker threads terminated!");
106 
107         doPrintProcessStatistics(stopWatch.getElapsedTime(), this.numberOfConstellations);
108 
109         
110         
111         
112 
113 
114 
115         
116         if (repo instanceof PersistentRepository) {
117             doPersist((PersistentRepository) repo);
118         }
119 
120         
121         doResultSearch(repo);
122 
123         
124         doCompletionControl(repo);
125 
126         System.out.println();
127         System.out.println("Overall time: " + stopWatch);
128     }
129 
130 
131     private static class RandomPermutationQueenPuzzleConstellationProducer extends RepositoryTask<Repository<QueenPuzzleConstellation>> {
132 
133         final long numberOfConstellationsToProduce;
134         final long logInterval;
135 
136         RandomPermutationQueenPuzzleConstellationProducer(final long numberOfConstellationsToProduce, final long logInterval) {
137             super();
138             this.numberOfConstellationsToProduce = numberOfConstellationsToProduce;
139             this.logInterval = logInterval;
140         }
141 
142         
143         private boolean constellationConstraintOk(final int[] queenPlacingNumbers, final int queenPlacingIndex, final int queenPlacingNumber) {
144             for (int index = 0; index < queenPlacingIndex; ++index) {
145                 if (queenPlacingNumber == queenPlacingNumbers[index]) {
146                     return false;
147                 }
148             }
149             return true;
150         }
151 
152         public void doConcurrentTask() {
153             long processingCounter = 0;
154             long redundantProcessingCounter = 0;
155 
156             final StopWatch stopWatch = new StopWatch().start();
157 
158             
159             for (long workerInternalConstellationNumber = 1;
160                  workerInternalConstellationNumber <= this.numberOfConstellationsToProduce;
161                  ++workerInternalConstellationNumber) {
162                 final int[] constellation = new int[8];
163                 int index = 0;
164                 while (index < 8) {
165                     int number = nextInt(64);
166                     while (!constellationConstraintOk(constellation, index, number)) {
167                         number = nextInt(64);
168                     }
169                     constellation[index++] = number;
170                 }
171                 final QueenPuzzleConstellation queenPuzzleConstellation = new QueenPuzzleConstellation(new ChessPiecePlacing(constellation[0]),
172                                                                                                        new ChessPiecePlacing(constellation[1]),
173                                                                                                        new ChessPiecePlacing(constellation[2]),
174                                                                                                        new ChessPiecePlacing(constellation[3]),
175                                                                                                        new ChessPiecePlacing(constellation[4]),
176                                                                                                        new ChessPiecePlacing(constellation[5]),
177                                                                                                        new ChessPiecePlacing(constellation[6]),
178                                                                                                        new ChessPiecePlacing(constellation[7]));
179                 this.repository.put(queenPuzzleConstellation);
180                 conditionalLogging((long) this.threadNumber, this.logInterval, workerInternalConstellationNumber, stopWatch, queenPuzzleConstellation, "generated and added to repo so far...");
181             }
182 
183             
184             final Iterator<? extends QueenPuzzleConstellation> allUnprocessedConstellations = this.repository.iterateAll(unProcessedQueenPuzzleConstellations);
185             long numberOfProcessedConstellations = 0;
186             while (allUnprocessedConstellations.hasNext()) {
187                 QueenPuzzleConstellation unProcessedQueenPuzzleConstellation = allUnprocessedConstellations.next();
188 
189                 
190                 synchronized (unProcessedQueenPuzzleConstellation) {
191                     if (unProcessedQueenPuzzleConstellation.isProcessed()) {
192                         ++redundantProcessingCounter;
193                     } else {
194                         unProcessedQueenPuzzleConstellation.setSolvesQueenPuzzle(queenPuzzleConstellationsThatInherentlySolvesTheQueenPuzzle.isSatisfiedBy(unProcessedQueenPuzzleConstellation));
195                         this.repository.update(unProcessedQueenPuzzleConstellation);
196                         ++processingCounter;
197                     }
198                     conditionalLogging((long) this.threadNumber, logInterval, ++numberOfProcessedConstellations, stopWatch, unProcessedQueenPuzzleConstellation, "processed so far...");
199                 }
200 
201                 
202                 
203                 
204             }
205             
206             System.out.println("Worker thread #" + this.threadNumber + " finished. " + processingCounter + " puzzle constellation processed by this worker. " + redundantProcessingCounter + " puzzle constellation was already processed.");
207             
208         }
209     }
210 }