std::cout << string << std::endl;
std::stringstream response;
- response << "HTTP/1.0 200 OK\r\n" << "Content-Length: " << size << "\r\n\r\n" << string;
+ response << "HTTP/1.1 200 OK\r\n" << "Content-Length: " << size << "\r\n\r\n" << string;
std::string response_string = response.str();
+ std::chrono::milliseconds expiry_time(std::chrono::milliseconds(4000 * 1000));
+
std::thread t([publisher, response_string]() {
- publisher->publishContent((uint8_t *) response_string.data(), response_string.size(), 0, true);
+ publisher->publishContent((uint8_t *) response_string.data(),
+ response_string.size(),
+ std::chrono::milliseconds(transport::default_values::content_object_expiry_time),
+ 0,
+ true);
publisher->serveClients();
});
return *this;
}
-void HTTPServerPublisher::publishContent(const uint8_t *buf, size_t buffer_size, const int response_id, bool is_last) {
+void HTTPServerPublisher::publishContent(const uint8_t *buf, size_t buffer_size, std::chrono::milliseconds content_lifetime, const int response_id, bool is_last) {
if (producer_) {
#ifdef __ANDROID__
__android_log_print(ANDROID_LOG_DEBUG, "HTTP_SERVER_PUBLISHER", "Replying to %s", const_cast<transport::Name &>(content_name_).toString().c_str());
#else
std::cout << "Replying to " << content_name_ << std::endl;
#endif
+ producer_->setSocketOption(transport::GeneralTransportOptions::CONTENT_OBJECT_EXPIRY_TIME, static_cast<int>(content_lifetime.count()));
+
producer_->produce(content_name_, buf, buffer_size, response_id, is_last);
}
}
void publishContent(const uint8_t *buf,
size_t buffer_size,
+ std::chrono::milliseconds content_lifetime,
const int response_id,
bool is_last);
}
void ContentStore::insert(const std::shared_ptr<ContentObject> &content_object) {
- std::unique_lock<std::mutex> lock(cs_mutex_);
- if (content_store_hash_table_.size() >= max_content_store_size_) {
- // Evict item
- content_store_hash_table_.erase(lru_list_.back());
- lru_list_.pop_back();
- }
+ // Check if the content can be cached
+ if (content_object->getExpiryTime() > 0) {
+ std::unique_lock<std::mutex> lock(cs_mutex_);
+ if (content_store_hash_table_.size() >= max_content_store_size_) {
+ // Evict item
+ content_store_hash_table_.erase(lru_list_.back());
+ lru_list_.pop_back();
+ }
- // Insert new item
- lru_list_.push_back(std::cref(content_object->getName()));
- LRUList::iterator pos = lru_list_.end();
- content_store_hash_table_[content_object->getName()] = CcnxContentStoreEntry(content_object, pos);
+ // Insert new item
+ lru_list_.push_back(std::cref(content_object->getName()));
+ LRUList::iterator pos = lru_list_.end();
+ content_store_hash_table_[content_object->getName()] = ContentStoreEntry(ObjectTimeEntry(content_object,
+ std::chrono::steady_clock::now()), pos);
+ }
}
ContentStoreHashTable::iterator it = content_store_hash_table_.find(interest.getName());
if (it != content_store_hash_table_.end()) {
if (it->second.second != lru_list_.begin()) {
- // Move element to the top of the LRU list
- lru_list_.splice(lru_list_.begin(), lru_list_, it->second.second);
+ if (std::chrono::duration_cast<std::chrono::milliseconds>(
+ std::chrono::steady_clock::now().time_since_epoch()).count()
+ < it->second.first.first->getExpiryTime()) {
+ // Move element to the top of the LRU list
+ lru_list_.splice(lru_list_.begin(), lru_list_, it->second.second);
+ return it->second.first.first;
+ } else {
+ // Stale content
+ content_store_hash_table_.erase(interest.getName());
+ }
}
- return it->second.first;
- } else {
- return empty_reference_;
}
+
+ return empty_reference_;
}
void ContentStore::erase(const Name &exact_name) {
namespace transport {
-typedef std::pair<std::shared_ptr<ContentObject>, std::list<std::reference_wrapper<const Name>>::iterator>
- CcnxContentStoreEntry;
+typedef std::pair<std::shared_ptr<ContentObject>, std::chrono::steady_clock::time_point> ObjectTimeEntry;
+typedef std::pair<ObjectTimeEntry, std::list<std::reference_wrapper<const Name>>::iterator>
+ ContentStoreEntry;
typedef std::list<std::reference_wrapper<const Name>> LRUList;
-typedef std::unordered_map<Name, CcnxContentStoreEntry> ContentStoreHashTable;
+typedef std::unordered_map<Name, ContentStoreEntry> ContentStoreHashTable;
class ContentStore {
public:
Name full_name = name;
content_object_segment = std::make_shared<ContentObject>(std::move(full_name.appendSegment(current_segment)));
- // content_object_segment->setExpiryTime((uint64_t) m_dataFreshness);
+ content_object_segment->setExpiryTime((uint64_t) content_object_expiry_time_);
if (packaged_segments == number_of_segments - 1) {
content_object_segment->setContent(&buf[bytes_segmented], buffer_size - bytes_segmented);
content_object = std::make_shared<ContentObject>(std::move(fullName.appendSegment(current_segment)));
// TODO If we set the throughput will decrease.. to investigate
- // content_object->setExpiryTime((uint64_t)m_dataFreshness);
+ content_object->setExpiryTime((uint64_t)content_object_expiry_time_);
if (is_last) {
content_object->setFinalChunkNumber(current_segment + number_of_segments - packaged_segments - 1);