#
# RTEMS Tools Project (http://www.rtems.org/)
# Copyright 2022 Chris Johns (chris@contemporary.software)
# All rights reserved.
#
# This file is part of the RTEMS Tools package in 'rtems-tools'.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
# 1. Redistributions of source code must retain the above copyright notice,
# this list of conditions and the following disclaimer.
#
# 2. Redistributions in binary form must reproduce the above copyright notice,
# this list of conditions and the following disclaimer in the documentation
# and/or other materials provided with the distribution.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
#
import pickle
import os
import urllib.request
class cache(object):
def __init__(self, milestone, path, force):
self.milestone = milestone
self.path = path
self.force = force
self.checked = False
self.cache_valid = False
@staticmethod
def _milestone(url):
path, options = url.split('?', 1)
opts = options.split('&')
for o in opts:
if 'milestone' in o:
label, milestone = o.split('=', 1)
return milestone
raise RuntimeError('milestone not found: ' + url)
def _tickets_path(self):
return os.path.join(self.path,
'tickets-%s' % (self.milestone) + '.ppk')
def _ticket_path(self, url):
path, options = url.split('?', 1)
opts = options.split('&')
fmt = None
for o in opts:
if 'format' in o:
label, fmt = o.split('=', 1)
if not fmt:
raise RuntimeError('ticket format not found: ' + url)
if '/' in path:
ticket_id = path[path.rfind('/') + 1:]
return os.path.join(self.path, '%s.%s' % (ticket_id, fmt))
raise RuntimeError('ticket id not found: ' + url)
def _query_path(self):
return os.path.join(self.path, 'query-%s' % (self.milestone) + '.csv')
def check(self):
if not self.checked:
self.checked = True
if self.path:
if os.path.exists(self.path):
if not os.path.isdir(self.path):
raise RuntimeError('cache is not a directory:' +
self.path)
else:
os.mkdir(self.path)
self.cache_valid = True
return self.cache_valid
def open_page(self, url):
url_path = None
if self.check():
if 'query' in url:
url_path = self._query_path()
else:
url_path = self._ticket_path(url)
if not self.force and os.path.exists(url_path):
return open(url_path, 'rb')
# Open the URL
delay = 1
tries = 6
backoff = 2
while tries > 0:
try:
page = urllib.request.urlopen(url)
if url_path:
with open(url_path, 'wb') as f:
f.write(page.read())
return open(url_path, 'rb')
return page
except OSError:
tries -= 1
time.sleep(delay)
delay *= backoff
raise RuntimeError('cannot open url:' + url)
def load(self):
if self.check():
ticket_cache = self._tickets_path()
if os.path.exists(ticket_cache):
if not self.force:
try:
with open(ticket_cache, 'rb') as f:
tickets = pickle.load(f)
print('%d tickets loaded from cache: %s' %
(len(tickets['tickets']), ticket_cache))
return tickets
except:
print('cache corrupted: ' + ticket_cache)
os.remove(ticket_cache)
return None
def unload(self, tickets):
if self.check():
ticket_cache = self._tickets_path()
with open(ticket_cache, 'wb') as f:
pickle.dump(tickets, f)