~canonical-ci-engineering/ubuntu-ci-services-itself/graphite-web

« back to all changes in this revision

Viewing changes to webapp/graphite/render/hashing.py

  • Committer: Package Import Robot
  • Author(s): Jonas Genannt
  • Date: 2013-03-09 16:06:34 UTC
  • Revision ID: package-import@ubuntu.com-20130309160634-p1ei8oxvm3plrbas
Tags: upstream-0.9.10+debian
ImportĀ upstreamĀ versionĀ 0.9.10+debian

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
"""Copyright 2008 Orbitz WorldWide
 
2
   Copyright 2011 Chris Davis
 
3
 
 
4
Licensed under the Apache License, Version 2.0 (the "License");
 
5
you may not use this file except in compliance with the License.
 
6
You may obtain a copy of the License at
 
7
 
 
8
   http://www.apache.org/licenses/LICENSE-2.0
 
9
 
 
10
Unless required by applicable law or agreed to in writing, software
 
11
distributed under the License is distributed on an "AS IS" BASIS,
 
12
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 
13
See the License for the specific language governing permissions and
 
14
limitations under the License."""
 
15
 
 
16
from graphite.logger import log
 
17
import time
 
18
try:
 
19
  from hashlib import md5
 
20
except ImportError:
 
21
  from md5 import md5
 
22
import bisect
 
23
 
 
24
def hashRequest(request):
 
25
  # Normalize the request parameters so ensure we're deterministic
 
26
  queryParams = ["%s=%s" % (key, '&'.join(values))
 
27
                 for (key,values) in request.GET.lists()
 
28
                 if not key.startswith('_')]
 
29
 
 
30
  normalizedParams = ','.join( sorted(queryParams) ) or 'noParam'
 
31
  myHash = stripControlChars(normalizedParams) #memcached doesn't like unprintable characters in its keys
 
32
 
 
33
  return compactHash(myHash)
 
34
 
 
35
 
 
36
def hashData(targets, startTime, endTime):
 
37
  targetsString = ','.join(targets)
 
38
  startTimeString = startTime.strftime("%Y%m%d_%H%M")
 
39
  endTimeString = endTime.strftime("%Y%m%d_%H%M")
 
40
  myHash = targetsString + '@' + startTimeString + ':' + endTimeString
 
41
  myHash = stripControlChars(myHash)
 
42
 
 
43
  return compactHash(myHash)
 
44
 
 
45
 
 
46
def stripControlChars(string):
 
47
  return filter(lambda char: ord(char) >= 33, string)
 
48
 
 
49
 
 
50
def compactHash(string):
 
51
  hash = md5()
 
52
  hash.update(string)
 
53
  return hash.hexdigest()
 
54
 
 
55
 
 
56
 
 
57
class ConsistentHashRing:
 
58
  def __init__(self, nodes, replica_count=100):
 
59
    self.ring = []
 
60
    self.replica_count = replica_count
 
61
    for node in nodes:
 
62
      self.add_node(node)
 
63
 
 
64
  def compute_ring_position(self, key):
 
65
    big_hash = md5( str(key) ).hexdigest()
 
66
    small_hash = int(big_hash[:4], 16)
 
67
    return small_hash
 
68
 
 
69
  def add_node(self, key):
 
70
    for i in range(self.replica_count):
 
71
      replica_key = "%s:%d" % (key, i)
 
72
      position = self.compute_ring_position(replica_key)
 
73
      entry = (position, key)
 
74
      bisect.insort(self.ring, entry)
 
75
 
 
76
  def remove_node(self, key):
 
77
    self.ring = [entry for entry in self.ring if entry[1] != key]
 
78
 
 
79
  def get_node(self, key):
 
80
    position = self.compute_ring_position(key)
 
81
    search_entry = (position, None)
 
82
    index = bisect.bisect_left(self.ring, search_entry)
 
83
    index %= len(self.ring)
 
84
    entry = self.ring[index]
 
85
    return entry[1]