if qp[0] == 'OPTIONS':
self.request = None
else:
- if qp[1].startswith('/search'):
+ if '/search' in qp[1]:
self.request = 'S'
- elif qp[1].startswith('/reverse'):
+ elif '/reverse' in qp[1]:
self.request = 'R'
- elif qp[1].startswith('/details'):
+ elif '/details' in qp[1]:
self.request = 'D'
else:
self.request = None
return LogEntry.get_log_time(l) if l is not None else None
def seek_to_date(self, target):
- date1 = self.seek_next(0)
- if date1 > target:
+ # start position for binary search
+ fromseek = 0
+ fromdate = self.seek_next(0)
+ if fromdate > target:
+ return True
+ # end position for binary search
+ toseek = -100
+ while -toseek < self.len:
+ todate = self.seek_next(self.len + toseek)
+ if todate is not None:
+ break
+ toseek -= 100
+ if todate is None or todate < target:
return False
- curseek = 2*1024*1024
- curdate = self.seek_next(curseek)
- if curdate is None:
- raise RuntimeError("Cannot seek to %d" % curseek)
- while target < curdate or (target - curdate).total_seconds() > 1:
- bps = curseek / ((curdate - date1).total_seconds())
- curseek += (target - curdate).total_seconds() * bps
- if curseek < 0:
- curseek = 0
- elif curseek > self.len:
- curseek = self.len - bps
- curdate = self.seek_next(curseek)
- if curdate is None:
- raise RuntimeError("Cannot see to %d" % curseek)
- return True
+ toseek = self.len + toseek
+
+
+ while True:
+ bps = (toseek - fromseek) / (todate - fromdate).total_seconds()
+ newseek = fromseek + int((target - fromdate).total_seconds() * bps)
+ newdate = self.seek_next(newseek)
+ if newdate is None:
+ return False;
+ error = abs((target - newdate).total_seconds())
+ if error < 1:
+ return True
+ if newdate > target:
+ toseek = newseek
+ todate = newdate
+ oldfromseek = fromseek
+ fromseek = toseek - error * bps
+ while True:
+ if fromseek <= oldfromseek:
+ fromseek = oldfromseek
+ fromdate = self.seek_next(fromseek)
+ break
+ fromdate = self.seek_next(fromseek)
+ if fromdate < target:
+ break;
+ bps *=2
+ fromseek -= error * bps
+ else:
+ fromseek = newseek
+ fromdate = newdate
+ oldtoseek = toseek
+ toseek = fromseek + error * bps
+ while True:
+ if toseek > oldtoseek:
+ toseek = oldtoseek
+ todate = self.seek_next(toseek)
+ break
+ todate = self.seek_next(toseek)
+ if todate > target:
+ break
+ bps *=2
+ toseek += error * bps
+ if toseek - fromseek < 500:
+ return True
+
def loglines(self):
for l in self.fd:
- yield LogEntry(l)
+ try:
+ yield LogEntry(l)
+ except ValueError:
+ pass # ignore invalid lines
class BlockList: