1. Project Clover database Tue Dec 20 2016 21:24:09 CET
  2. Package com.xpn.xwiki.stats.impl.xwiki

File XWikiStatsStoreService.java

 

Coverage histogram

../../../../../../img/srcFileCovDistChart2.png
81% of files have more coverage

Code metrics

24
70
13
3
310
168
30
0.43
5.38
4.33
2.31

Classes

Class Line # Actions
XWikiStatsStoreService 48 69 0% 28 85
0.182692318.3%
StopStatsRegisterObject 288 1 0% 2 3
0.00%
StopStatsStoreException 307 0 - 0 0
-1.0 -
 

Contributing tests

No tests hitting this source file were found.

Source view

1    /*
2    * See the NOTICE file distributed with this work for additional
3    * information regarding copyright ownership.
4    *
5    * This is free software; you can redistribute it and/or modify it
6    * under the terms of the GNU Lesser General Public License as
7    * published by the Free Software Foundation; either version 2.1 of
8    * the License, or (at your option) any later version.
9    *
10    * This software is distributed in the hope that it will be useful,
11    * but WITHOUT ANY WARRANTY; without even the implied warranty of
12    * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13    * Lesser General Public License for more details.
14    *
15    * You should have received a copy of the GNU Lesser General Public
16    * License along with this software; if not, write to the Free
17    * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
18    * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
19    */
20    package com.xpn.xwiki.stats.impl.xwiki;
21   
22    import java.util.ArrayList;
23    import java.util.Date;
24    import java.util.HashMap;
25    import java.util.List;
26    import java.util.Map;
27    import java.util.concurrent.ArrayBlockingQueue;
28   
29    import org.slf4j.Logger;
30    import org.slf4j.LoggerFactory;
31    import org.xwiki.context.ExecutionContext;
32   
33    import com.xpn.xwiki.XWikiContext;
34    import com.xpn.xwiki.doc.XWikiDocument;
35    import com.xpn.xwiki.stats.impl.StatsUtil;
36    import com.xpn.xwiki.stats.impl.VisitStats;
37    import com.xpn.xwiki.util.AbstractXWikiRunnable;
38    import com.xpn.xwiki.web.DownloadAction;
39    import com.xpn.xwiki.web.SaveAction;
40    import com.xpn.xwiki.web.ViewAction;
41   
42    /**
43    * Back-end statistics storing service.
44    *
45    * @version $Id: 56d5668802f42fd93ffa20663e0e96cd435b6a7b $
46    * @since 1.4M2
47    */
 
48    public class XWikiStatsStoreService extends AbstractXWikiRunnable
49    {
50    /**
51    * Logging tools.
52    */
53    private static final Logger LOGGER = LoggerFactory.getLogger(XWikiStatsStoreService.class);
54   
55    /**
56    * The queue containing the statistics to store.
57    */
58    private ArrayBlockingQueue<XWikiStatsStoreItem> queue;
59   
60    /**
61    * The thread on which the storing service is running.
62    */
63    private Thread thread;
64   
65    /**
66    * The xwiki context.
67    */
68    private XWikiContext xwikiContext;
69   
70    /**
71    * Create new instance of XWikiStatsRegister and init statistics queue.
72    *
73    * @param context the XWiki context.
74    */
 
75  60 toggle public XWikiStatsStoreService(XWikiContext context)
76    {
77  60 this.xwikiContext = context.clone();
78  60 long queueSize = context.getWiki().ParamAsLong("stats.queue.size", 200);
79  60 this.queue = new ArrayBlockingQueue<XWikiStatsStoreItem>((int) queueSize);
80    }
81   
 
82  60 toggle @Override
83    protected void declareProperties(ExecutionContext executionContext)
84    {
85  60 this.xwikiContext.declareInExecutionContext(executionContext);
86  60 this.xwikiContext = null;
87    }
88   
89    /**
90    * Start storing thread.
91    */
 
92  60 toggle public void start()
93    {
94  60 if (this.thread == null) {
95  60 this.thread = new Thread(this, "Statistics storing daemon");
96    // The JVM should be allowed to shutdown while this thread is running
97  60 this.thread.setDaemon(true);
98  60 this.thread.start();
99    }
100    }
101   
102    /**
103    * Stop storing thread.
104    */
 
105  0 toggle public void stop()
106    {
107  0 this.queue.clear();
108  0 try {
109  0 this.queue.put(new StopStatsRegisterObject());
110  0 this.thread.join();
111  0 this.thread = null;
112    } catch (InterruptedException e) {
113  0 if (LOGGER.isWarnEnabled()) {
114  0 LOGGER.warn("Thread join has been interrupted", e);
115    }
116    }
117    }
118   
 
119  60 toggle @Override
120    public void runInternal()
121    {
122  60 try {
123  60 while (true) {
124  60 register();
125    }
126    } catch (InterruptedException e) {
127  0 if (LOGGER.isWarnEnabled()) {
128  0 LOGGER.warn("Statistics storing thread has been interrupted.", e);
129    }
130    } catch (StopStatsStoreException e) {
131  0 if (LOGGER.isInfoEnabled()) {
132  0 LOGGER.warn("Statistics storing thread received stop order.", e);
133    }
134    }
135    }
136   
137    /**
138    * Store the statistics in the queue.
139    *
140    * @throws InterruptedException thread has been interrupted.
141    * @throws StopStatsStoreException service received stop order.
142    */
 
143  60 toggle private void register() throws InterruptedException, StopStatsStoreException
144    {
145  60 XWikiStatsStoreItem stat = this.queue.take();
146   
147  0 List<List<XWikiStatsStoreItem>> statsList = new ArrayList<List<XWikiStatsStoreItem>>();
148  0 Map<String, List<XWikiStatsStoreItem>> statsMap = new HashMap<String, List<XWikiStatsStoreItem>>();
149   
150  0 do {
151  0 if (stat instanceof StopStatsRegisterObject) {
152  0 throw new StopStatsStoreException();
153    }
154   
155  0 String statId = stat.getId();
156   
157  0 List<XWikiStatsStoreItem> stats = statsMap.get(statId);
158   
159  0 if (stats == null) {
160  0 stats = new ArrayList<XWikiStatsStoreItem>();
161   
162  0 statsMap.put(statId, stats);
163  0 statsList.add(stats);
164    }
165   
166  0 stats.add(stat);
167   
168  0 stat = this.queue.poll();
169  0 } while (stat != null);
170   
171  0 for (List<XWikiStatsStoreItem> stats : statsList) {
172  0 stats.get(0).store(stats);
173    }
174    }
175   
176    // ////////////////////////////////////////////////////////////////////////////
177    // Add stats to queue
178    // ////////////////////////////////////////////////////////////////////////////
179   
180    /**
181    * Add new statistic to store.
182    *
183    * @param statsRegisterItem the statistic store item.
184    */
 
185  0 toggle public void add(XWikiStatsStoreItem statsRegisterItem)
186    {
187  0 try {
188  0 this.queue.put(statsRegisterItem);
189    } catch (InterruptedException e) {
190  0 LOGGER.error("Statistics storage thread has been interrupted", e);
191    }
192    }
193   
194    /**
195    * Add all the statistics to the save queue.
196    *
197    * @param doc the document.
198    * @param action the user action.
199    * @param context the XWiki context.
200    */
 
201  0 toggle public void addStats(XWikiDocument doc, String action, XWikiContext context)
202    {
203  0 VisitStats vobject = StatsUtil.findVisit(context);
204  0 synchronized (vobject) {
205  0 if (action.equals(ViewAction.VIEW_ACTION)) {
206    // We count page views in the sessions only for the "view" action
207  0 vobject.incPageViews();
208  0 } else if (action.equals(SaveAction.ACTION_NAME)) {
209    // We count "save" and "download" actions separately
210  0 vobject.incPageSaves();
211  0 } else if (action.equals(DownloadAction.ACTION_NAME)) {
212    // We count "save" and "download" actions separately
213  0 vobject.incDownloads();
214    }
215   
216  0 addVisitStats(vobject, context);
217   
218  0 boolean isVisit = (vobject.getPageViews() == 1) && (action.equals(ViewAction.VIEW_ACTION));
219   
220  0 addDocumentStats(doc, action, isVisit, context);
221    }
222   
223    // In case of a "view" action we want to store referer info
224  0 if (action.equals(ViewAction.VIEW_ACTION)) {
225  0 addRefererStats(doc, context);
226    }
227    }
228   
229    /**
230    * Add visit statistics to the save queue.
231    *
232    * @param vobject the visit statistics object.
233    * @param context the XWiki context.
234    */
 
235  0 toggle private void addVisitStats(VisitStats vobject, XWikiContext context)
236    {
237  0 Date currentDate = new Date();
238   
239  0 vobject.setEndDate(currentDate);
240  0 add(new VisitStatsStoreItem(vobject, context));
241  0 vobject.unrememberOldObject();
242    }
243   
244    /**
245    * Add document statistics to the save queue.
246    *
247    * @param doc the document.
248    * @param action the user action.
249    * @param isVisit indicate if it's included in a visit.
250    * @param context the XWiki context.
251    */
 
252  0 toggle private void addDocumentStats(XWikiDocument doc, String action, boolean isVisit, XWikiContext context)
253    {
254  0 Date currentDate = new Date();
255   
256  0 add(new DocumentStatsStoreItem(doc.getFullName(), currentDate, StatsUtil.PeriodType.MONTH, action, isVisit,
257    context));
258  0 add(new DocumentStatsStoreItem(doc.getSpace(), currentDate, StatsUtil.PeriodType.MONTH, action, isVisit,
259    context));
260  0 add(new DocumentStatsStoreItem("", currentDate, StatsUtil.PeriodType.MONTH, action, false, context));
261  0 add(new DocumentStatsStoreItem(doc.getFullName(), currentDate, StatsUtil.PeriodType.DAY, action, isVisit,
262    context));
263  0 add(new DocumentStatsStoreItem(doc.getSpace(), currentDate, StatsUtil.PeriodType.DAY, action, isVisit,
264    context));
265  0 add(new DocumentStatsStoreItem("", currentDate, StatsUtil.PeriodType.DAY, action, false, context));
266    }
267   
268    /**
269    * Add referer statistics to the save queue.
270    *
271    * @param doc the document.
272    * @param context the XWiki context.
273    */
 
274  0 toggle private void addRefererStats(XWikiDocument doc, XWikiContext context)
275    {
276  0 String referer = StatsUtil.getReferer(context);
277  0 if ((referer != null) && (!referer.equals(""))) {
278  0 add(new RefererStatsStoreItem(doc.getFullName(), new Date(), StatsUtil.PeriodType.MONTH, referer, context));
279    }
280    }
281    }
282   
283    /**
284    * Item used to stop the statistics storing.
285    *
286    * @version $Id: 56d5668802f42fd93ffa20663e0e96cd435b6a7b $
287    */
 
288    class StopStatsRegisterObject implements XWikiStatsStoreItem
289    {
 
290  0 toggle @Override
291    public String getId()
292    {
293  0 return null;
294    }
295   
 
296  0 toggle @Override
297    public void store(List<XWikiStatsStoreItem> register)
298    {
299    }
300    }
301   
302    /**
303    * Used to order stopping storing thread.
304    *
305    * @version $Id: 56d5668802f42fd93ffa20663e0e96cd435b6a7b $
306    */
 
307    class StopStatsStoreException extends Exception
308    {
309   
310    }