/*
* Copyright 2009 VoidSearch.com
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package com.voidsearch.voidbase.storage.queuetree;
import com.voidsearch.voidbase.serialization.VoidBaseSerialization;
import com.voidsearch.voidbase.storage.StorageOperationHooks;
import com.voidsearch.voidbase.apps.queuetree.protocol.QueueTreeProtocol;
import com.voidsearch.voidbase.util.VoidBaseUtil;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.ArrayList;
public class QueueTreeHooks implements StorageOperationHooks {
public static void handlePut(QueueMetadata metadata, ArrayBlockingQueue queue, Object value) {
if (metadata.getType().equals(VoidBaseSerialization.NUMERIC)) {
try {
dupValue(metadata,value);
updateMinMax(metadata,value);
updateAverage(metadata,queue,value);
updateVariance(metadata,queue,value);
//testUpdate(metadata,queue,value);
} catch (NumberFormatException e) {
e.printStackTrace();
}
}
else if (metadata.getType().equals(VoidBaseSerialization.NUMERIC_TUPLE)) {
try {
updateMinMaxMultipleDimensions(metadata,value);
updateAverageMultipleDimensions(metadata,queue,value);
updateVarianceMultipleDimensions(metadata,queue,value);
updateStandardDeviationMultipleDimensions(metadata);
updateCovariance(metadata,queue,value);
updateCorrelation(metadata);
} catch (NumberFormatException e) {
e.printStackTrace();
}
}
}
// copy value to metadata
public static void dupValue(QueueMetadata metadata, Object value) throws NumberFormatException {
metadata.set(QueueTreeProtocol.CURRENT,value);
}
// update minimum and maximum for single value
public static void updateMinMax(QueueMetadata metadata, Object value) throws NumberFormatException {
double val = VoidBaseSerialization.getDouble(value);
// update min
if (metadata.contains(QueueTreeProtocol.MIN)) {
double min = VoidBaseSerialization.getDouble(metadata.get(QueueTreeProtocol.MIN));
if (val < min)
metadata.set(QueueTreeProtocol.MIN, val);
}
else {
metadata.set(QueueTreeProtocol.MIN, val);
}
// update max
if (metadata.contains(QueueTreeProtocol.MAX)) {
double max = VoidBaseSerialization.getDouble(metadata.get(QueueTreeProtocol.MAX));
if (val > max)
metadata.set(QueueTreeProtocol.MAX, val);
}
else {
metadata.set(QueueTreeProtocol.MAX, val);
}
}
// update average value
public static void updateAverage(QueueMetadata metadata, ArrayBlockingQueue queue, Object value) throws NumberFormatException {
double val = VoidBaseSerialization.getDouble(value);
if (metadata.contains(QueueTreeProtocol.AVG)) {
double avg = (Double) metadata.get(QueueTreeProtocol.AVG);
int numElems = queue.size();
avg = (avg * (numElems - 1) + val) / queue.size();
metadata.set(QueueTreeProtocol.AVG, avg);
}
else {
metadata.set(QueueTreeProtocol.AVG, val);
}
}
// update variance
public static void updateVariance(QueueMetadata metadata, ArrayBlockingQueue queue, Object value) throws NumberFormatException {
double val = VoidBaseSerialization.getDouble(value);
if (metadata.contains(QueueTreeProtocol.VAR)) {
if (metadata.contains(QueueTreeProtocol.AVG)) {
double avg = (Double) metadata.get(QueueTreeProtocol.AVG);
double var = (Double) metadata.get(QueueTreeProtocol.VAR);
int numElems = queue.size();
var = var + (Math.pow((val - avg), 2) / (numElems - 1));
metadata.set(QueueTreeProtocol.VAR, var);
}
else {
metadata.set(QueueTreeProtocol.VAR, 0.0);
}
}
else {
metadata.set(QueueTreeProtocol.VAR, 0.0);
}
}
public static void testUpdate(QueueMetadata metadata, ArrayBlockingQueue queue, Object value) throws NumberFormatException {
double val = VoidBaseSerialization.getDouble(value);
metadata.set("test",Math.sqrt(val));
}
// update deviation
public static void updateDeviation(QueueMetadata metadata) throws NumberFormatException {
if (metadata.contains(QueueTreeProtocol.VAR)) {
double var = (Double)metadata.get(QueueTreeProtocol.VAR);
metadata.set(QueueTreeProtocol.DEVIATION,Math.sqrt(var));
}
}
// update minimum and maximum for multiple dimensions
public static void updateMinMaxMultipleDimensions(QueueMetadata metadata, Object value) throws NumberFormatException {
ArrayList<Double> valArray = VoidBaseSerialization.getDoubleArray(value);
// update min
if (metadata.contains(QueueTreeProtocol.MIN)) {
ArrayList<Double> minArray = VoidBaseSerialization.getDoubleArray(metadata.get(QueueTreeProtocol.MIN));
int cnt = 0;
for (double val: valArray) {
if (val < minArray.get(cnt))
minArray.set(cnt,val);
cnt++;
}
metadata.set(QueueTreeProtocol.MIN, minArray);
} else {
metadata.set(QueueTreeProtocol.MIN, VoidBaseUtil.getZeroDoubleArray(valArray.size()));
}
// update max
if (metadata.contains(QueueTreeProtocol.MAX)) {
ArrayList<Double> maxArray = VoidBaseSerialization.getDoubleArray(metadata.get(QueueTreeProtocol.MAX));
int cnt = 0;
for (double val: valArray) {
if (val > maxArray.get(cnt))
maxArray.set(cnt,val);
cnt++;
}
metadata.set(QueueTreeProtocol.MAX, maxArray);
} else {
metadata.set(QueueTreeProtocol.MAX, VoidBaseUtil.getZeroDoubleArray(valArray.size()));
}
}
// update average value
public static void updateAverageMultipleDimensions(QueueMetadata metadata, ArrayBlockingQueue queue, Object value) throws NumberFormatException {
ArrayList<Double> valArray = VoidBaseSerialization.getDoubleArray(value);
if (metadata.contains(QueueTreeProtocol.AVG)) {
ArrayList<Double> avgArray = VoidBaseSerialization.getDoubleArray(metadata.get(QueueTreeProtocol.AVG));
int numElems = queue.size();
for (int i=0; i<valArray.size(); i++) {
double avg = (avgArray.get(i) * (numElems - 1) + valArray.get(i)) / queue.size();
avgArray.set(i,avg);
}
metadata.set(QueueTreeProtocol.AVG, avgArray);
}
else {
metadata.set(QueueTreeProtocol.AVG, VoidBaseUtil.getZeroDoubleArray(valArray.size()));
}
}
// update variance
public static void updateVarianceMultipleDimensions(QueueMetadata metadata, ArrayBlockingQueue queue, Object value) throws NumberFormatException {
ArrayList<Double> valArray = VoidBaseSerialization.getDoubleArray(value);
if (metadata.contains(QueueTreeProtocol.VAR)) {
if (metadata.contains(QueueTreeProtocol.AVG)) {
ArrayList<Double> avgArray = VoidBaseSerialization.getDoubleArray(metadata.get(QueueTreeProtocol.AVG));
ArrayList<Double> varArray = VoidBaseSerialization.getDoubleArray(metadata.get(QueueTreeProtocol.VAR));
int numElems = queue.size();
for (int i=0; i<valArray.size(); i++) {
double var = varArray.get(i) + (Math.pow((valArray.get(i) - avgArray.get(i)), 2) / (numElems - 1));
varArray.set(i,var);
}
metadata.set(QueueTreeProtocol.VAR, varArray);
}
else {
metadata.set(QueueTreeProtocol.VAR, VoidBaseUtil.getZeroDoubleArray(valArray.size()));
}
}
else {
metadata.set(QueueTreeProtocol.VAR, VoidBaseUtil.getZeroDoubleArray(valArray.size()));
}
}
// update standard deviation
public static void updateStandardDeviationMultipleDimensions(QueueMetadata metadata) {
if (metadata.contains(QueueTreeProtocol.VAR)) {
ArrayList<Double> varArray = VoidBaseSerialization.getDoubleArray(metadata.get(QueueTreeProtocol.VAR));
ArrayList<Double> deviation = new ArrayList<Double>();
for (Double val : varArray) {
deviation.add(Math.sqrt(val));
}
metadata.set(QueueTreeProtocol.DEVIATION, deviation);
}
}
// update variance
public static void updateCovariance(QueueMetadata metadata, ArrayBlockingQueue queue, Object value) throws NumberFormatException {
ArrayList<Double> valArray = VoidBaseSerialization.getDoubleArray(value);
if (metadata.contains(QueueTreeProtocol.COVARIANCE)
&& metadata.contains(QueueTreeProtocol.AVG)) {
double cov = (Double) metadata.get(QueueTreeProtocol.COVARIANCE);
ArrayList<Double> avgArray = VoidBaseSerialization.getDoubleArray(metadata.get(QueueTreeProtocol.AVG));
int numElems = queue.size();
if (numElems > 2) {
double covProduct = 1.0;
for (int i=0; i<valArray.size(); i++) {
covProduct *= (valArray.get(i) - avgArray.get(i));
}
metadata.set(QueueTreeProtocol.COVARIANCE, (cov*(numElems -2) + covProduct)/(numElems -1));
}
}
else {
metadata.set(QueueTreeProtocol.COVARIANCE, 0.0);
}
}
// update standard deviation
public static void updateCorrelation(QueueMetadata metadata) {
if (metadata.contains(QueueTreeProtocol.COVARIANCE)
&& metadata.contains(QueueTreeProtocol.VAR)) {
double corr = (Double) metadata.get(QueueTreeProtocol.COVARIANCE);
ArrayList<Double> varArray = VoidBaseSerialization.getDoubleArray(metadata.get(QueueTreeProtocol.VAR));
double deviationDenominator = 1.0;
for (Double val : varArray) {
deviationDenominator *= val;
}
metadata.set(QueueTreeProtocol.CORRELATION, corr/deviationDenominator);
}
}
}