View Javadoc
1   package net.sf.appstatus.batch;
2   
3   import java.util.ArrayList;
4   import java.util.Calendar;
5   import java.util.Date;
6   import java.util.List;
7   import java.util.Properties;
8   import java.util.Vector;
9   
10  import org.apache.commons.lang3.StringUtils;
11  import org.slf4j.Logger;
12  import org.slf4j.LoggerFactory;
13  
14  import net.sf.appstatus.core.batch.IBatch;
15  import net.sf.appstatus.core.batch.IBatchManager;
16  import net.sf.appstatus.core.batch.IBatchProgressMonitor;
17  
18  /**
19   * This implementation stores batch history and status in memory.
20   * <p>
21   * Can be used when batch is run within the same JVM as the console.
22   * <p>
23   * History is lost on restart.
24   *
25   * @author Nicolas Richeton
26   *
27   */
28  public class InProcessBatchManager implements IBatchManager {
29  
30  	private static Logger logger = LoggerFactory.getLogger(InProcessBatchManager.class);
31  
32  	private List<IBatch> errorBatches = new Vector<IBatch>();
33  
34  	List<IBatch> finishedBatches = new Vector<IBatch>();
35  	private int logInterval = 1000;
36  	private long maxSize = 25;
37  	List<IBatch> runningBatches = new Vector<IBatch>();
38  
39  	private int zombieInterval;
40  
41  	public IBatch addBatch(String name, String group, String uuid) {
42  
43  		// Add batch
44  		IBatch b = new Batch(uuid, name, group);
45  		((Batch) b).setZombieInterval(this.zombieInterval);
46  
47  		int currentPosition = runningBatches.indexOf(b);
48  		if (currentPosition >= 0) {
49  			// Reuse existing object (and keep monitor).
50  			b = runningBatches.get(currentPosition);
51  		} else {
52  			// Add new batch
53  
54  			// initMonitor
55  			getMonitor(b);
56  
57  			// runningBatches is not limited in size.
58  			runningBatches.add(b);
59  		}
60  
61  		return b;
62  	}
63  
64  	protected void addTo(List<IBatch> l, IBatch b) {
65  		// Ensure batch list does not exceed defined size
66  		if (l.size() >= maxSize) {
67  			l.remove(0);
68  		}
69  
70  		l.add(b);
71  	}
72  
73  	public void batchEnd(Batch batch) {
74  		runningBatches.remove(batch);
75  		addTo(finishedBatches, batch);
76  
77  		if (!batch.isSuccess()) {
78  			addTo(errorBatches, batch);
79  		}
80  	}
81  
82  	public List<IBatch> getBatches(String group, String name) {
83  		List<IBatch> result = new ArrayList<IBatch>();
84  
85  		for (IBatch b : runningBatches) {
86  			if (StringUtils.equals(group, b.getGroup()) && StringUtils.equals(name, b.getName())) {
87  				result.add(b);
88  			}
89  		}
90  
91  		for (IBatch b : finishedBatches) {
92  			if (StringUtils.equals(group, b.getGroup()) && StringUtils.equals(name, b.getName())) {
93  				result.add(b);
94  			}
95  		}
96  
97  		return result;
98  	}
99  
100 	public Properties getConfiguration() {
101 		return null;
102 	}
103 
104 	public List<IBatch> getErrorBatches() {
105 		return errorBatches;
106 	}
107 
108 	public List<IBatch> getFinishedBatches() {
109 		return finishedBatches;
110 	}
111 
112 	public IBatchProgressMonitor getMonitor(IBatch batch) {
113 		Batch b = (Batch) batch;
114 		// If batch has no progress monitor, create one.
115 		if (b.getProgressMonitor() == null) {
116 			// Calling this method automatically call
117 			// IBatch#setProgressMonitor()
118 			InProcessBatchProgressMonitor pm = new InProcessBatchProgressMonitor(batch.getUuid(), batch, this);
119 			pm.setWritingDelay(logInterval);
120 		}
121 
122 		// Return current monitor.
123 		return b.getProgressMonitor();
124 	}
125 
126 	public List<IBatch> getRunningBatches() {
127 		return runningBatches;
128 	}
129 
130 	public void init() {
131 	}
132 
133 	/*
134 	 * (non-Javadoc)
135 	 *
136 	 * @see net.sf.appstatus.core.batch.IBatchManager#removeAllBatches(int)
137 	 */
138 	public void removeAllBatches(int scope) {
139 
140 		if (finishedBatches == null || finishedBatches.size() == 0) {
141 			// Nothing can be removed using scoped.
142 			return;
143 		}
144 
145 		ArrayList<IBatch> toRemove = new ArrayList<IBatch>();
146 		switch (scope) {
147 		case REMOVE_SUCCESS:
148 			for (IBatch b : finishedBatches) {
149 				if (b.isSuccess() && (b.getRejectedItemsId() == null || b.getRejectedItemsId().size() == 0)) {
150 					toRemove.add(b);
151 				}
152 			}
153 			break;
154 
155 		case REMOVE_OLD:
156 			// Create reference date.
157 			Calendar c = Calendar.getInstance();
158 			c.add(Calendar.MONTH, -6);
159 			Date thisIsOld = c.getTime();
160 
161 			for (IBatch b : finishedBatches) {
162 				if (b.getLastUpdate().before(thisIsOld)) {
163 					toRemove.add(b);
164 				}
165 			}
166 			break;
167 		}
168 
169 		// Remove all batches marked for deletion.
170 		for (IBatch b : toRemove) {
171 			removeBatch(b);
172 		}
173 
174 	}
175 
176 	private void removeBatch(IBatch b) {
177 
178 		// Remove only finished jobs
179 		if (!runningBatches.contains(b)) {
180 
181 			// remove from errorBatches
182 			if (errorBatches.contains(b)) {
183 				errorBatches.remove(b);
184 			}
185 
186 			// Remove from finished batches.
187 			if (finishedBatches.contains(b)) {
188 				finishedBatches.remove(b);
189 			}
190 		}
191 	}
192 
193 	/*
194 	 * (non-Javadoc)
195 	 *
196 	 * @see
197 	 * net.sf.appstatus.core.batch.IBatchManager#removeBatch(net.sf.appstatus
198 	 * .core.batch.IBatch)
199 	 */
200 	public void removeBatch(String uuid) {
201 		Batch b = new Batch(uuid);
202 		removeBatch(b);
203 	}
204 
205 	public void setConfiguration(Properties configuration) {
206 		try {
207 
208 			logInterval = Integer.parseInt(configuration.getProperty("batch.logInterval"));
209 		} catch (NumberFormatException e) {
210 			logInterval = 1000;
211 		}
212 		logger.info("Batch log interval: {}ms", logInterval);
213 
214 		try {
215 			maxSize = Integer.parseInt(configuration.getProperty("batch.maxHistory"));
216 		} catch (NumberFormatException e) {
217 			maxSize = 25;
218 		}
219 		logger.info("Batch history size: {}", maxSize);
220 
221 		try {
222 			zombieInterval = Integer.parseInt(configuration.getProperty("batch.zombieInterval"));
223 		} catch (NumberFormatException e) {
224 			zombieInterval = 1000 * 60 * 10;
225 		}
226 		logger.info("Zombie interval: {}", zombieInterval);
227 
228 	}
229 }