blob: fa5a2bb48894eb8699831c211929af7b30208504 [file] [log] [blame]
Zhenkai Zhue42b4572013-01-22 15:57:54 -08001/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil -*- */
2/*
3 * Copyright (c) 2013 University of California, Los Angeles
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2 as
7 * published by the Free Software Foundation;
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 *
18 * Author: Zhenkai Zhu <zhenkai@cs.ucla.edu>
19 * Alexander Afanasyev <alexander.afanasyev@ucla.edu>
20 */
21
22#include "content-server.h"
Alexander Afanasyev28ca3ed2013-01-24 23:17:15 -080023#include "logging.h"
24#include <boost/lexical_cast.hpp>
25
26INIT_LOGGER ("ContentServer");
Zhenkai Zhue42b4572013-01-22 15:57:54 -080027
28using namespace Ccnx;
29using namespace std;
Alexander Afanasyev28ca3ed2013-01-24 23:17:15 -080030using namespace boost;
Zhenkai Zhue42b4572013-01-22 15:57:54 -080031
Alexander Afanasyev28ca3ed2013-01-24 23:17:15 -080032ContentServer::ContentServer(CcnxWrapperPtr ccnx, ActionLogPtr actionLog,
33 const boost::filesystem::path &rootDir,
34 const Ccnx::Name &deviceName, const std::string &sharedFolderName,
35 int freshness)
36 : m_ccnx(ccnx)
37 , m_actionLog(actionLog)
38 , m_dbFolder(rootDir / ".chronoshare")
39 , m_freshness(freshness)
40 , m_executor (1)
41 , m_deviceName (deviceName)
42 , m_sharedFolderName (sharedFolderName)
Zhenkai Zhue42b4572013-01-22 15:57:54 -080043{
Alexander Afanasyev28ca3ed2013-01-24 23:17:15 -080044 m_executor.start ();
Zhenkai Zhue42b4572013-01-22 15:57:54 -080045}
46
47ContentServer::~ContentServer()
48{
Alexander Afanasyev28ca3ed2013-01-24 23:17:15 -080049 m_executor.shutdown ();
50
51 ScopedLock lock (m_mutex);
Zhenkai Zhue42b4572013-01-22 15:57:54 -080052 for (PrefixIt it = m_prefixes.begin(); it != m_prefixes.end(); ++it)
53 {
Alexander Afanasyev28ca3ed2013-01-24 23:17:15 -080054 m_ccnx->clearInterestFilter (Name (*it)(m_deviceName)("action")(m_sharedFolderName));
55 m_ccnx->clearInterestFilter (Name (*it)(m_deviceName)("file"));
Zhenkai Zhue42b4572013-01-22 15:57:54 -080056 }
57}
58
59void
60ContentServer::registerPrefix(const Name &prefix)
61{
Zhenkai Zhuc3a27872013-01-25 19:21:25 -080062 m_ccnx->setInterestFilter (prefix, bind(&ContentServer::serve, this, prefix, _1));
Zhenkai Zhub74e1e92013-01-25 14:36:18 -080063
Zhenkai Zhuc3a27872013-01-25 19:21:25 -080064 _LOG_DEBUG (">> content server: register " << prefix);
Alexander Afanasyev28ca3ed2013-01-24 23:17:15 -080065
66 ScopedLock lock (m_mutex);
Zhenkai Zhue42b4572013-01-22 15:57:54 -080067 m_prefixes.insert(prefix);
68}
69
70void
Alexander Afanasyev28ca3ed2013-01-24 23:17:15 -080071ContentServer::deregisterPrefix (const Name &prefix)
Zhenkai Zhue42b4572013-01-22 15:57:54 -080072{
Alexander Afanasyev28ca3ed2013-01-24 23:17:15 -080073
Zhenkai Zhuc3a27872013-01-25 19:21:25 -080074 m_ccnx->clearInterestFilter(prefix);
Alexander Afanasyev28ca3ed2013-01-24 23:17:15 -080075
Zhenkai Zhuc3a27872013-01-25 19:21:25 -080076 _LOG_DEBUG ("<< content server: deregister " << prefix);
Alexander Afanasyev28ca3ed2013-01-24 23:17:15 -080077 ScopedLock lock (m_mutex);
78 m_prefixes.erase (prefix);
Zhenkai Zhue42b4572013-01-22 15:57:54 -080079}
80
81void
Zhenkai Zhuc3a27872013-01-25 19:21:25 -080082ContentServer::serve(Name forwardingHint, const Name &interest)
83{
84 // /forwardingHint/device-name/action/shared-folder/action-seq
85 // /forwardingHint/device-name/file/file-hash/segment
86
87 Name name = interest.getPartialName(forwardingHint.size());
88 if (name.size() > 3)
89 {
90 string type = name.getCompAsString(name.size() - 3);
91 if (type == "action")
92 {
93 serve_Action (forwardingHint, interest);
94 }
95 else if (type == "file")
96 {
97 serve_File (forwardingHint, interest);
98 }
99 }
100}
101
102void
Alexander Afanasyev28ca3ed2013-01-24 23:17:15 -0800103ContentServer::serve_Action (Name forwardingHint, const Name &interest)
Zhenkai Zhue42b4572013-01-22 15:57:54 -0800104{
Zhenkai Zhub74e1e92013-01-25 14:36:18 -0800105 _LOG_DEBUG (">> content server serving, forwardHing " << forwardingHint << ", interest " << interest);
Alexander Afanasyev28ca3ed2013-01-24 23:17:15 -0800106 m_executor.execute (bind (&ContentServer::serve_Action_Execute, this, forwardingHint, interest));
107 // need to unlock ccnx mutex... or at least don't lock it
108}
109
110void
111ContentServer::serve_File (Name forwardingHint, const Name &interest)
112{
Zhenkai Zhub74e1e92013-01-25 14:36:18 -0800113 _LOG_DEBUG (">> content server serving, forwardHing " << forwardingHint << ", interest " << interest);
Alexander Afanasyev28ca3ed2013-01-24 23:17:15 -0800114 m_executor.execute (bind (&ContentServer::serve_File_Execute, this, forwardingHint, interest));
115 // need to unlock ccnx mutex... or at least don't lock it
116}
117
118void
119ContentServer::serve_File_Execute (Name forwardingHint, Name interest)
120{
121 // /device-name/file/<file-hash>/segment, or
122
123 int64_t segment = interest.getCompFromBackAsInt (0);
124 Name deviceName = interest.getPartialName (forwardingHint.size (), interest.size () - forwardingHint.size () - 3);
125 Hash hash (head(interest.getCompFromBack (1)), interest.getCompFromBack (1).size());
126
127 _LOG_DEBUG (" server FILE for device: " << deviceName << ", file_hash: " << hash << " segment: " << segment);
128
129 string hashStr = lexical_cast<string> (hash);
130 if (ObjectDb::DoesExist (m_dbFolder, deviceName, hashStr)) // this is kind of overkill, as it counts available segments
Zhenkai Zhue42b4572013-01-22 15:57:54 -0800131 {
Alexander Afanasyev28ca3ed2013-01-24 23:17:15 -0800132 ObjectDb db (m_dbFolder, hashStr);
133 // may do prefetching
134
135 BytesPtr co = db.fetchSegment (deviceName, segment);
136 if (co)
Zhenkai Zhue42b4572013-01-22 15:57:54 -0800137 {
Alexander Afanasyev28ca3ed2013-01-24 23:17:15 -0800138 if (forwardingHint.size () == 0)
139 {
140 m_ccnx->putToCcnd (*co);
141 }
142 else
143 {
144 if (m_freshness > 0)
145 {
146 m_ccnx->publishData(interest, *co, m_freshness);
147 }
148 else
149 {
150 m_ccnx->publishData(interest, *co);
151 }
152 }
153
154 }
155 else
156 {
157 _LOG_ERROR ("ObjectDd exists, but no segment " << segment << " for device: " << deviceName << ", file_hash: " << hash);
158 }
159 }
160 else
161 {
162 _LOG_ERROR ("ObjectDd doesn't exist for device: " << deviceName << ", file_hash: " << hash);
163 }
164
165}
166
167void
168ContentServer::serve_Action_Execute (Name forwardingHint, Name interest)
169{
170 // /device-name/action/shared-folder/seq
171
172 int64_t seqno = interest.getCompFromBackAsInt (0);
173 Name deviceName = interest.getPartialName (forwardingHint.size (), interest.size () - forwardingHint.size () - 3);
174
175 _LOG_DEBUG (" server ACTION for device: " << deviceName << " and seqno: " << seqno);
176
177 PcoPtr pco = m_actionLog->LookupActionPco (deviceName, seqno);
178 if (pco)
179 {
180 if (forwardingHint.size () == 0)
181 {
182 m_ccnx->putToCcnd (pco->buf ());
183 }
184 else
185 {
186 const Bytes &content = pco->buf ();
187 if (m_freshness > 0)
Zhenkai Zhubc738572013-01-23 22:46:11 -0800188 {
189 m_ccnx->publishData(interest, content, m_freshness);
190 }
Alexander Afanasyev28ca3ed2013-01-24 23:17:15 -0800191 else
Zhenkai Zhubc738572013-01-23 22:46:11 -0800192 {
193 m_ccnx->publishData(interest, content);
194 }
Zhenkai Zhue42b4572013-01-22 15:57:54 -0800195 }
Zhenkai Zhue42b4572013-01-22 15:57:54 -0800196 }
Alexander Afanasyev28ca3ed2013-01-24 23:17:15 -0800197 else
198 {
199 _LOG_ERROR ("ACTION not found for device: " << deviceName << " and seqno: " << seqno);
200 }
Zhenkai Zhue42b4572013-01-22 15:57:54 -0800201}