blob: e05116eadfbd069d91e5cd43ce36c138eea3d6d4 [file] [log] [blame]
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/**
* Copyright (c) 2013-2017, Regents of the University of California.
*
* This file is part of ChronoShare, a decentralized file sharing application over NDN.
*
* ChronoShare is free software: you can redistribute it and/or modify it under the terms
* of the GNU General Public License as published by the Free Software Foundation, either
* version 3 of the License, or (at your option) any later version.
*
* ChronoShare 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 General Public License for more details.
*
* You should have received copies of the GNU General Public License along with
* ChronoShare, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
*
* See AUTHORS.md for complete list of ChronoShare authors and contributors.
*/
#ifndef CHRONOSHARE_SRC_DISPATCHER_HPP
#define CHRONOSHARE_SRC_DISPATCHER_HPP
#include "core/chronoshare-common.hpp"
#include "action-log.hpp"
#include "content-server.hpp"
#include "state-server.hpp"
#include "fetch-manager.hpp"
#include "object-db.hpp"
#include "object-manager.hpp"
#include "sync-core.hpp"
#include <boost/filesystem.hpp>
#include <boost/filesystem/fstream.hpp>
#include <map>
namespace ndn {
namespace chronoshare {
typedef shared_ptr<ActionItem> ActionItemPtr;
// TODO:
// This class lacks a permanent table to store the files in fetching process
// and fetch the missing pieces for those in the table after the application launches
/**
* @brief Class synchroize different components
*
* - from SyncLog: when state changes -> to fetch missing actions
*
* - from FetchManager/Actions: when action is fetched -> to request a file, specified by the action
* -> to add action to the action log
*
* - from ActionLog/Delete: when action applied(file state changed, file deleted) -> to delete local file
*
* - from ActionLog/AddOrUpdate: when action applied(file state changes, file added or modified) ->
* to assemble the file if file is available in the ObjectDb, otherwise, do nothing
*
* - from FetchManager/Files: when file segment is retrieved -> save it in ObjectDb
* when file fetch is completed -> if file belongs to FileState, then assemble
* it to filesystem. Don't do anything otherwise
*/
class Dispatcher
{
public:
// sharedFolder is the name to be used in NDN name;
// rootDir is the shared folder dir in local file system;
Dispatcher(const std::string& localUserName, const std::string& sharedFolder,
const boost::filesystem::path& rootDir, Face& face);
~Dispatcher();
// ----- Callbacks, they only submit the job to executor and immediately return so that event
// processing thread won't be blocked for too long -------
// callback to process local file change
void
Did_LocalFile_AddOrModify(const boost::filesystem::path& relativeFilepath);
void
Did_LocalFile_Delete(const boost::filesystem::path& relativeFilepath);
/**
* @brief Invoked when FileState is detected to have a file which does not exist on a file system
*/
void
Restore_LocalFile(FileItemPtr file);
// for test
ConstBufferPtr
SyncRoot()
{
return m_core->root();
}
inline void
LookupRecentFileActions(const boost::function<void(const std::string&, int, int)>& visitor,
int limit)
{
m_actionLog->LookupRecentFileActions(visitor, limit);
}
private:
void
Did_LocalFile_AddOrModify_Execute(boost::filesystem::path relativeFilepath); // cannot be const &
// for Execute
// event!!! otherwise
// there will be
// segfault
void
Did_LocalFile_Delete_Execute(boost::filesystem::path relativeFilepath); // cannot be const & for
// Execute event!!!
// otherwise there will be
// segfault
void
Restore_LocalFile_Execute(FileItemPtr file);
private:
/**
* Callbacks:
*
* - from SyncLog: when state changes -> to fetch missing actions
*
* - from FetchManager/Actions: when action is fetched -> to request a file, specified by the action
* -> to add action to the action log
*
* - from ActionLog/Delete: when action applied(file state changed, file deleted) -> to delete local file
*
* - from ActionLog/AddOrUpdate: when action applied(file state changes, file added or modified) ->
* to assemble the file if file is available in the ObjectDb, otherwise, do nothing
*
* - from FetchManager/Files: when file segment is retrieved -> save it in ObjectDb
* when file fetch is completed -> if file belongs to FileState, then assemble
* it to filesystem. Don't do anything otherwise
*/
// callback to process remote sync state change
void
Did_SyncLog_StateChange(SyncStateMsgPtr stateMsg);
void
Did_SyncLog_StateChange_Execute(SyncStateMsgPtr stateMsg);
void
Did_FetchManager_ActionFetch(const Name& deviceName, const Name& actionName, uint32_t seqno,
shared_ptr<Data> actionData);
void
Did_ActionLog_ActionApply_Delete(const std::string& filename);
void
Did_ActionLog_ActionApply_Delete_Execute(std::string filename);
void
Did_FetchManager_FileSegmentFetch(const Name& deviceName, const Name& fileSegmentName,
uint32_t segment, shared_ptr<Data> fileSegmentData);
void
Did_FetchManager_FileSegmentFetch_Execute(Name deviceName, Name fileSegmentName, uint32_t segment,
shared_ptr<Data> fileSegmentData);
void
Did_FetchManager_FileFetchComplete(const Name& deviceName, const Name& fileBaseName);
void
Did_FetchManager_FileFetchComplete_Execute(Name deviceName, Name fileBaseName);
void
Handle_Prefix_Discovery(const Interest& interest, const Data& data);
void
DiscoverPrefix();
void
Did_LocalPrefix_Updated(const Name& prefix);
private:
void
AssembleFile_Execute(const Name& deviceName, const Buffer& filehash,
const boost::filesystem::path& relativeFilepath);
private:
Face& m_face;
unique_ptr<SyncCore> m_core;
SyncLogPtr m_syncLog;
ActionLogPtr m_actionLog;
FileStatePtr m_fileState;
FileStatePtr m_fileStateCow;
boost::filesystem::path m_rootDir;
boost::asio::io_service& m_ioService;
Scheduler m_scheduler;
util::scheduler::ScopedEventId m_autoDiscovery;
ObjectManager m_objectManager;
Name m_localUserName;
// maintain object db ptrs so that we don't need to create them
// for every fetched segment of a file
std::map<Buffer, shared_ptr<ObjectDb>> m_objectDbMap;
std::string m_sharedFolder;
unique_ptr<ContentServer> m_server;
unique_ptr<StateServer> m_stateServer;
FetchManagerPtr m_actionFetcher;
FetchManagerPtr m_fileFetcher;
KeyChain m_keyChain;
};
namespace error {
struct Dispatcher : virtual boost::exception, virtual std::exception
{
};
typedef boost::error_info<struct tag_errmsg, std::string> error_info_str;
} // namespace error
} // namespace chronoshare
} // namespace ndn
#endif // CHRONOSHARE_SRC_DISPATCHER_HPP