Exemplo n.º 1
0
async def get_experiment(request, experiment_id):
    redis = request.app.redis
    session_id = request['session'].sid

    try:
        experiment = json.loads(await redis.hget(
            hash_key('experiments', experiment_id), experiment_id))
    except TypeError as e:
        print('Error', e)
        return json_response(
            {"message": "Invalid experiment. Has it been registered?"},
            status=404)
    print('--- expr', experiment)

    # TODO check if session in experiment
    # if not, increase samples
    # TODO always return same choice for this session
    print('--', hash_key('samples', experiment_id), experiment_id)

    policy = POLICIES[experiment.get('policy')]
    choice_idx = await policy(experiment_id, experiment, redis)

    print('--- choice_idx', choice_idx)
    await redis.sadd('samples:%s:%s' % (experiment_id, choice_idx),
                     [session_id])

    return json_response({
        "message": "Ok.",
        "choice": choice_idx,
    })
Exemplo n.º 2
0
 async def find_node_responsible_for_key(self, key: str):
     hashed_key = hash_key(key)
     node_responsible = await self.find_node_responsible_for_addr(hashed_key
                                                                  )
     trace_log('SuccRouter: Found the node responsible for key ', key,
               ' : ', node_responsible)
     return node_responsible
Exemplo n.º 3
0
async def thompson_sampling(experiment_id, experiment, redis):
    """
    Continuously chooses based on observed successes, e.g. Polya's urn.
    """
    choices = experiment['choices']
    p = np.zeros(len(choices))
    for choice in choices:
        p[choice] = await redis.scard(
            # FIXME (what needs fixing here? doh!)
            hash_key('successes', experiment_id) + ':' + choice)
    p /= p.sum()
    return np.random.choice(len(p), p=p)
Exemplo n.º 4
0
async def register_experiment(request):
    redis = request.app.redis

    experiment_id = uuid.uuid4().hex
    experiment = EXPERIMENT_SCHEMA.validate(request.json)

    experiment_exists = await redis.hexists(
        hash_key('experiments', experiment_id), experiment_id)
    if experiment_exists:
        return json_response(
            {"message": "Experiment by this id already exists."}, status=400)

    await redis.hset(
        hash_key('experiments', experiment_id),
        experiment_id,
        json.dumps(experiment),
    )

    print('- registered')
    return json_response({
        "message": "New experiment created.",
        "experiment_id": experiment_id,
    })
Exemplo n.º 5
0
 async def copy_to(self, to_node: int, interval: Interval):
     """
     Copy the keys of an interval from our persistant storage to the `to_node`.
     """
     trace_log("KeyTransferer ", self.chord_addr,
               " : Starting copy of keys from myself to ", to_node)
     all_keys = await self.persistant_storage.get_keys()
     keys_to_transfer = [
         key for key in all_keys if interval.in_interval(hash_key(key))
     ]
     dict_to_transfer = {}
     for key in keys_to_transfer:
         dict_to_transfer[key] = await self.persistant_storage.get(key)
     await self.copy_key_values_to(to_node, interval, dict_to_transfer)
Exemplo n.º 6
0
    async def handle_transfer_keys_to_me(self, msg: Message):
        """
        Handle a request to transfer keys to me.
        """
        if self.router == None:
            return
        interval, data_dict, copy_node, receiving_node = msg.get_args(
            ['interval', 'data_dict', 'copy_node', 'receiving_node'])
        interval = parse_interval_str(interval)
        receiving_node = int(receiving_node)
        copy_node = int(copy_node)
        if debug_log_key_transfers:
            debug_log("KeyTransferer", self.chord_addr,
                      ": Handling transfer keys from",
                      copy_node, "to", self.chord_addr, "of interval",
                      interval.to_string(), "current-pred",
                      self.router.predecessor, " succ ", self.router.successor)

        data_to_store = None
        # Check that we should recieve these and that this is in fact intended for us.
        if (self.chord_addr == self.router.successor
                or self.router.predecessor == None):
            # These are intended for us, because we control everything
            # Store the data on disk
            data_to_store = data_dict
        else:
            # assert(interval.top == self.chord_addr and interval.top_closed)
            print("interval is", interval, "predecessor",
                  self.router.predecessor)
            if (interval.in_interval(self.router.predecessor)):
                # This means the whole interval isn't for us.
                # Take out what's ours and foward what ever else there is
                our_key_range = Interval(self.chord_addr, True,
                                         self.router.successor, False)
                our_keys = set(key for key in data_dict.keys()
                               if our_key_range.in_interval(hash_key(key)))
                dict_that_is_ours = dict(
                    {key: data_dict[key]
                     for key in our_keys})

                other_keys = set(data_dict.keys()).difference(our_keys)
                dict_that_isnt_ours = {
                    key: data_dict[key]
                    for key in other_keys
                }
                # Assume we are the end of the interval, then we need to pass it back wards.
                other_range = Interval(interval.bottom, interval.bottom_closed,
                                       self.router.predecessor, True)
                # Pass along the rest of the interval
                await self.copy_key_values_to(self.router.predecessor,
                                              other_range, dict_that_isnt_ours)
                data_to_store = dict_that_is_ours
            else:
                # This means we are replicating
                data_to_store = data_dict

        # Store the data on disk
        debug_log("KeyTransferer", self.chord_addr,
                  ": Handling transfer keys from",
                  copy_node, "to", self.chord_addr, "of interval",
                  interval.to_string(), "current-pred",
                  self.router.predecessor, " succ ", self.router.successor,
                  "data", data_to_store)
        await self.persistant_storage.add_dict(data_to_store)

        # Confirm what we stored.
        self.send_confirm_transfer(copy_node, interval, data_dict)
Exemplo n.º 7
0
    async def handle_set(self, msg: Message):
        """
        Handle a client request to set the value of a key among the chord network.
        """
        if not self.alive:
            return
        # Set the key
        assert ('key' in msg.args and 'value' in msg.args and 'id' in msg.args)
        key = msg.args['key']
        req_id = msg.args['id']
        value = msg.args['value']
        debug_test("Chord", self.chord_addr,": set request key", key, "to value", value, "with hash", hash_key(key))
        
        node_responsible_addr = await self.router.find_node_responsible_for_key(key) 
        debug_test("Chord", self.chord_addr,": found node responsible for", key, node_responsible_addr)

        if (node_responsible_addr == self.chord_addr):
            debug_test("Chord", self.chord_addr,": setting ", key, "to value", value)
            await self.persistent_storage.set(key, value)
            debug_test("Chord", self.chord_addr,": setting ", key, "to value", value, "complete")
            # if config.USING_SUCCESSOR_LIST_REPL:
            #     await self.successor_list.replicate_set_to_successors(key, value)
        else:
            set_msg = self.message_sender.create_message(MessageType.SET_VALUE, node_responsible_addr, { 'key': key, 'value' : value })
            set_msg_res = await self.keep_resending_until_response(set_msg, lambda msg: msg.has_type(MessageType.SET_VALUE_REPLY) and msg.src == node_responsible_addr)
            assert('key' in set_msg_res.args and 'value' in set_msg_res.args)
            assert(set_msg_res.args['key'] == key and set_msg_res.args['value'] == value)
        self.message_sender.create_and_send_message(MessageType.SET_RESPONSE_TO_BROKER, node_responsible_addr, {'id' : req_id, 'key': str(key), 'value' : value})