org.grouplens.samantha.server.space.RedisVariableSpace.java Source code

Java tutorial

Introduction

Here is the source code for org.grouplens.samantha.server.space.RedisVariableSpace.java

Source

/*
 * Copyright (c) [2016-2017] [University of Minnesota]
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */

package org.grouplens.samantha.server.space;

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
import org.apache.commons.math3.linear.MatrixUtils;
import org.apache.commons.math3.linear.RealMatrix;
import org.apache.commons.math3.linear.RealVector;
import org.grouplens.samantha.modeler.space.SpaceMode;
import org.grouplens.samantha.modeler.space.VariableSpace;
import org.grouplens.samantha.server.common.RedisService;
import org.grouplens.samantha.server.io.IOUtilities;
import play.libs.Json;

import javax.inject.Inject;
import java.util.ArrayList;
import java.util.List;

public class RedisVariableSpace extends RedisSpace implements VariableSpace {
    private static final long serialVersionUID = 1L;

    @Inject
    public RedisVariableSpace(RedisService redisService) {
        super(redisService);
    }

    synchronized public void setSpaceState(String spaceName, SpaceMode spaceMode) {
        if (spaceMode.equals(SpaceMode.DEFAULT)) {
            spaceVersion = redisService.get(spaceName + "_" + SpaceType.INDEX.get(), spaceMode.get());
        }
        if (spaceVersion == null) {
            spaceVersion = redisService.incre(spaceName, SpaceType.VARIABLE.get()).toString();
            redisService.set(spaceName + "_" + SpaceType.VARIABLE.get(), spaceMode.get(), spaceVersion);
        }
        this.spaceMode = spaceMode;
        this.spaceName = spaceName;
        this.spaceType = SpaceType.VARIABLE;
        this.spaceIdentifier = RedisService.composeKey(spaceName + "_" + spaceType.get(), spaceVersion);
    }

    public void requestScalarVar(String name, int size, double initial, boolean randomize) {
        ObjectNode val = Json.newObject();
        val.put("name", name);
        val.put("size", size);
        val.put("initial", initial);
        val.put("randomize", randomize);
        redisService.set(spaceIdentifier, "S_" + name, val.toString());
    }

    public boolean hasScalarVar(String name) {
        String val = redisService.get(spaceIdentifier, "S_" + name);
        if (val != null) {
            return true;
        } else {
            return false;
        }
    }

    public void ensureScalarVar(String name, int size, double initial, boolean randomize) {
        String varName = "S_" + name;
        ObjectNode obj = Json.newObject();
        obj.put("name", name);
        obj.put("initial", initial);
        obj.put("randomize", randomize);
        ensureVar(obj, varName, size);
    }

    public void requestVectorVar(String name, int size, int dim, double initial, boolean randomize,
            boolean normalize) {
        ObjectNode val = Json.newObject();
        val.put("name", name);
        val.put("size", size);
        val.put("dim", dim);
        val.put("initial", initial);
        val.put("randomize", randomize);
        val.put("normalize", normalize);
        redisService.set(spaceIdentifier, "V_" + name, val.toString());
    }

    public boolean hasVectorVar(String name) {
        String val = redisService.get(spaceIdentifier, "V_" + name);
        if (val != null) {
            return true;
        } else {
            return false;
        }
    }

    private void ensureVar(ObjectNode obj, String varName, int size) {
        List<Object> resps;
        do {
            JsonNode val = redisService.getValue(spaceIdentifier, varName);
            redisService.watch(spaceIdentifier, varName);
            redisService.multi(false);
            if (val != null) {
                IOUtilities.parseEntityFromJsonNode(val, obj);
                if (size > obj.get("size").asInt()) {
                    obj.put("size", size);
                    redisService.setWithoutLock(spaceIdentifier, varName, obj.toString());
                }
            } else {
                obj.put("size", size);
                redisService.setWithoutLock(spaceIdentifier, varName, obj.toString());
            }
            resps = redisService.exec();
        } while (resps.size() > 0 && resps.get(0) == null);
    }

    public void ensureVectorVar(String name, int size, int dim, double initial, boolean randomize,
            boolean normalize) {
        String varName = "V_" + name;
        ObjectNode obj = Json.newObject();
        obj.put("name", name);
        obj.put("dim", size);
        obj.put("initial", initial);
        obj.put("randomize", randomize);
        obj.put("normalize", normalize);
        ensureVar(obj, varName, size);
    }

    public RealVector getScalarVarByName(String name) {
        String varName = "S_" + name;
        JsonNode obj = redisService.getValue(spaceIdentifier, varName);
        String varIdxName = "IDX_S_" + name + "_";
        List<String> keys = redisService.keysWithPrefixPattern(spaceIdentifier, varIdxName);
        int size = obj.get("size").asInt();
        RealVector vars = MatrixUtils.createRealVector(new double[size]);
        initializeVector(vars, obj.get("initial").asDouble(), obj.get("randomize").asBoolean(), false);
        List<JsonNode> values = redisService.bulkGet(keys);
        for (JsonNode one : values) {
            vars.setEntry(one.get(0).asInt(), one.get(1).asDouble());
        }
        return vars;
    }

    public int getScalarVarSizeByName(String name) {
        String varName = "S_" + name;
        JsonNode obj = redisService.getValue(spaceIdentifier, varName);
        return obj.get("size").asInt();
    }

    public void setScalarVarByName(String name, RealVector vars) {
        for (int i = 0; i < vars.getDimension(); i++) {
            setScalarVarByNameIndex(name, i, vars.getEntry(i));
        }
    }

    public double getScalarVarByNameIndex(String name, int index) {
        String varIdxName = "IDX_S_" + name + "_" + Integer.valueOf(index).toString();
        JsonNode value = redisService.getValue(spaceIdentifier, varIdxName);
        if (value != null) {
            return value.get(1).asDouble();
        } else {
            JsonNode obj = redisService.getValue(spaceIdentifier, "S_" + name);
            double init = initialScalarVar(obj.get("initial").asDouble(), obj.get("randomize").asBoolean());
            return init;
        }
    }

    public void setScalarVarByNameIndex(String name, int index, double var) {
        String varIdxName = "IDX_S_" + name + "_" + Integer.valueOf(index).toString();
        ArrayNode values = Json.newArray();
        values.add(index);
        values.add(var);
        redisService.setValue(spaceIdentifier, varIdxName, values);
    }

    private void setValue(RealVector var, JsonNode one, int dim) {
        for (int i = 0; i < dim; i++) {
            var.setEntry(i, one.get(i + 1).asDouble());
        }
    }

    private void setValue(List<RealVector> vars, JsonNode one, int dim) {
        RealVector chosen = vars.get(one.get(0).asInt());
        setValue(chosen, one, dim);
    }

    public List<RealVector> getVectorVarByName(String name) {
        String varName = "V_" + name;
        JsonNode obj = redisService.getValue(spaceIdentifier, varName);
        int size = obj.get("size").asInt();
        int dim = obj.get("dim").asInt();
        double initial = obj.get("initial").asDouble();
        boolean randomize = obj.get("randomize").asBoolean();
        boolean normalize = obj.get("normalize").asBoolean();
        List<RealVector> vars = new ArrayList<>(size);
        for (int i = 0; i < size; i++) {
            RealVector var = MatrixUtils.createRealVector(new double[dim]);
            initializeVector(var, initial, randomize, normalize);
            vars.add(var);
        }
        String varIdxName = "IDX_V_" + name + "_";
        List<String> keys = redisService.keysWithPrefixPattern(spaceIdentifier, varIdxName);
        List<JsonNode> values = redisService.bulkGet(keys);
        for (JsonNode one : values) {
            setValue(vars, one, dim);
        }
        return vars;
    }

    public RealMatrix getMatrixVarByName(String name) {
        String varName = "V_" + name;
        JsonNode obj = redisService.getValue(spaceIdentifier, varName);
        int size = obj.get("size").asInt();
        int dim = obj.get("dim").asInt();
        RealMatrix matrix = MatrixUtils.createRealMatrix(size, dim);
        for (int i = 0; i < size; i++) {
            matrix.setRowVector(i, getVectorVarByNameIndex(name, i));
        }
        return matrix;
    }

    public int getVectorVarSizeByName(String name) {
        String varName = "V_" + name;
        JsonNode obj = redisService.getValue(spaceIdentifier, varName);
        return obj.get("size").asInt();
    }

    public int getVectorVarDimensionByName(String name) {
        String varName = "V_" + name;
        JsonNode obj = redisService.getValue(spaceIdentifier, varName);
        return obj.get("dim").asInt();
    }

    public RealVector getVectorVarByNameIndex(String name, int index) {
        String varIdxName = "IDX_V_" + name + "_" + Integer.valueOf(index).toString();
        JsonNode value = redisService.getValue(spaceIdentifier, varIdxName);
        if (value != null) {
            int dim = value.size() - 1;
            RealVector var = MatrixUtils.createRealVector(new double[dim]);
            setValue(var, value, dim);
            return var;
        } else {
            JsonNode obj = redisService.getValue(spaceIdentifier, "V_" + name);
            RealVector var = MatrixUtils.createRealVector(new double[obj.get("dim").asInt()]);
            initializeVector(var, obj.get("initial").asDouble(), obj.get("randomize").asBoolean(),
                    obj.get("normalize").asBoolean());
            return var;
        }
    }

    public void setVectorVarByNameIndex(String name, int index, RealVector var) {
        String varIdxName = "IDX_V_" + name + "_" + Integer.valueOf(index).toString();
        ArrayNode values = Json.newArray();
        values.add(index);
        for (int i = 0; i < var.getDimension(); i++) {
            values.add(var.getEntry(i));
        }
        redisService.setValue(spaceIdentifier, varIdxName, values);
    }

    private List<String> getAllVarNames(String label) {
        List<String> names = new ArrayList<>();
        List<String> keys = redisService.keysWithPrefixPattern(spaceIdentifier, label);
        List<JsonNode> values = redisService.bulkGet(keys);
        for (JsonNode val : values) {
            names.add(val.get("name").asText());
        }
        return names;
    }

    public List<String> getAllScalarVarNames() {
        return getAllVarNames("S_");
    }

    public List<String> getAllVectorVarNames() {
        return getAllVarNames("V_");
    }

    public void freeSpace() {
        List<String> keys = redisService.keysWithPrefixPattern(spaceIdentifier, null);
        for (String key : keys) {
            redisService.delWithKey(key);
        }
    }

    public void freeScalarVar(String name) {
        List<String> keys = redisService.keysWithPrefixPattern(spaceIdentifier, "S_" + name);
        for (String key : keys) {
            redisService.delWithKey(key);
        }
    }

    public void freeVectorVar(String name) {
        List<String> keys = redisService.keysWithPrefixPattern(spaceIdentifier, "V_" + name);
        for (String key : keys) {
            redisService.delWithKey(key);
        }
    }
}