Exemple #1
0
void free_key_node(PanDB * const db, KeyNode * const key_node)
{
    if (key_node == NULL) {
        return;
    }
    assert(key_node->slot == NULL);
    release_key(key_node->key);
    key_node->key = NULL;
    free_slip_map(&key_node->properties);
    key_node->properties = NULL;
    HttpHandlerContext * context = db->context;
    if (key_node->expirable != NULL) {
        remove_expirable_from_tree(db, key_node->expirable);        
        remove_entry_from_slab(&context->expirables_slab, key_node->expirable);
        key_node->expirable = NULL;
    }
    free(key_node);
}
int handle_op_records_put(RecordsPutOp * const put_op,
                          HttpHandlerContext * const context)
{
    yajl_gen json_gen;
    PanDB *pan_db;

    if (get_pan_db_by_layer_name(context, put_op->layer_name->val,
                                 AUTOMATICALLY_CREATE_LAYERS, &pan_db) < 0) {
        release_key(put_op->layer_name);
        release_key(put_op->key);
        free_slip_map(&put_op->properties);
        free_slip_map(&put_op->special_properties);

        return HTTP_NOTFOUND;
    }
    release_key(put_op->layer_name);

    int status;
    KeyNode *key_node;
    status = get_key_node_from_key(pan_db, put_op->key, 1, &key_node);
    release_key(put_op->key);
    if (key_node == NULL) {
        assert(status <= 0);
        free_slip_map(&put_op->properties);
        free_slip_map(&put_op->special_properties);
        return HTTP_NOTFOUND;
    }
    assert(status > 0);
    const Rectangle2D * const qbounds = &pan_db->qbounds;
    if (put_op->position_set != 0 &&
            !(put_op->position.latitude >= qbounds->edge0.latitude &&
              put_op->position.longitude >= qbounds->edge0.longitude &&
              put_op->position.latitude < qbounds->edge1.latitude &&
              put_op->position.longitude < qbounds->edge1.longitude)) {
        put_op->position_set = 0;
    }
    if (status > 0 && put_op->position_set != 0 && key_node->slot != NULL) {
#if PROJECTION
        const Position2D * const previous_position =
            &key_node->slot->real_position;
#else
        const Position2D * const previous_position =
            &key_node->slot->position;
#endif
        if (previous_position->latitude == put_op->position.latitude &&
                previous_position->longitude == put_op->position.longitude) {
            put_op->position_set = 0;
        } else {
            remove_entry_from_key_node(pan_db, key_node, 0);
            assert(key_node->slot != NULL);
            key_node->slot = NULL;
        }
    }
    if (put_op->position_set != 0) {
        Slot slot;
        Slot *new_slot;

        init_slot(&slot);
        slot = (Slot) {
#if PROJECTION
            .real_position = put_op->position,
#endif
             .position = put_op->position,
              .key_node = key_node
        };
        if (add_slot(pan_db, &slot, &new_slot) != 0) {
            RB_REMOVE(KeyNodes_, &pan_db->key_nodes, key_node);
            key_node->slot = NULL;
            free_key_node(pan_db, key_node);
            free_slip_map(&put_op->properties);
            free_slip_map(&put_op->special_properties);

            return HTTP_SERVUNAVAIL;
        }
        key_node->slot = new_slot;
        assert(new_slot != NULL);
    }
    if (put_op->special_properties != NULL) {
        RecordsPutApplySpecialPropertiesCBContext cb_context = {
            .target_map_pnt = &key_node->properties
        };
        slip_map_foreach(&put_op->special_properties,
                         records_put_apply_special_properties_cb,
                         &cb_context);
        free_slip_map(&put_op->special_properties);
    }
    if (key_node->properties == NULL) {
        key_node->properties = put_op->properties;
    } else {
        RecordsPutMergePropertiesCBContext cb_context = {
            .target_map_pnt = &key_node->properties
        };
        slip_map_foreach(&put_op->properties, records_put_merge_properties_cb,
                         &cb_context);
        free_slip_map(&put_op->properties);
    }
    Expirable *expirable = key_node->expirable;
    if (put_op->expires_at != (time_t) 0) {
        if (expirable == NULL) {
            Expirable new_expirable = {
                .ts = put_op->expires_at,
                .key_node = key_node
            };
            expirable = add_entry_to_slab(&context->expirables_slab,
                                          &new_expirable);
            key_node->expirable = expirable;
            add_expirable_to_tree(pan_db, expirable);
        } else {
            if (expirable->ts != put_op->expires_at) {
                remove_expirable_from_tree(pan_db, expirable);
                expirable->ts = put_op->expires_at;
                add_expirable_to_tree(pan_db, expirable);
            }
        }
        assert(expirable->key_node == key_node);
    } else if (expirable != NULL) {