1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23 package org.diyefi.openlogviewer.genericlog;
24
25 import java.beans.PropertyChangeEvent;
26 import java.beans.PropertyChangeListener;
27 import java.beans.PropertyChangeSupport;
28 import java.util.LinkedHashMap;
29 import java.util.Iterator;
30 import org.diyefi.openlogviewer.OpenLogViewer;
31
32 public class GenericLog extends LinkedHashMap<String, GenericDataElement> {
33 private static final long serialVersionUID = 1L;
34
35
36
37 private static final String LOG_LOADED_TEXT = "LogLoaded";
38 public static final int LOG_NOT_LOADED = -1;
39 public static final int LOG_LOADING = 0;
40 public static final int LOG_LOADED = 1;
41
42
43 public static final String recordCountKey = "OLV Record Count";
44 public static final String tempResetKey = "OLV Temp Resets";
45 public static final String elapsedTimeKey = "OLV Elapsed Time";
46 private static final int NUMBER_OF_BUILTIN_FIELDS = 3;
47 private static final int RECORD_COUNT_OFFSET = 0;
48 private static final int TEMP_RESET_OFFSET = 1;
49 private static final int ELAPSED_TIME_OFFSET = 2;
50 private static final int SIZE_OF_DOUBLE = 8;
51 private static final int NUMBER_OF_BYTES_IN_A_MEG = 1000000;
52 private GenericDataElement recordCountElement;
53
54 private String metaData;
55 protected final PropertyChangeSupport PCS;
56 private int logStatus;
57 private String logStatusMessage = null;
58
59
60 private int currentCapacity;
61 private int currentPosition = -1;
62
63 private int ourLoadFactor;
64 private int numberOfInternalHeaders;
65
66 private final PropertyChangeListener autoLoad = new PropertyChangeListener() {
67 public void propertyChange(final PropertyChangeEvent propertyChangeEvent) {
68 if ((Integer) propertyChangeEvent.getNewValue() == 0) {
69 final GenericLog genLog = (GenericLog) propertyChangeEvent.getSource();
70 genLog.setLogStatus(GenericLog.LOG_LOADING);
71 OpenLogViewer.getInstance().setLog(genLog);
72 } else if ((Integer) propertyChangeEvent.getNewValue() == 1) {
73 final GenericLog genLog = (GenericLog) propertyChangeEvent.getSource();
74 genLog.setLogStatus(GenericLog.LOG_LOADED);
75 OpenLogViewer.getInstance().setLog(genLog);
76 OpenLogViewer.getInstance().getOptionFrame().updateFromLog(genLog);
77 }
78 }
79 };
80
81
82
83
84
85
86 public GenericLog(final String[] headers, final int initialCapacity, final int ourLoadFactor) {
87 super(1 + (headers.length + NUMBER_OF_BUILTIN_FIELDS), 1.0f);
88
89 GenericDataElement.resetPosition();
90 logStatus = LOG_NOT_LOADED;
91 PCS = new PropertyChangeSupport(this);
92 addPropertyChangeListener(LOG_LOADED_TEXT, autoLoad);
93 metaData = "";
94
95 this.ourLoadFactor = ourLoadFactor;
96 currentCapacity = initialCapacity;
97
98
99 numberOfInternalHeaders = headers.length + NUMBER_OF_BUILTIN_FIELDS;
100 final String[] internalHeaders = new String[numberOfInternalHeaders];
101 for (int i = 0; i < headers.length; i++) {
102 internalHeaders[i] = headers[i];
103 }
104
105
106 internalHeaders[headers.length + RECORD_COUNT_OFFSET] = recordCountKey;
107 internalHeaders[headers.length + TEMP_RESET_OFFSET] = tempResetKey;
108 internalHeaders[headers.length + ELAPSED_TIME_OFFSET] = elapsedTimeKey;
109
110 for (int x = 0; x < internalHeaders.length; x++) {
111 GenericDataElement GDE = new GenericDataElement(initialCapacity);
112 GDE.setName(internalHeaders[x]);
113 this.put(internalHeaders[x], GDE);
114 }
115
116 recordCountElement = this.get(recordCountKey);
117 }
118
119
120
121
122
123
124
125 public final void addValue(final String key, final double value) {
126 this.get(key).add(value);
127 }
128
129 public final void incrementPosition() {
130 currentPosition++;
131 GenericDataElement.incrementPosition();
132 if(currentPosition >= currentCapacity){
133 System.out.println(OpenLogViewer.NEWLINE + "############## Memory about to be resized! ##############");
134 final long startResizes = System.currentTimeMillis();
135 System.out.println("Old capacity = " + currentCapacity);
136 Runtime ourRuntime = Runtime.getRuntime();
137
138 System.out.println("Memory Before = Max: " + ourRuntime.maxMemory() + ", Free: " + ourRuntime.freeMemory() + ", Total: " + ourRuntime.totalMemory());
139
140 int numberResized = 0;
141 final Iterator<GenericDataElement> genLogIterator = this.values().iterator();
142 while (genLogIterator.hasNext()) {
143
144 final long overheadInMemory = currentCapacity * SIZE_OF_DOUBLE;
145 final long increaseInMemory = overheadInMemory * ourLoadFactor;
146
147
148
149 final long requiredMemory = 2 * (increaseInMemory + overheadInMemory);
150 final long availableMemory = ourRuntime.freeMemory();
151
152 if(availableMemory < requiredMemory) {
153 currentPosition--;
154 final String jvmHelp = "Get more with -Xms and -Xmx JVM options!";
155 System.out.println("Detected impending out-of-memory doom! Details below! :-(");
156 System.out.println("Total" + "Available: " + availableMemory + " Required: " + requiredMemory + " Increase: " + increaseInMemory + " Overhead: " + overheadInMemory);
157 System.out.println(jvmHelp);
158 final long allocatedMemory = (ourRuntime.maxMemory() / NUMBER_OF_BYTES_IN_A_MEG);
159 throw new RuntimeException(allocatedMemory + "MB is insufficent memory to increase log size! " + jvmHelp + OpenLogViewer.NEWLINE +
160 "Completed " + numberResized + " of " + numberOfInternalHeaders +
161 " while increasing from " + currentCapacity + " records to "+ (currentCapacity * ourLoadFactor) + " records!");
162 }
163
164 final GenericDataElement dataElement = genLogIterator.next();
165 dataElement.increaseCapacity(ourLoadFactor);
166 numberResized++;
167 }
168 currentCapacity *= ourLoadFactor;
169
170 System.out.println("Memory After = Max: " + ourRuntime.maxMemory() + ", Free: " + ourRuntime.freeMemory() + ", Total: " + ourRuntime.totalMemory());
171
172 final long finishResizes = System.currentTimeMillis();
173 System.out.println("New capacity = " + currentCapacity);
174 System.out.println("Resizes took " + (finishResizes - startResizes) + " ms");
175 }
176
177 recordCountElement.add((double) currentPosition);
178 }
179
180
181
182
183
184 public final void setLogStatus(final int newLogStatus) {
185 int oldLogStatus = this.logStatus;
186 this.logStatus = newLogStatus;
187 PCS.firePropertyChange(LOG_LOADED_TEXT, oldLogStatus, newLogStatus);
188 }
189
190
191
192
193
194 public final int getLogStatus() {
195 return this.logStatus;
196 }
197
198
199
200
201
202
203 public final void setMetaData(final String md) {
204 metaData = md;
205 }
206
207
208
209
210
211 public final String getMetadata() {
212 return metaData;
213 }
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228 public final void addPropertyChangeListener(final String name, final PropertyChangeListener listener) {
229 PCS.addPropertyChangeListener(name, listener);
230 }
231
232
233
234
235
236
237 public final void removePropertyChangeListener(final String propertyName, final PropertyChangeListener listener) {
238 PCS.removePropertyChangeListener(propertyName, listener);
239 }
240
241 public final String getLogStatusMessage() {
242 return logStatusMessage;
243 }
244
245 public void setLogStatusMessage(String message) {
246 this.logStatusMessage = message;
247 }
248
249 public final int getRecordCount() {
250 return currentPosition;
251 }
252
253 public final void clearOut() {
254 final Iterator<GenericDataElement> lastRound = this.values().iterator();
255 while (lastRound.hasNext()) {
256 lastRound.next().clearOut();
257 }
258 this.clear();
259 }
260 }