cache expiration
parent
dbfe970da2
commit
7242080191
24
dns/cache.py
24
dns/cache.py
|
@ -14,6 +14,8 @@ from dns.resource import ResourceRecord, RecordData
|
||||||
from dns.types import Type
|
from dns.types import Type
|
||||||
from dns.classes import Class
|
from dns.classes import Class
|
||||||
|
|
||||||
|
import datetime
|
||||||
|
|
||||||
|
|
||||||
class ResourceEncoder(json.JSONEncoder):
|
class ResourceEncoder(json.JSONEncoder):
|
||||||
""" Conver ResourceRecord to JSON
|
""" Conver ResourceRecord to JSON
|
||||||
|
@ -23,13 +25,16 @@ class ResourceEncoder(json.JSONEncoder):
|
||||||
"""
|
"""
|
||||||
def default(self, obj):
|
def default(self, obj):
|
||||||
if isinstance(obj, ResourceRecord):
|
if isinstance(obj, ResourceRecord):
|
||||||
return {
|
res = {
|
||||||
"name": obj.name,
|
"name": obj.name,
|
||||||
"type": Type.to_string(obj.type_),
|
"type": Type.to_string(obj.type_),
|
||||||
"class": Class.to_string(obj.class_),
|
"class": Class.to_string(obj.class_),
|
||||||
"ttl": obj.ttl,
|
"ttl": obj.ttl,
|
||||||
"rdata": obj.rdata.data
|
"rdata": obj.rdata.data
|
||||||
}
|
}
|
||||||
|
if obj.createDate is not None:
|
||||||
|
res['createDate'] = obj.createDate.isoformat()
|
||||||
|
return res
|
||||||
return json.JSONEncoder.default(self, obj)
|
return json.JSONEncoder.default(self, obj)
|
||||||
|
|
||||||
|
|
||||||
|
@ -44,14 +49,18 @@ def resource_from_json(dct):
|
||||||
class_ = Class.from_string(dct["class"])
|
class_ = Class.from_string(dct["class"])
|
||||||
ttl = dct["ttl"]
|
ttl = dct["ttl"]
|
||||||
rdata = RecordData.create(type_, dct["rdata"])
|
rdata = RecordData.create(type_, dct["rdata"])
|
||||||
return ResourceRecord(name, type_, class_, ttl, rdata)
|
try:
|
||||||
|
createDate = datetime.datetime.strptime(dct["createDate"], "%Y-%m-%dT%H:%M:%S.%f")
|
||||||
|
except KeyError, e:
|
||||||
|
createDate = None
|
||||||
|
return ResourceRecord(name, type_, class_, ttl, rdata, createDate)
|
||||||
|
|
||||||
class DummyCache(object):
|
class DummyCache(object):
|
||||||
""" Cache for ResourceRecords """
|
""" Cache for ResourceRecords """
|
||||||
|
|
||||||
def __init__(self, ttl):
|
def __init__(self, ttl):
|
||||||
pass
|
pass
|
||||||
def gc(self):
|
def sweep(self):
|
||||||
pass
|
pass
|
||||||
def lookup(self, dname, type_, class_):
|
def lookup(self, dname, type_, class_):
|
||||||
return []
|
return []
|
||||||
|
@ -76,8 +85,8 @@ class RecordCache(object):
|
||||||
self.records = []
|
self.records = []
|
||||||
self.ttl = ttl
|
self.ttl = ttl
|
||||||
|
|
||||||
def gc(self):
|
def sweep(self):
|
||||||
pass
|
self.records = [rec for rec in self.records if rec.valid()]
|
||||||
|
|
||||||
def lookup(self, dname, type_, class_):
|
def lookup(self, dname, type_, class_):
|
||||||
""" Lookup resource records in cache
|
""" Lookup resource records in cache
|
||||||
|
@ -90,7 +99,7 @@ class RecordCache(object):
|
||||||
type_ (Type): type
|
type_ (Type): type
|
||||||
class_ (Class): class
|
class_ (Class): class
|
||||||
"""
|
"""
|
||||||
|
self.sweep()
|
||||||
matches = lambda rec: rec.type_ == type_ and rec.class_ == class_ and rec.name.lower() == dname.lower()
|
matches = lambda rec: rec.type_ == type_ and rec.class_ == class_ and rec.name.lower() == dname.lower()
|
||||||
return filter(matches, self.records)
|
return filter(matches, self.records)
|
||||||
|
|
||||||
|
@ -102,6 +111,7 @@ class RecordCache(object):
|
||||||
"""
|
"""
|
||||||
if self.ttl > 0:
|
if self.ttl > 0:
|
||||||
record.ttl = self.ttl
|
record.ttl = self.ttl
|
||||||
|
record.createDate = datetime.datetime.now()
|
||||||
for rec in self.records:
|
for rec in self.records:
|
||||||
if rec.type_ == record.type_ and rec.class_ == record.class_ and rec.name.lower() == record.name.lower() \
|
if rec.type_ == record.type_ and rec.class_ == record.class_ and rec.name.lower() == record.name.lower() \
|
||||||
and rec.rdata.data == record.rdata.data:
|
and rec.rdata.data == record.rdata.data:
|
||||||
|
@ -115,8 +125,10 @@ class RecordCache(object):
|
||||||
""" Read the cache file from disk """
|
""" Read the cache file from disk """
|
||||||
with open("cache.json") as f:
|
with open("cache.json") as f:
|
||||||
self.records = json.load(f, object_hook=resource_from_json)
|
self.records = json.load(f, object_hook=resource_from_json)
|
||||||
|
self.sweep()
|
||||||
def write_cache_file(self):
|
def write_cache_file(self):
|
||||||
""" Write the cache file to disk """
|
""" Write the cache file to disk """
|
||||||
|
self.sweep()
|
||||||
with open("cache.json", 'w') as f:
|
with open("cache.json", 'w') as f:
|
||||||
json.dump(self.records, f, cls=ResourceEncoder, indent=4)
|
json.dump(self.records, f, cls=ResourceEncoder, indent=4)
|
||||||
|
|
||||||
|
|
|
@ -12,10 +12,11 @@ import struct
|
||||||
|
|
||||||
from dns.types import Type
|
from dns.types import Type
|
||||||
|
|
||||||
|
from datetime import timedelta, datetime
|
||||||
|
|
||||||
class ResourceRecord(object):
|
class ResourceRecord(object):
|
||||||
""" DNS resource record """
|
""" DNS resource record """
|
||||||
def __init__(self, name, type_, class_, ttl, rdata):
|
def __init__(self, name, type_, class_, ttl, rdata, createDate=None):
|
||||||
""" Create a new resource record
|
""" Create a new resource record
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
|
@ -29,6 +30,15 @@ class ResourceRecord(object):
|
||||||
self.class_ = class_
|
self.class_ = class_
|
||||||
self.ttl = ttl
|
self.ttl = ttl
|
||||||
self.rdata = rdata
|
self.rdata = rdata
|
||||||
|
self.createDate = createDate
|
||||||
|
|
||||||
|
def valid(self):
|
||||||
|
if self.createDate is None:
|
||||||
|
return True
|
||||||
|
time = datetime.now()
|
||||||
|
if (self.createDate + timedelta(seconds=self.ttl)) > time:
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return "<Resource " + Type.by_value[self.type_] + " " + self.name + ">"
|
return "<Resource " + Type.by_value[self.type_] + " " + self.name + ">"
|
||||||
|
|
Loading…
Reference in New Issue