blob: ee04fdd2b2d5fba9ac947cd675e67688594166dd [file] [log] [blame]
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/**
* Copyright (c) 2016 Regents of the University of California.
*
* This file is part of the nTorrent codebase.
*
* nTorrent is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free Software
* Foundation, either version 3 of the License, or (at your option) any later version.
*
* nTorrent is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
* PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
*
* You should have received copies of the GNU General Public License and GNU Lesser
* General Public License along with nTorrent, e.g., in COPYING.md file. If not, see
* <http://www.gnu.org/licenses/>.
*
* See AUTHORS for complete list of nTorrent authors and contributors.
*/
#ifndef INCLUDED_FILE_MANIFEST_HPP
#define INCLUDED_FILE_MANIFEST_HPP
#include "util/shared-constants.hpp"
#include <cstring>
#include <memory>
#include <string>
#include <utility>
#include <vector>
#include <ndn-cxx/data.hpp>
#include <ndn-cxx/name.hpp>
namespace ndn {
namespace ntorrent {
class FileManifest : public Data {
/**
* \class FileManifest
*
* \brief A value semantic type for File manifests
*
*/
public:
// TYPES
class Error : public Data::Error
{
public:
explicit
Error(const std::string& what)
: Data::Error(what)
{
}
};
public:
// CLASS METHODS
static std::vector<FileManifest>
generate(const std::string& filePath,
const ndn::Name& manifestPrefix,
size_t subManifestSize,
size_t dataPacketSize);
static std::pair<std::vector<FileManifest>, std::vector<Data>>
generate(const std::string& filePath,
const ndn::Name& manifestPrefix,
size_t subManifestSize,
size_t dataPacketSize,
bool returnData);
/**
* \brief Generates the FileManifest(s) and Data packets for the file at the specified 'filePath'
*
* @param filePath The path to the file for which we are to create a manifest
* @param manifestPrefix The prefix to be used for the name of this manifest
* @param subManifestSize The maximum number of data packets to be included in a sub-manifest
* @param dataPacketSize The maximum number of bytes per Data packet packets for the file
* @param returnData If true also return the Data
*
* @throws Error if there is any I/O issue when trying to read the filePath.
*
* Generates the FileManfiest(s) for the file at the specified 'filePath', splitting the manifest
* into sub-manifests of size at most the specified 'subManifestSize'. Each sub-manifest is
* composed of a catalog of Data packets of at most the specified 'dataPacketSize'. Returns all
* of the manifests that were created in order. The behavior is undefined unless the
* trailing component of of the manifestPrefix is a subComponent filePath and
'* O < subManifestSize' and '0 < dataPacketSize'.
*/
// CREATORS
FileManifest() = default;
~FileManifest() = default;
/// Destroy this object
FileManifest(const Name& name,
size_t dataPacketSize,
const Name& commonPrefix,
const std::vector<Name>& catalog = std::vector<Name>(),
std::shared_ptr<Name> subManifestPtr = nullptr);
/**
* \brief Creates a new FileManifest with the specified values
*
* @param name The Name of this FileManifest
* @param dataPacketSize The size (except the last) of each data packet in this FileManifest
* @param commonPrefix The common prefix used for all named in the catalog
* @param catalog The collection of Names for this FileManifest
* @param subManifestPtr (optional) The Name for the sub-manifest in this for this file
*/
FileManifest(const Name& name,
size_t dataPacketSize,
const Name& catalogPrefix,
std::vector<Name>&& catalog,
std::shared_ptr<Name> subManifestPtr = nullptr);
/**
* \brief Creates a new FileManifest with the specified values
*
* @param name The Name of this FileManifest
* @param dataPacketSize The size (except the last) of each data packet in this FileManifest
* @param catalogPrefix the common prefix used for all named in the catalog
* @param catalog The collection of Names for this FileManifest
* @param subManifestPtr (optional) The Name for the sub-manifest in this for this file
*/
explicit
FileManifest(const Block& block);
FileManifest(const FileManifest& other) = default;
/// Creates a new FileManifest with same value as the specified 'other'
// ACCESSORS
const Name&
name() const;
/// Returns the 'name' of this FileManifest
const Name&
catalog_prefix() const;
/// Returns the 'catalogPrefix' of this FileManfiest.
size_t
data_packet_size() const;
/// Returns the 'data_packet_size' of this FileManifest
size_t
submanifest_number() const;
/// Return the submanifest number for this FileManifest
std::string
file_name() const;
/// Return the file name for this FileManifest
std::shared_ptr<Name>
submanifest_ptr() const;
/// Returns the 'submanifest_ptr' of this FileManifest, or 'nullptr' is none exists
const std::vector<Name>&
catalog() const;
/// Returns an unmodifiable reference to the 'catalog' of this FileManifest
private:
template<encoding::Tag TAG>
size_t
encodeContent(EncodingImpl<TAG>& encoder) const;
/// Encodes the contents of this object and append the contents to the 'encoder'
public:
// MANIPULATORS
FileManifest&
operator=(const FileManifest& rhs) = default;
/// Assigns the value of the specific 'rhs' object to this object.
void
set_submanifest_ptr(std::shared_ptr<Name> subManifestPtr);
/// Sets the sub-manifest pointer of manifest to the specified 'subManifestPtr'
void
push_back(const Name& name);
/// Appends a Name to the catalog
void
reserve(size_t capacity);
/// Reserve memory in the catalog adequate to hold at least 'capacity' Names.
bool
remove(const Name& name);
/// If 'name' in catalog, removes first instance and returns 'true', otherwise returns 'false'.
void
wireDecode(const Block& wire);
/**
* \brief Decodes the wire and assign its contents to this FileManifest
*
* @param wire the write to be decoded
* @throws Error if decoding fails
*/
void
finalize();
/*
* \brief Performs all final processing on this manifest
*
* This method should be called once this manifest is populated and *must* be called before
* signing it or calling wireEncode().
*/
private:
void
decodeContent();
/// Decodes the contents of this Data packet, assigning its contents to this FileManifest.
void
encodeContent();
/// Encodes the contents of this FileManifest into the content section of its Data packet.
// DATA
private:
size_t m_dataPacketSize;
Name m_catalogPrefix;
std::vector<Name> m_catalog;
std::shared_ptr<Name> m_submanifestPtr;
};
/// Non-member functions
bool operator==(const FileManifest& lhs, const FileManifest& rhs);
/// Returns 'true' if 'lhs' and 'rhs' have the same value, 'false' otherwise.
bool operator!=(const FileManifest& lhs, const FileManifest& rhs);
/// Returns 'true' if 'lhs' and 'rhs' have different values, and 'false' otherwise.
inline
std::vector<FileManifest>
FileManifest::generate(const std::string& filePath,
const ndn::Name& manifestPrefix,
size_t subManifestSize,
size_t dataPacketSize)
{
return generate(filePath, manifestPrefix, subManifestSize, dataPacketSize, false).first;
}
inline
FileManifest::FileManifest(
const Name& name,
size_t dataPacketSize,
const Name& catalogPrefix,
const std::vector<Name>& catalog,
std::shared_ptr<Name> subManifestPtr)
: Data(name)
, m_dataPacketSize(dataPacketSize)
, m_catalogPrefix(catalogPrefix)
, m_catalog(catalog)
, m_submanifestPtr(subManifestPtr)
{
}
inline
FileManifest::FileManifest(
const Name& name,
size_t dataPacketSize,
const Name& catalogPrefix,
std::vector<Name>&& catalog,
std::shared_ptr<Name> subManifestPtr)
: Data(name)
, m_dataPacketSize(dataPacketSize)
, m_catalogPrefix(catalogPrefix)
, m_catalog(catalog)
, m_submanifestPtr(subManifestPtr)
{
}
inline
FileManifest::FileManifest(const Block& block)
: Data()
, m_dataPacketSize(0)
, m_catalogPrefix("")
, m_catalog()
, m_submanifestPtr(nullptr)
{
wireDecode(block);
}
inline const Name&
FileManifest::name() const
{
return getName();
}
inline size_t
FileManifest::data_packet_size() const
{
return m_dataPacketSize;
}
inline const Name&
FileManifest::catalog_prefix() const
{
return m_catalogPrefix;
}
inline const std::vector<Name>&
FileManifest::catalog() const
{
return m_catalog;
}
inline std::shared_ptr<Name>
FileManifest::submanifest_ptr() const
{
return m_submanifestPtr;
}
inline std::string
FileManifest::file_name() const
{
Name scheme(SharedConstants::commonPrefix);
return name().getSubName(1 + scheme.size(),
name().size() - (2 + scheme.size())).toUri();
}
inline size_t
FileManifest::submanifest_number() const
{
return name().get(name().size() - 1).toSequenceNumber();
}
inline void
FileManifest::set_submanifest_ptr(std::shared_ptr<Name> subManifestPtr)
{
m_submanifestPtr = subManifestPtr;
}
inline void
FileManifest::reserve(size_t capacity)
{
m_catalog.reserve(capacity);
}
} // end ntorrent
} // end ndn
#endif // INCLUDED_FILE_MANIFEST_HPP