001/* 002 * (C) Copyright 2006-2009 Nuxeo SAS (http://nuxeo.com/) and contributors. 003 * 004 * All rights reserved. This program and the accompanying materials 005 * are made available under the terms of the GNU Lesser General Public License 006 * (LGPL) version 2.1 which accompanies this distribution, and is available at 007 * http://www.gnu.org/licenses/lgpl.html 008 * 009 * This library is distributed in the hope that it will be useful, 010 * but WITHOUT ANY WARRANTY; without even the implied warranty of 011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 012 * Lesser General Public License for more details. 013 * 014 * Contributors: 015 * Nuxeo - initial API and implementation 016 * 017 * $Id$ 018 */ 019 020package org.nuxeo.ecm.admin.repo; 021 022import java.util.concurrent.LinkedBlockingQueue; 023import java.util.concurrent.ThreadFactory; 024import java.util.concurrent.ThreadPoolExecutor; 025import java.util.concurrent.TimeUnit; 026import java.util.concurrent.atomic.AtomicInteger; 027 028import org.nuxeo.ecm.core.api.DocumentRef; 029 030/** 031 * This class holds and manage the threads used to compute stats on the document repository 032 * 033 * @author <a href="mailto:td@nuxeo.com">Thierry Delprat</a> 034 */ 035public class RepoStat { 036 037 protected final ThreadPoolExecutor pool; 038 039 protected int nbThreads = 5; 040 041 protected final String repoName; 042 043 protected final boolean includeBlob; 044 045 protected RepoStatInfo info; 046 047 public RepoStat(String repoName, int nbThreads, boolean includeBlob) { 048 this.nbThreads = nbThreads; 049 this.repoName = repoName; 050 this.includeBlob = includeBlob; 051 pool = new ThreadPoolExecutor(nbThreads, nbThreads, 500L, TimeUnit.MILLISECONDS, 052 new LinkedBlockingQueue<Runnable>(100), new DaemonThreadFactory()); 053 } 054 055 public void exec(StatsTask task) { 056 pool.execute(task); 057 } 058 059 public void run(DocumentRef root) { 060 info = new RepoStatInfo(); 061 StatsTask task = new StatsTask(repoName, root, includeBlob, this); 062 exec(task); 063 } 064 065 protected boolean isPoolFull() { 066 return pool.getQueue().size() > 1; 067 } 068 069 public RepoStatInfo getInfo() { 070 return info; 071 } 072 073 public boolean isRunning() { 074 return pool.getActiveCount() > 0; 075 } 076 077 protected static class DaemonThreadFactory implements ThreadFactory { 078 079 private final ThreadGroup group; 080 081 private final String namePrefix; 082 083 private static final AtomicInteger poolNumber = new AtomicInteger(); 084 085 private final AtomicInteger threadNumber = new AtomicInteger(); 086 087 public DaemonThreadFactory() { 088 SecurityManager s = System.getSecurityManager(); 089 group = (s != null) ? s.getThreadGroup() : Thread.currentThread().getThreadGroup(); 090 namePrefix = "RepoStatThread-" + poolNumber.incrementAndGet() + '-'; 091 } 092 093 @Override 094 public Thread newThread(Runnable r) { 095 String name = namePrefix + threadNumber.incrementAndGet(); 096 Thread t = new Thread(group, r, name); 097 t.setDaemon(true); 098 t.setPriority(Thread.NORM_PRIORITY); 099 return t; 100 } 101 102 } 103}