def handle_documents(env, response, distribution, storage): # get the content content = parse_request(env) index = content.get('index', [None])[0] document = content.get('document', [None])[0] if index: # take the 2 first hexa value to determine # in which cluster the data should be. # It works with 256 cluster only cluster_index = int(index[0:2], 16) target_host = distribution.get_host_from_cluster(cluster_index) if target_host != distribution.current_host: return http(response, "This document is not on this host but on host (%s)" % target_host) method = env['REQUEST_METHOD'] if method == 'GET': if not index: return http(response, "Must provide index (%s)" % index, code=404) try: document = read_document(storage, index) except IOError: return http(response, "Document not found.", code=404) return http(response, document) if method == 'POST': if not document: return http(response, "Must provide a json document.") if not index: index = create_index(document) try: store_document(storage, index, document) except json.DecodeError: return http(response, "Json is invalid.") return http(response, index) return http(response, "handle_documents:no routes")
def handle_hosts(env, response, host_pool): """Handle all the requests on this host""" method = env['REQUEST_METHOD'] if method == 'GET': return http(response, json.encode(host_pool)) # post method signify a new host as to integrated to the pool # or a request to join a pool of hosts # handling a new server that want to enter the pool if env['PATH_INFO'].startswith('/hosts/register'): content = parse_request(env) new_host_address = content.get('address', [None])[0] # already registered, is some server already migrating? We need to stop here. for host in host_pool: if host['address'] == new_host_address: return http(response, "This server is already in the pool.") if host['state'] == 'migrating': return http(response, "There is already a migrating server in the pool.") new_host = { 'address':new_host_address, 'index':len(host_pool), 'state':'migrating', } # if we were alone, we are now pooling. for host in host_pool: if host['state'] == 'alone': host['state'] = 'pooling' # register the new host host_pool.append(new_host) return http(response, WELCOME_POOL) if env['PATH_INFO'].startswith('/hosts/migration_finished'): content = parse_request(env) new_host_address = content.get('address', [None])[0] for host in host_pool: if host['state'] == 'migrating': if host['address'] != new_host_address: raise "Wrong!" host['state'] = 'pooling' return http(response, WELCOME_POOL) # handling the client that ask to join a pool if env['PATH_INFO'].startswith('/hosts/join'): if len(host_pool) > 1: return http(response, "Already in a pool.") content = parse_request(env) pool_address = content.get('pool_address', [None])[0] my_address = host_pool[0]['address'] if pool_address == my_address: return http(response, "That's silly.") req = get_pool_request(pool_address) try: data = urllib2.urlopen(req) except urllib2.URLError, e: return http(response, "Cannot get pool description.") new_pool = json.decode(data.read()) # empty local host_pool for host in range(len(host_pool)): host_pool.pop(0) for host in new_pool: host_pool.append(host) # notifiy all the other hosts that there is a new host in town for host in new_pool: # avoid deadly infinite loop if my_address != host['address']: req = register_pool_request(my_address, host['address']) data = urllib2.urlopen(req) assert(data.read() == WELCOME_POOL) #TODO: launch the cluster migration migrate_clusters(my_address, host_pool) # notify all the hosts that the data migration was sucessful for host in new_pool: if my_address != host['address']: req = migration_finished_request(my_address, host['address']) data = urllib2.urlopen(req) assert(data.read() == WELCOME_POOL) # request everything again req = get_pool_request(pool_address) try: data = urllib2.urlopen(req) except urllib2.URLError, e: return http(response, "Cannot get pool description.")
def handle_clusters(env, response, distribution, storage): content = parse_request(env) index = content.get('index', [None])[0] return http(response, json.encode(list_cluster(storage, index)))