mirror of https://github.com/EdgeVPNio/portal.git
203 lines
6.7 KiB
JavaScript
203 lines
6.7 KiB
JavaScript
/* EdgeVPNio
|
|
* Copyright 2021, University of Florida
|
|
*
|
|
* 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.
|
|
*/
|
|
|
|
const mongoose = require("mongoose");
|
|
const { DataBaseInterface } = require("./DatabaseInterface");
|
|
const { overlayModel, topologyModel } = require("./Model");
|
|
const { DataTransformer } = require("../controllers/DataTransformer");
|
|
|
|
class MongoDBImpl extends DataBaseInterface {
|
|
// Stores the url and dbname and is available for every instance
|
|
constructor(url, dbname) {
|
|
super(url);
|
|
// Once an instance is created the db connection is kept until the instance is alive.
|
|
this.connection = mongoose.connect(url, {
|
|
useNewUrlParser: true,
|
|
useUnifiedTopology: true,
|
|
useCreateIndex: true,
|
|
});
|
|
this.dbname = dbname;
|
|
this.db = mongoose.connection.client;
|
|
}
|
|
|
|
/**
|
|
* Getter function for the db attribute
|
|
*/
|
|
getDb() {
|
|
return this.db;
|
|
}
|
|
|
|
/**
|
|
* Function to insert the PUT data sent by the EVIO nodes into
|
|
* collections: 1) Overlays
|
|
* 2) Topology
|
|
*
|
|
* @param {Json} data Aggregated data Object
|
|
* @param {Number} timestamp End timestamp at which object was taken.
|
|
*/
|
|
async insertInto(data, timestamp) {
|
|
var dataTrasformer = new DataTransformer();
|
|
try {
|
|
// The data is transformed to the required form and returned as an array of arrays.
|
|
var transformedData = dataTrasformer.transformData(data);
|
|
//console.log("transformedData: ", JSON.stringify(transformedData));
|
|
var overlaySaveData = new overlayModel({
|
|
_id: timestamp,
|
|
Overlays: transformedData[0], // Overlays array
|
|
});
|
|
// Overlay data is put into the db with the below call.
|
|
overlaySaveData.save(function (err) {
|
|
if (err) {
|
|
console.log(err.stack);
|
|
}
|
|
//console.log("Saved Overlay data for timestamp: " + timestamp);
|
|
});
|
|
var topologySaveData = new topologyModel({
|
|
_id: timestamp,
|
|
Topology: transformedData[1], // Topology Array
|
|
});
|
|
// Topology data is put into the db with the below call.
|
|
topologySaveData.save(function (err) {
|
|
if (err) {
|
|
console.log(err.stack);
|
|
}
|
|
//console.log("Saved Topology data for timestamp:" + timestamp);
|
|
});
|
|
} catch (err) {
|
|
console.error(err);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Database call to get the intervals stored.
|
|
*
|
|
* @param {String} tableName Model Name to use to find the intervals.
|
|
*/
|
|
async getIntervals(tableName) {
|
|
return tableName.find({}, { Overlays: 0 });
|
|
}
|
|
|
|
/**
|
|
* Database call to get the high level Overlay information.
|
|
*
|
|
* @param {String} tableName Model to use to get the overlay.
|
|
* @param {Float} intervalId Interval identifier to query.
|
|
*/
|
|
async findOverlays(tableName, intervalId) {
|
|
if (intervalId) {
|
|
//Find the next available interval, greater than the previous one from client
|
|
return tableName
|
|
.find({ _id: { $gt: intervalId } })
|
|
.sort({ _id: 1 })
|
|
.limit(1);
|
|
}
|
|
//Most recent entry - intervalId not passed
|
|
return tableName.find().sort({ _id: -1 }).limit(1);
|
|
}
|
|
|
|
/**
|
|
* Database call to get the detailed topology information.
|
|
*
|
|
* @param {String} tableName
|
|
* @param {Float} intervalId
|
|
* @param {String} overlayId
|
|
*/
|
|
async findTopology(tableName, intervalId, overlayId) {
|
|
if (intervalId) {
|
|
//Find the next available interval, greater than the previous one from client
|
|
return tableName
|
|
.find(
|
|
{
|
|
Topology: { $elemMatch: { OverlayId: overlayId } },
|
|
_id: { $gt: intervalId },
|
|
},
|
|
{ "Topology.$": 1 }
|
|
)
|
|
.sort({ _id: 1 })
|
|
.limit(1);
|
|
}
|
|
//Most recent entry - intervalId not passed
|
|
return tableName
|
|
.find(
|
|
{ Topology: { $elemMatch: { OverlayId: overlayId } } },
|
|
{ "Topology.$": 1 }
|
|
)
|
|
.sort({ _id: -1 })
|
|
.limit(1);
|
|
}
|
|
|
|
async getOverlays(tableName, intervalId) {
|
|
var overlayData = await this.findOverlays(tableName, intervalId);
|
|
if (Object.keys(overlayData).length === 0) {
|
|
const pipeline = [{ $match: { operationType: "insert" } }]; //watch for insert operation
|
|
const overlayChangeStream = this.db
|
|
.db("Evio")
|
|
.collection("Overlays")
|
|
.watch(pipeline);
|
|
await Promise.resolve(overlayChangeStream.hasNext());
|
|
let newData = await Promise.resolve(overlayChangeStream.next());
|
|
overlayData = [newData.fullDocument];
|
|
overlayChangeStream.close();
|
|
}
|
|
return overlayData;
|
|
}
|
|
|
|
/**
|
|
* Function to query Topology collection, watch the collection for insert op every 1 second
|
|
* @param {String} tableName
|
|
* @param {Float} intervalId
|
|
* @param {String} overlayId
|
|
* @returns inserted data to topology collection
|
|
*/
|
|
async getTopology(tableName, intervalId, overlayId) {
|
|
var topologyData = await this.findTopology(
|
|
tableName,
|
|
intervalId,
|
|
overlayId
|
|
);
|
|
if (Object.keys(topologyData).length === 0) {
|
|
const pipeline = [{ $match: { operationType: "insert" } }];
|
|
const topologyChangeStream = this.db
|
|
.db("Evio")
|
|
.collection("Topology")
|
|
.watch(pipeline);
|
|
await Promise.resolve(topologyChangeStream.hasNext());
|
|
topologyChangeStream.close();
|
|
topologyData = await this.findTopology(tableName, intervalId, overlayId);
|
|
}
|
|
return topologyData;
|
|
}
|
|
|
|
/**
|
|
* Database call to get the intervals stored.
|
|
*
|
|
* @param {mogoose.Model} tableName Model Name to use to find the intervals.
|
|
* @param {String} nodeId
|
|
*/
|
|
async getEvioControl(tableName, nodeId) {
|
|
return tableName.find(
|
|
{ "EvioControl.NodeId": { $eq: nodeId } }
|
|
).sort({ _id: -1 }).limit(1);
|
|
}
|
|
}
|
|
module.exports = { MongoDBImpl };
|