CoAP/coapthon/layers/cachelayer.py
giacomo.tanganelli@for.unipi.it 4db21cd7e7 Porting to Python3
2018-01-23 11:31:46 +01:00

111 lines
3.7 KiB
Python

import logging
from coapthon.defines import Codes
from coapthon.caching.cache import *
__author__ = 'Emilio Vallati'
logger = logging.getLogger(__name__)
class CacheLayer(object):
def __init__(self, mode, max_dim=2048):
"""
:param max_dim:
"""
self.cache = Cache(mode, max_dim)
def receive_request(self, transaction):
"""
checks the cache for a response to the request
:param transaction:
:return:
"""
transaction.cached_element = self.cache.search_response(transaction.request)
if transaction.cached_element is None:
transaction.cacheHit = False
else:
transaction.response = transaction.cached_element.cached_response
transaction.response.mid = transaction.request.mid
transaction.cacheHit = True
age = transaction.cached_element.creation_time + transaction.cached_element.max_age - time.time()
if transaction.cached_element.freshness is True:
if age <= 0:
logger.debug("resource not fresh")
"""
if the resource is not fresh, its Etag must be added to the request so that the server might validate it instead of sending a new one
"""
transaction.cached_element.freshness = False
"""
ensuring that the request goes to the server
"""
transaction.cacheHit = False
logger.debug("requesting etag %s", transaction.response.etag)
transaction.request.etag = transaction.response.etag
else:
transaction.response.max_age = age
else:
transaction.cacheHit = False
return transaction
def send_response(self, transaction):
"""
updates the cache with the response if there was a cache miss
:param transaction:
:return:
"""
if transaction.cacheHit is False:
"""
handling response based on the code
"""
logger.debug("handling response")
self._handle_response(transaction)
return transaction
def _handle_response(self, transaction):
"""
handles responses based on their type
:param transaction:
:return:
"""
code = transaction.response.code
utils.check_code(code)
"""
VALID response:
change the current cache value by switching the option set with the one provided
also resets the timestamp
if the request etag is different from the response, send the cached response
"""
if code == Codes.VALID.number:
logger.debug("received VALID")
self.cache.validate(transaction.request, transaction.response)
if transaction.request.etag != transaction.response.etag:
element = self.cache.search_response(transaction.request)
transaction.response = element.cached_response
return transaction
"""
CHANGED, CREATED or DELETED response:
mark the requested resource as not fresh
"""
if code == Codes.CHANGED.number or code == Codes.CREATED.number or code == Codes.DELETED.number:
target = self.cache.search_related(transaction.request)
if target is not None:
for element in target:
self.cache.mark(element)
return transaction
"""
any other response code can be cached normally
"""
self.cache.cache_add(transaction.request, transaction.response)
return transaction