use of net.sourceforge.processdash.data.SaveableData in project processdash by dtuma.
the class DataRepository method getInheritableValue.
/** @since 2.0.9 */
public static SaveableData getInheritableValue(DataContext ctx, StringBuffer prefix_, String name) {
String prefix = prefix_.toString();
String dataName = prefix + "/" + name;
SaveableData result = ctx.getValue(dataName);
int pos;
while (result == null && prefix.length() > 0) {
pos = prefix.lastIndexOf('/');
if (pos == -1)
prefix = "";
else
prefix = prefix.substring(0, pos);
dataName = prefix + "/" + name;
result = ctx.getValue(dataName);
}
if (result != null)
prefix_.setLength(prefix.length());
return result;
}
use of net.sourceforge.processdash.data.SaveableData in project processdash by dtuma.
the class DataRepository method mountData.
void mountData(DataFile dataFile, String dataPrefix, Map values) throws InvalidDatafileFormat {
try {
startInconsistency();
boolean registerDataNames = false;
String datafilePath = "internal data";
boolean fileEditable = true;
// if this is a regular file,
if (dataFile != null && dataFile.file != null) {
datafilePath = dataFile.file.getPath();
fileEditable = dataFile.canWrite && Settings.isReadWrite();
// register the names of data elements in this file IF it is
// not global data.
registerDataNames = dataPrefix.length() > 0;
}
Map defaultData = dataFile.inheritedDefinitions;
if (defaultData == null)
defaultData = Collections.EMPTY_MAP;
boolean successful = false;
boolean datafileModified = false;
int retryCount = 10;
while (!successful && retryCount-- > 0) try {
// values map.
for (Iterator i = values.entrySet().iterator(); i.hasNext(); ) {
Map.Entry defn = (Map.Entry) i.next();
String localName = (String) defn.getKey();
Object valueObj = defn.getValue();
String dataName = createDataName(dataPrefix, localName);
SaveableData o = instantiateValue(dataName, dataPrefix, valueObj, !fileEditable);
if (o instanceof MalformedData)
logger.warning("Data value for '" + dataName + "' in file '" + datafilePath + "' is malformed.");
DataElement d = (DataElement) data.get(dataName);
if (d == null) {
boolean isDefaultName = defaultData.containsKey(localName);
if (o != null || isDefaultName) {
try {
add(dataName, isDefaultName, o, IS_NOT_DEFAULT_VAL, dataFile, DO_NOTIFY);
} catch (DataElementAlreadyExistsException e) {
d = e.elem;
}
}
}
if (d != null) {
putValue(dataName, o, IS_NOT_DEFAULT_VAL, NOT_MODIFYING_DATAFILE);
d = (DataElement) data.get(dataName);
if (d != null) {
d.datafile = dataFile;
d.isDefaultName = defaultData.containsKey(localName);
}
}
if (registerDataNames && (o instanceof DoubleData || o instanceof CompiledFunction))
dataElementNameSet.add(localName);
}
// Next, handle the default values that this datafile inherits.
String dataPrefixSlash = dataPrefix + "/";
for (Iterator i = defaultData.entrySet().iterator(); i.hasNext(); ) {
Map.Entry defn = (Map.Entry) i.next();
String localName = (String) defn.getKey();
Object valueObj = defn.getValue();
// name, do nothing.
if (values.containsKey(localName))
continue;
// Ignore renaming operations; they are not relevant.
if (valueObj instanceof DataRenamingOperation)
continue;
boolean shouldCreateEagerly = shouldCreateEagerly(valueObj);
if ("@now".equals(valueObj))
shouldCreateEagerly = datafileModified = true;
String dataName = dataPrefixSlash + localName;
DataElement d = (DataElement) data.get(dataName);
if (d == null) {
if (shouldCreateEagerly) {
// the item doesn't exist, but we should create it anyway.
SaveableData o = instantiateValue(dataName, dataPrefix, valueObj, !fileEditable);
if (o != null) {
try {
add(dataName, IS_DEFAULT_NAME, o, IS_DEFAULT_VAL, dataFile, DO_NOT_NOTIFY);
} catch (DataElementAlreadyExistsException e) {
d = e.elem;
}
}
}
}
if (d != null) {
// a matching data element exists.
d.datafile = dataFile;
d.isDefaultName = true;
dataName = d.name;
if (instantiatedDataMatches(valueObj, d.getValue())) {
// the data element already has the proper value. (This
// will be common, as clients registering data listeners
// will cause lazy data to spring to life even as this
// for loop is executing.) Nothing needs to be done.
} else if (!d.hasListeners()) {
// This element has the wrong value, but no one is
// listening to it. Revert the element to a lazy
// default value.
janitor.cleanup(d);
} else {
// This element has the wrong value, and clients are
// listening to it. Create and save the correct value.
SaveableData o = instantiateValue(dataName, dataPrefix, valueObj, !fileEditable);
putValue(dataName, o, IS_DEFAULT_VAL, NOT_MODIFYING_DATAFILE);
}
}
// send an event stating that the element is added. (Elsewhere in
// DataRepository, added events are never sent for data elements
// with default names (because it cannot tell whether the item is
// springing forth for the first time, or a subsequent time).
repositoryListenerList.dispatchAdded(dataName);
if (registerDataNames && (valueObj instanceof DoubleData || valueObj instanceof CompiledScript))
dataElementNameSet.add(localName);
}
// make a call to getID. We don't need the resulting value, but
// having made the call will cause an ID to be mapped for this
// prefix. This is necessary to allow users to bring up HTML pages
// from their browser's history or bookmark list.
getID(dataPrefix);
if (defaultData == globalDataDefinitions)
globalDataIsMounted = true;
if (datafileModified)
datafileModified(dataFile);
successful = true;
} catch (Throwable e) {
if (retryCount > 0) {
// Try again to open this datafile. Most errors are transient,
// caused by incredibly infrequent thread-related problems.
logger.log(Level.WARNING, "when opening " + datafilePath + " caught error; retrying.", e);
} else {
// We've done our best, but after 10 tries, we still can't open
// this datafile. Give up and throw an exception.
dataFile.invalidate();
closeDatafile(dataPrefix);
throw new InvalidDatafileFormat("Caught unexpected exception " + e);
}
}
} finally {
finishInconsistency();
}
}
use of net.sourceforge.processdash.data.SaveableData in project processdash by dtuma.
the class SearchFunction method dataAdded.
public void dataAdded(String dataName) {
String dataPrefix = getTagPrefix(dataName);
if (dataPrefix == null)
return;
/*
if (eventThreads.add(Thread.currentThread()) == false)
return; // Guard against infinite loops.
*/
if (script == null) {
// Listen for changes to the data value.
data.addActiveDataListener(dataName, this, name, false);
// element is defined, and then add it.
if (test2(data.getSimpleValue(dataName))) {
if (doAdd(dataPrefix))
doNotify();
}
} else {
// We need to see if this element matches the expression.
String condName = getAnonymousConditionName(dataPrefix);
SaveableData condition = new CompiledFunction(condName, script, data, dataPrefix);
data.putValue(condName, condition);
// Keep a list of the conditions we're watching.
condList.add(condName);
// Listen for changes to this condition expression.
data.addActiveDataListener(condName, this, name, false);
// value.
if (test(condition.getSimpleValue())) {
if (doAdd(dataPrefix))
doNotify();
}
}
eventThreads.remove(Thread.currentThread());
}
use of net.sourceforge.processdash.data.SaveableData in project processdash by dtuma.
the class DefaultTimeLoggingModel method shouldForceTimeLogEntry.
/**
* In some usage scenarios, an individual needs to mark several tasks
* complete in a row, but still reflect the fact that they "worked" on them.
* If the timer is running when the user marks a task complete, and no time
* has ever been logged against that task, round the current time log entry
* up to 1 minute if it isn't there already.
*/
private boolean shouldForceTimeLogEntry(double elapsedMinutes) {
// time log entry.
if (elapsedMinutes > 1.0)
return false;
// paused at this very moment), don't force a time log entry.
if (paused && !pauseInProgress)
return false;
// Check a user setting to see if this functionality is disabled.
if (!Settings.getBool("pauseButton.forceCompletedTaskTime", true))
return false;
// Check the data repository to see if the current task has been
// flagged as one that should never receive "forced" time log entries.
String path = currentPhase.path();
SaveableData sd = DataRepository.getInheritableValue(data, new StringBuffer(path), "Force_Completed_Task_Time");
if (sd != null && sd.getSimpleValue().test() == false)
return false;
// If time has been logged against this task in the past, don't force
// a new time log entry.
String dataName = DataRepository.createDataName(path, "Time");
if (sd != null && sd.getSimpleValue().test())
return false;
// Check to see if the current task was *just* marked complete. If so,
// force a time log entry.
dataName = DataRepository.createDataName(path, "Completed");
sd = data.getSimpleValue(dataName);
if (sd instanceof DateData) {
Date completed = ((DateData) sd).getValue();
long age = System.currentTimeMillis() - completed.getTime();
if (age < 1000) {
logger.fine("Forcing 1 minute time log entry for " + "completed task " + path);
return true;
}
}
return false;
}
use of net.sourceforge.processdash.data.SaveableData in project processdash by dtuma.
the class ProbeData method getEffectiveData.
/** Get the applicable set of historical data which was saved in
* the [PROBE_LIST] variable, if it has been set. Otherwise, return
* the default set of historical data.
*/
public static ProbeData getEffectiveData(DataRepository data, String prefix) {
String forListDataName = DataRepository.createDataName(prefix, PROBE_LIST_NAME);
SaveableData probeList = data.getValue(forListDataName);
if (probeList == null)
return new ProbeData(data, prefix, (String) null);
else
return new ProbeData(data, prefix, ListData.asListData(probeList));
}
Aggregations