Sleds/cppcore/component/storagenode.cpp

843 lines
21 KiB
C++

// Copyright (c) 2013, IOnU Security, Inc.
// Copyright (c) 2016, Sequence Logic, Inc. All rights reserved.
/**
* StorageNode implementation.
*
* NOTE: The C++ language is a little lame when it comes to 'named' enumerations. Trying to access an enumeration value using
* a fully qualified name was not in the standard until C++11. Since Dev Studio versions prior to VS2012 conform to this,
* you will get the following warning:
* warning C4482: nonstandard extension used: enum 'sequencelogic::StorageNodeType' used in qualified name
* due to the fact that this is the name of an enumeration. These can be ignored, and hopefully will dissappear when
* we're up and running on VS2012.
*/
#include "storagenode.h"
#include "storagelocation.h"
#include "../cppcoreobjects/cloudguardurn.h"
#include "../cppcoreobjects/permissions.h"
#include "eyetime.h"
#include <algorithm>
#include <iostream>
#include <sstream>
using namespace sequencelogic;
/*
* Empty constructor. Create an empty storage node.
*/
StorageNode::StorageNode () : _pData(new JSONObject())
{
}
/*
* Copy constructor.
*/
StorageNode::StorageNode (const StorageNodePtr &pNode) : _pData(new JSONObject(*pNode->_pData))
{
}
StorageNode::StorageNode (const StorageNode &node) : _pData(new JSONObject(*node._pData))
{
}
/*
* Copy constructor.
*/
StorageNode::StorageNode (const JSONObjectPtr &pNode) : _pData(new JSONObject(*pNode))
{
}
StorageNode::StorageNode (const JSONObject &node) : _pData(new JSONObject(node))
{
}
/*
* Create a StorageNode from a JSON string.
*/
StorageNode::StorageNode (const std::string &nodeString) : _pData(new JSONObject(nodeString))
{
}
StorageNode& StorageNode::operator=(const StorageNode &rhs)
{
if (this != &rhs)
_pData.reset(new JSONObject(*rhs._pData));
return *this;
}
/*
* Create a pending node! Caller owns the return pointer, and is responsible for cleanup!
*/
StorageNodePtr StorageNode::createPendingNode(const CloudGuardURN &pendingUrn, const std::string &path, const std::string &name)
{
StorageNodePtr pRetVal (new StorageNode());
pRetVal->setPath (path);
pRetVal->setName (name);
pRetVal->setType(StorageNodeType::SNT_PENDING);
pRetVal->setMetaType("peer");
pRetVal->setStatus (StorageNodeStatus::pendingDownload);
std::string mount = pendingUrn.getPMOID();
if (pendingUrn.getDeviceID() != "")
{
mount += "/";
mount += pendingUrn.getDeviceID();
}
pRetVal->setMount(mount);
return pRetVal;
}
/*
* Create an empty node! Caller owns the return pointer, and is responsible for cleanup!
*/
StorageNodePtr StorageNode::createEmptyNode()
{
StorageNodePtr pRetVal (new StorageNode());
pRetVal->setName("No Results");
pRetVal->setType(StorageNodeType::SNT_EMPTY);
pRetVal->setStatus(StorageNodeStatus::informational);
/* These seemed to be "extra" in the Java code (i.e. no setters/getters)
node.put("size", 0);
node.put("description", "Refresh!");
*/
return pRetVal;
}
/*
* Set the name of this node.
*/
void StorageNode::setName (const std::string &name)
{
_pData->setJSONValue(STORAGE_NODE_NAME, name.c_str());
}
/*
* Get the name of this node.
*/
std::string StorageNode::getName () const
{
return _pData->getJSONString(STORAGE_NODE_NAME, getPath());
}
/*
* Set the version of this node.
*/
void StorageNode::setVersion (int nVer)
{
_pData->setJSONValue("version", nVer);
}
/*
* Get the version of this node.
*/
int StorageNode::getVersion () const
{
return _pData->getJSONInt("version", -1);
}
std::string StorageNode::getUniqueName(const std::string& deviceId) const
{
if (getMount() == "s" ||
getMount() == "g")
{
CloudGuardURN urn(getURN());
if (deviceId != "" && urn.getDeviceID() != deviceId)
{
std::string result(urn.getDocumentID());
if (result != "") {
result.append(".");
}
result.append(getName());
return result;
}
}
return getName();
}
/*
* Set the mime type of this node.
*/
void StorageNode::setMimeType (const std::string &mimeType)
{
_pData->setJSONValue(STORAGE_NODE_MIME_TYPE, mimeType.c_str());
}
/*
* Get the mime type of this node.
*/
std::string StorageNode::getMimeType () const
{
return _pData->getJSONString(STORAGE_NODE_MIME_TYPE, MIME_TYPE_APP_UNKNOWN);
}
/*
* Set the length of this node.
*/
void StorageNode::setLength (unsigned int length)
{
_pData->setJSONValue(STORAGE_NODE_LENGTH, length);
}
/*
* Get the length of this node.
*/
unsigned int StorageNode::getLength () const
{
return _pData->getJSONUInt(STORAGE_NODE_LENGTH);
}
/*
* Set the last access time for this node.
*/
void StorageNode::setLastAccessed (const EyeTime &lastAccessed)
{
_pData->setJSONValue(STORAGE_NODE_LAST_ACCESS, const_cast<EyeTime &>(lastAccessed).GetISO8601TimeMs());
}
void StorageNode::setLastAccessed (const std::string &lastAccessed)
{
_pData->setJSONValue(STORAGE_NODE_LAST_ACCESS, lastAccessed.c_str());
}
/*
* Get the last access time for this node.
*/
sequencelogic::EyeTime StorageNode::getLastAccessed () const
{
std::string lastAccessStr = _pData->getJSONString(STORAGE_NODE_LAST_ACCESS, "1970-01-01T00:00:00.000Z");
return EyeTime(lastAccessStr.c_str());
}
/*
* Set the last modified time for this node.
*/
void StorageNode::setLastModified (const EyeTime &lastModified)
{
_pData->setJSONValue(STORAGE_NODE_LAST_MODIFIED, const_cast<EyeTime &>(lastModified).GetISO8601TimeMs());
}
void StorageNode::setLastModified (const std::string &lastModified)
{
_pData->setJSONValue(STORAGE_NODE_LAST_MODIFIED, lastModified.c_str());
}
/*
* Get the last modified time for this node.
*/
sequencelogic::EyeTime StorageNode::getLastModified () const
{
std::string lastModifiedStr = _pData->getJSONString(STORAGE_NODE_LAST_MODIFIED, "1970-01-01T00:00:00.000Z");
return EyeTime(lastModifiedStr.c_str());
}
/*
* Set the last modified time for this node.
*/
void StorageNode::setutime (const EyeTime &utime)
{
_pData->setJSONValue(STORAGE_NODE_UTIME, const_cast<EyeTime &>(utime).GetISO8601TimeMs());
}
void StorageNode::setutime (const std::string &lastModified)
{
_pData->setJSONValue(STORAGE_NODE_UTIME, lastModified.c_str());
}
/*
* Get the last modified time for this node.
*/
sequencelogic::EyeTime StorageNode::getutime () const
{
std::string utimeStr = _pData->getJSONString(STORAGE_NODE_UTIME, "1970-01-01T00:00:00.000Z");
return EyeTime(utimeStr.c_str());
}
/*
* Get the mtime for this node.
*/
sequencelogic::EyeTime StorageNode::getmtime () const
{
std::string mtimeStr = _pData->getJSONString(STORAGE_NODE_MTIME, "1970-01-01T00:00:00.000Z");
return EyeTime(mtimeStr.c_str());
}
/*
* Set the mtime for this node.
*/
void StorageNode::setmtime (const EyeTime &mtime)
{
_pData->setJSONValue(STORAGE_NODE_MTIME, const_cast<EyeTime &>(mtime).GetISO8601TimeMs());
}
void StorageNode::setmtime (const std::string &lastModified)
{
_pData->setJSONValue(STORAGE_NODE_MTIME, lastModified.c_str());
}
/*
* Set the creation time for this node.
*/
void StorageNode::setCreation (const EyeTime &created)
{
_pData->setJSONValue(STORAGE_NODE_CREATE_TIME, const_cast<EyeTime &>(created).GetISO8601TimeMs());
}
void StorageNode::setCreation (const std::string &created)
{
_pData->setJSONValue(STORAGE_NODE_CREATE_TIME, created.c_str());
}
/*
* Get the creation time for this node.
*/
sequencelogic::EyeTime StorageNode::getCreation () const
{
std::string createdStr = _pData->getJSONString(STORAGE_NODE_CREATE_TIME, "1970-01-01T00:00:00.000Z");
return EyeTime(createdStr.c_str());
}
/*
* Set the host for this node.
*/
void StorageNode::setHost (const std::string &host)
{
if (host == "")
_pData->erase(STORAGE_NODE_HOST);
else
_pData->setJSONValue(STORAGE_NODE_HOST, host.c_str());
}
/*
* Get the host for this node.
*/
std::string StorageNode::getHost () const
{
return _pData->getJSONString(STORAGE_NODE_HOST);
}
/*
* Set the mount.
*/
void StorageNode::setMount (const std::string &mount)
{
_pData->setJSONValue(STORAGE_NODE_MOUNT, mount.c_str());
}
/*
* Get the mount.
*/
std::string StorageNode::getMount () const
{
return _pData->getJSONString(STORAGE_NODE_MOUNT);
}
/*
* Set the URN.
*/
void StorageNode::setURN (const std::string &mount)
{
_pData->setJSONValue(STORAGE_NODE_URN, mount.c_str());
}
/*
* Get the URN.
*/
std::string StorageNode::getURN () const
{
return _pData->getJSONString(STORAGE_NODE_URN);
}
/*
* Set the source.
*/
void StorageNode::setSource (const std::string &source)
{
_pData->setJSONValue(STORAGE_NODE_SOURCE, source.c_str());
}
/*
* Get the source.
*/
std::string StorageNode::getSource () const
{
return _pData->getJSONString(STORAGE_NODE_SOURCE);
}
/*
* Set the path.
*/
void StorageNode::setPath (const std::string &path)
{
_pData->setJSONValue(STORAGE_NODE_PATH, path.c_str());
}
/*
* Get the path.
*/
std::string StorageNode::getPath () const
{
return _pData->getJSONString(STORAGE_NODE_PATH);
}
/*
* Set the folder.
*/
void StorageNode::setFolder (const std::string &folder)
{
_pData->setJSONValue(STORAGE_NODE_FOLDER, folder.c_str());
}
/*
* Get the folder.
*/
std::string StorageNode::getFolder () const
{
std::string result = _pData->getJSONString(STORAGE_NODE_FOLDER);
//if not supplied in metadata derive folder from path + name
//NOTE: This is a (hopefully) temporary work-around for backwards compatability
// this routine could/should be removed when support for folder is solidified
if (result.empty()) {
//remove node name from end of path, case-insensitive
result = getPath();
std::string workingPath = result;
std::transform(workingPath.begin(), workingPath.end(), workingPath.begin(), ::tolower);
std::string workingName = getName();
std::transform(workingName.begin(), workingName.end(), workingName.begin(), ::tolower);
//find name at end of path
std::string::size_type position = workingPath.rfind(workingName);
if (position == std::string::npos) {
result = "";
}
else {
result = result.substr(0, position);
}
}
return result;
}
/*
* Set the parents from a JSONArray.
*/
void StorageNode::setParents(const JSONArray &parents)
{
// Just copy the array into the node, verbaitim.
if (!parents.empty())
_pData->setJSONValue(STORAGE_NODE_PARENTS, parents);
}
/*
* Set the parent.
* For some reason parents is an array with a single object in it.
* The object contains an array of the grand parents.
* This routine sets only the immediate parent URN
*/
void StorageNode::setParent (const std::string &parent)
{
JSONArray parents = _pData->getJSONArray(STORAGE_NODE_PARENTS);
if (parents.getnumelements() > 0) {
JSONObject& parentsJSON = static_cast<JSONObject&>(parents[0]);
parentsJSON.setJSONValue(STORAGE_NODE_URN, parent.c_str());
} else {
JSONObject newParent;
newParent.setJSONValue(STORAGE_NODE_URN, parent.c_str());
JSONArray parentsArray;
parentsArray.addElement(newParent);
_pData->setJSONValue(STORAGE_NODE_PARENTS, parentsArray);
}
}
/*
* Get the parent.
* For some reason parents is an array with a single object in it.
* The object contains an array of the grand parents.
* This routine returns only the immediate parent URN
*/
std::string StorageNode::getParent () const
{
std::string result;
JSONArray parents = _pData->getJSONArray(STORAGE_NODE_PARENTS);
if (parents.getnumelements() > 0) {
const JSONObject& parentsJSON = static_cast<const JSONObject&>(parents[0]);
result = parentsJSON.getJSONString(STORAGE_NODE_URN);
}
return result;
}
/*
* Set this node's status.
*/
void StorageNode::setStatus (StorageNodeStatus status)
{
_pData->setJSONValue(STORAGE_NODE_STATUS, StorageNodeStatusUtil::toString(status).c_str());
}
void StorageNode::setStatus (const std::string &status)
{
_pData->setJSONValue(STORAGE_NODE_STATUS, status.c_str());
}
/*
* Get this node's status.
*/
StorageNodeStatus StorageNode::getStatus () const
{
return StorageNodeStatusUtil::valueOf(_pData->getJSONString(STORAGE_NODE_STATUS));
}
/*
* Set this node's type.
*/
void StorageNode::setType (StorageNodeType type)
{
_pData->setJSONValue(STORAGE_NODE_TYPE, StorageNodeTypeUtil::toString(type).c_str());
}
void StorageNode::setType (const std::string &type)
{
_pData->setJSONValue(STORAGE_NODE_TYPE, type.c_str());
}
/*
* Get this node's type.
*/
StorageNodeType StorageNode::getType () const
{
return StorageNodeTypeUtil::valueOf(_pData->getJSONString(STORAGE_NODE_TYPE));
}
/*
* Set this node's meta type.
*/
void StorageNode::setMetaType (const std::string &metaType)
{
_pData->setJSONValue(STORAGE_NODE_META_TYPE, metaType.c_str());
}
/*
* Get this node's meta type.
*/
std::string StorageNode::getMetaType () const
{
return _pData->getJSONString(STORAGE_NODE_META_TYPE, MIME_TYPE_APP_UNKNOWN);
}
void StorageNode::setSignature(const std::string &sig)
{
_pData->setJSONValue(PERMISSION_KEY_SIGNATURE, sig.c_str());
}
/*
* Set this node's sync status.
*/
void StorageNode::setSync (bool sync)
{
_pData->setJSONValue(STORAGE_NODE_SYNC, sync);
}
/*
* Get this node's sync status.
*/
bool StorageNode::getSync () const
{
return _pData->getJSONInt(STORAGE_NODE_SYNC, 1) != 0;
}
/*
* Get this node's permissions.
*/
std::string StorageNode::getSignature() const
{
return _pData->getJSONString(PERMISSION_KEY_SIGNATURE);
}
/**
Set/get the size of the node.
*/
void StorageNode::setSize(int nSize)
{
_pData->setJSONValue(STORAGE_NODE_SIZE, nSize);
}
int StorageNode::getSize() const
{
return _pData->getJSONInt(STORAGE_NODE_SIZE);
}
/**
Set/get the absolute path of the node.
*/
void StorageNode::setAbsPath(const std::string &absPath)
{
_pData->setJSONValue(STORAGE_NODE_ABS_PATH, absPath.c_str());
}
std::string StorageNode::getAbsPath() const
{
return _pData->getJSONString(STORAGE_NODE_ABS_PATH);
}
/**
Set/get the description of the node.
*/
void StorageNode::setDescription(const std::string &desc)
{
_pData->setJSONValue(STORAGE_NODE_DESC, desc.c_str());
}
std::string StorageNode::getDescription() const
{
return _pData->getJSONString(STORAGE_NODE_DESC);
}
/*
* Set and get 'hash' for the node.
*/
void StorageNode::setHash(const std::string &hash)
{
_pData->setJSONValue(STORAGE_NODE_HASH, hash.c_str());
}
std::string StorageNode::getHash() const
{
return _pData->getJSONString(STORAGE_NODE_HASH);
}
/**
Set/get the view for the node.
*/
void StorageNode::setView(const std::string &view)
{
_pData->setJSONValue(STORAGE_NODE_VIEW, view.c_str());
}
std::string StorageNode::getView() const
{
return _pData->getJSONString(STORAGE_NODE_VIEW);
}
/**
Set/get the port for the node.
*/
void StorageNode::setPort(int nPort)
{
_pData->setJSONValue(STORAGE_NODE_PORT, nPort);
}
int StorageNode::getPort() const
{
return _pData->getJSONInt(STORAGE_NODE_PORT);
}
void
StorageNode::setLocations(std::pair<StorageLocation,StorageLocation>& p)
{
JSONArray locArray;
std::shared_ptr<JSONObject> p_loc = p.first.getAsJson();
std::shared_ptr<JSONObject> p_remote_loc = p.second.getAsJson();
locArray.addElement(*p_loc);
locArray.addElement( *p_remote_loc);
_pData->erase(STORAGE_NODE_LOC);
_pData->setJSONValue(STORAGE_NODE_LOC, locArray);
}
StorageLocation StorageNode::getLocation() const {
JSONArray& locs_data = _pData->getJSONArray(STORAGE_NODE_LOC);
for (int i = 0; i < locs_data.getnumelements(); ++i) {
const JSONObject& loc_data = static_cast<const JSONObject &>(locs_data[i]);
StorageLocation loc(loc_data);
if (loc.getType() == StorageLocation::LOCATE_TYPE::L1) {
return loc;
}
}
return (StorageLocation());
}
StorageLocation StorageNode::getRemoteLocation() const {
JSONArray& locs_data = _pData->getJSONArray(STORAGE_NODE_LOC);
for (int i = 0; i < locs_data.getnumelements(); ++i) {
const JSONObject& loc_data = static_cast<const JSONObject &>(locs_data[i]);
StorageLocation loc(loc_data);
// TODO: A number of assumptions are in play here and need validation.
// Nowhere do we force locations to be unique in the array. Also, this
// assumes that the storage node has only two locations, 'here' and
// 'there'. What about shared devices?
if (loc.getType() != StorageLocation::LOCATE_TYPE::L1) {
return loc;
}
}
std::string bucket_id("");
return (StorageLocation(StorageLocation::LOCATE_TYPE::UNKNOWN,
StorageLocation::LOCATE_KIND::UNKNOWN, bucket_id,
StorageLocation::LOCATE_STATUS::FLUSHED));
}
std::string StorageNode::toDebugString() const
{
std::string retVal;
if (_pData->empty())
retVal = "NULL StorageNode object...";
else
{
std::stringstream retValStream;
retValStream << getName() << ":\n";
retValStream << " path: '" << getPath() << "'\n type: " << StorageNodeTypeUtil::toString(getType()) << "\n mimeType: '" << getMimeType() << "'\n";
retValStream << " status: " << StorageNodeStatusUtil::toString(getStatus()) << "\n length: " << getLength() << "\n metaType: '" << getMetaType() << "'\n";
retValStream << " created: " << getCreation().GetISO8601TimeMs() << " modified: " << getLastModified().GetISO8601TimeMs() << " accessed: " << getLastAccessed().GetISO8601TimeMs();
retValStream << " host: '" << getHost() << "'\n mount: '" << getMount() << "'\n";
retValStream << "JSON string:\n" << _pData->toString() << "\n";
retVal = retValStream.str();
}
return retVal;
}
std::string StorageNode::toString() const
{
return _pData->toString();
}
StorageNodeVector
StorageNode::getChildren() const
{
StorageNodeVector result;
JSONArray children = _pData->getJSONArray(STORAGE_NODE_CHILDREN);
for (int i = 0; i < children.getnumelements(); ++i) {
const JSONObject & child = static_cast<const JSONObject &>(children[i]);
StorageNodePtr childPtr (new StorageNode(child));
result.push_back(childPtr);
}
return result;
}
void
StorageNode::setChildren(const StorageNodeVector & children)
{
JSONArray childrenArray;
for (StorageNodePtr child : children) {
childrenArray.addElement(*(child->_pData));
}
_pData->erase(STORAGE_NODE_CHILDREN);
_pData->setJSONValue(STORAGE_NODE_CHILDREN, childrenArray);
}
void
StorageNode::addChild(const StorageNode & child)
{
//create array if not present
_pData->setJSONArray(STORAGE_NODE_CHILDREN);
//add child to end of array
JSONArray & childrenArray = _pData->getJSONArray(STORAGE_NODE_CHILDREN);
childrenArray.addElement(*(child._pData));
}
JSONObject
StorageNode::getMetadata() const
{
return _pData->getJSONObject(STORAGE_NODE_META_DATA);
}
/**
Set metadata associated with EyeFile pointed to by StorageNode
@param metaData - metadata as string
*/
void
StorageNode::setMetadata(const JSONObject & metadata)
{
_pData->setJSONValue(STORAGE_NODE_META_DATA, metadata);
}
/**
* Merge this node with the node passed in.
*/
void StorageNode::mergeWith(const StorageNode &node)
{
_pData->mergeWith(*node._pData);
}
void StorageNode::mergeWith(const JSONObject &node)
{
_pData->mergeWith(node);
}
/**
* Set/get permisisons.
*/
/*
void StorageNode::setPermissions(const Permissions &perms)
{
JSONArray tmpPerms (perms.toString());
_pData->setJSONValue(PERMISSION_ROOT_KEY, tmpPerms);
}
PermissionsPtr StorageNode::getPermissions() const
{
if (_pData->search(PERMISSION_ROOT_KEY) != NULL)
return PermissionsPtr(new Permissions(_pData->getJSONObject(PERMISSION_ROOT_KEY)));
else
return PermissionsPtr(NULL);
}
*/
bool StorageNode::isRemoteFileOrDirectory (const StorageNode &obj)
{
StorageNodeType type = StorageNode::type(obj);
return ( (isFile(obj) && (type != StorageNodeType::SNT_DEVICE_FILE)) ||
(type == StorageNodeType::SNT_MOUNT) ||
(type == StorageNodeType::SNT_REMOTE_DIRECTORY) ||
(type == StorageNodeType::SNT_PEER_DIRECTORY));
}
/**
Set/get the isDirectory bool for the node.
*/
void StorageNode::setIsDir(bool bIsDir)
{
_pData->setJSONValue(STORAGE_NODE_ISDIR, bIsDir);
}
bool StorageNode::getIsDir() const
{
return _pData->getJSONBool(STORAGE_NODE_ISDIR, false);
}
/**
Is this node empty?
@returns true if empty
*/
bool StorageNode::isEmpty() const
{
return ((_pData == NULL) || _pData->empty());
}
/**
Set/get the filename for the node.
*/
void StorageNode::setFilename(const std::string &filename)
{
_pData->setJSONValue(STORAGE_NODE_FILENAME, filename.c_str());
}
std::string StorageNode::getFilename() const
{
return _pData->getJSONString(STORAGE_NODE_FILENAME);
}
namespace sequencelogic
{
std::ostream& operator<<(std::ostream &out, const StorageNode &node)
{
out << node.toDebugString();
return out;
}
}