return ret.country
def get_location(self, addr):
- family = self.guess_address_family(addr)
-
- if family == 6:
- query = "SELECT *, NULL AS city, NULL AS postal_code FROM geoip_ipv6 WHERE %s \
- BETWEEN start_ip AND end_ip LIMIT 1"
- elif family == 4:
- query = "SELECT * FROM geoip_ipv4 WHERE inet_to_bigint(%s) \
- BETWEEN start_ip AND end_ip LIMIT 1"
+ query = "SELECT * FROM geoip \
+ WHERE %s BETWEEN start_ip AND end_ip LIMIT 1"
return self.db.get(query, addr)
def get_asn(self, addr):
- family = self.guess_address_family(addr)
-
- if family == 6:
- query = "SELECT asn FROM geoip_asnv6 WHERE %s \
- BETWEEN start_ip AND end_ip LIMIT 1"
- elif family == 4:
- query = "SELECT asn FROM geoip_asnv4 WHERE inet_to_bigint(%s) \
- BETWEEN start_ip AND end_ip LIMIT 1"
+ query = "SELECT asn FROM geoip_asn \
+ WHERE %s BETWEEN start_ip AND end_ip LIMIT 1"
ret = self.db.get(query, addr)
return MirrorSet(self.backend, mirrors)
def get_by_hostname(self, hostname):
- mirror = self.db.get("SELECT id FROM mirrors WHERE hostname=%s", hostname)
+ ret = self.db.get("SELECT * FROM mirrors WHERE hostname = %s", hostname)
- return Mirror(self.backend, mirror.id)
+ if ret:
+ return Mirror(self.backend, ret.id, ret)
def get_with_file(self, filename, country=None):
# XXX quick and dirty solution - needs a performance boost
return mirrors
- def get_for_country(self, country):
- # XXX need option for random order
- mirrors = self.db.query("SELECT id FROM mirrors WHERE prefer_for_countries LIKE %s", country)
-
- for mirror in mirrors:
- yield self.get(mirror.id)
-
- def get_for_location(self, location):
+ def get_for_location(self, location, max_distance=4000, filename=None):
if not location:
- return None
-
- distance = 2500
+ return []
+
+ if filename:
+ res = self.db.query("\
+ WITH client AS (SELECT point(%s, %s) AS location) \
+ SELECT * FROM mirrors WHERE mirrors.state = %s \
+ AND mirrors.id IN ( \
+ SELECT mirror FROM mirror_files WHERE filename = %s \
+ ) AND mirrors.id IN ( \
+ SELECT id FROM mirrors_locations, client \
+ WHERE geodistance(mirrors_locations.location, client.location) <= %s \
+ )",
+ location.latitude, location.longitude, "UP", filename, max_distance)
+ else:
+ res = self.db.query("\
+ WITH client AS (SELECT point(%s, %s) AS location) \
+ SELECT * FROM mirrors WHERE mirrors.state = %s AND mirrors.id IN ( \
+ SELECT id FROM mirrors_locations, client \
+ WHERE geodistance(mirrors_locations.location, client.location) <= %s \
+ )",
+ location.latitude, location.longitude, "UP", max_distance)
mirrors = []
- all_mirrors = self.get_all()
-
- while all_mirrors and len(mirrors) <= 3 and distance <= 8000:
- for mirror in all_mirrors:
- mirror_distance = mirror.distance_to(location)
- if mirror_distance is None:
- continue
-
- if mirror_distance<= distance:
- mirrors.append(mirror)
- all_mirrors.remove(mirror)
-
- distance *= 1.2
+ for row in res:
+ mirror = Mirror(self.backend, row.id, row)
+ mirrors.append(mirror)
- return mirrors
+ return sorted(mirrors)
def get_all_files(self):
files = []
return files
+ def get_random(self, filename=None):
+ if filename:
+ ret = self.db.get("SELECT * FROM mirrors WHERE state = %s \
+ AND mirrors.id IN (SELECT mirror FROM mirror_files \
+ WHERE filename = %s) ORDER BY RANDOM() LIMIT 1", "UP", filename)
+ else:
+ ret = self.db.get("SELECT * FROM mirrors WHERE state = %s \
+ ORDER BY RANDOM() LIMIT 1", "UP")
+
+ if ret:
+ return Mirror(self.backend, ret.id, ret)
+
+ def file_exists(self, filename):
+ ret = self.db.get("SELECT 1 FROM mirror_files \
+ WHERE filename = %s LIMIT 1", filename)
+
+ if ret:
+ return True
+
+ return False
+
class MirrorSet(Object):
def __init__(self, backend, mirrors):
return random.choice(mirrors)
- def get_for_country(self, country):
- mirrors = []
-
- for mirror in self._mirrors:
- if country in mirror.prefer_for_countries:
- mirrors.append(mirror)
-
- return MirrorSet(self.backend, mirrors)
-
def get_for_location(self, location):
distance = 2500
mirrors = []
self.redirect_to_mirror(filename, log_download=True)
def find_mirror(self, filename):
- # Get all mirrors...
- mirrors = self.mirrors.get_all()
- mirrors = mirrors.get_with_file(filename)
- mirrors = mirrors.get_with_state("UP")
-
- if not mirrors:
+ exists = self.mirrors.file_exists(filename)
+ if not exists:
raise tornado.web.HTTPError(404, "File not found: %s" % filename)
# Find mirrors located near to the user.
- # If we have not found any, we use all.
+ # If we have not found any, we use a random one.
remote_location = self.get_remote_location()
if remote_location:
- mirrors_nearby = mirrors.get_for_location(remote_location)
+ mirrors = self.mirrors.get_for_location(remote_location, filename=filename)
- if mirrors_nearby:
- mirrors = mirrors_nearby
+ if mirrors:
+ return random.choice(mirrors)
- return mirrors.get_random()
+ return self.mirrors.get_random(filename=filename)
def redirect_to_mirror(self, filename, log_download=False):
# Find a random mirror.
class DownloadCompatHandler(BaseHandler):
def get(self, path, url):
- _filename = None
-
for filename in self.mirrors.get_all_files():
- if filename.endswith("/%s" % url):
- _filename = filename
- break
+ if not filename.endswith("/%s" % url):
+ continue
- if not _filename:
- raise tornado.web.HTTPError(404)
+ self.redirect("/%s" % filename)
+ return
- self.redirect("/%s" % _filename)
+ raise tornado.web.HTTPError(404)
class DownloadSplashHandler(BaseHandler):