Exemplo n.º 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);
}
Exemplo n.º 2
0
static int records_put_apply_special_properties_cb(void * const context_,
        const void * const key,
        const size_t key_len,
        const void * const value,
        const size_t value_len)
{
    RecordsPutApplySpecialPropertiesCBContext * const context = context_;

    assert(key_len > (size_t) 0U);
    assert(* (const char *) key == INT_PROPERTY_COMMON_PREFIX);

    if (key_len >= sizeof INT_PROPERTY_DELETE_PREFIX &&
            strncasecmp(key, INT_PROPERTY_DELETE_PREFIX,
                        sizeof INT_PROPERTY_DELETE_PREFIX - (size_t) 1U) == 0) {
        if (value_len <= (size_t) 0U || * (const char *) value == 0 ||
                context->target_map_pnt == NULL ||
                *context->target_map_pnt == NULL) {
            return 0;
        }
        remove_entry_from_slip_map
        (context->target_map_pnt,
         (void *)
         ((const unsigned char *) key +
          (sizeof INT_PROPERTY_DELETE_PREFIX - (size_t) 1U)),
         key_len - (sizeof INT_PROPERTY_DELETE_PREFIX - (size_t) 1U));
        return 0;
    }
    if (key_len == sizeof INT_PROPERTY_DELETE_ALL_PREFIX - (size_t) 1U &&
            strncasecmp(key, INT_PROPERTY_DELETE_ALL_PREFIX,
                        sizeof INT_PROPERTY_DELETE_ALL_PREFIX - (size_t) 1U) == 0) {
        if (value_len <= (size_t) 0U || * (const char *) value == 0 ||
                context->target_map_pnt == NULL ||
                *context->target_map_pnt == NULL) {
            return 0;
        }
        free_slip_map(context->target_map_pnt);
        assert(*context->target_map_pnt == NULL);

        return 0;
    }

    if (key_len >= sizeof INT_PROPERTY_ADD_INT_PREFIX &&
            strncasecmp(key, INT_PROPERTY_ADD_INT_PREFIX,
                        sizeof INT_PROPERTY_ADD_INT_PREFIX - (size_t) 1U) == 0) {
        if (value_len <= (size_t) 0U || * (const char *) value == 0 ||
                value_len >= sizeof "-170141183460469231731687303715884105728") {
            return 0;
        }
        const void *num_value_s = NULL;
        size_t num_value_len;
        if (find_in_slip_map
                (context->target_map_pnt,
                 (void *) ((const unsigned char *) key +
                           (sizeof INT_PROPERTY_ADD_INT_PREFIX - (size_t) 1U)),
                 key_len - (sizeof INT_PROPERTY_ADD_INT_PREFIX - (size_t) 1U),
                 &num_value_s, &num_value_len) == 0) {
            num_value_s = "0";
            num_value_len = sizeof "0" - (size_t) 1U;
        }
        if (num_value_len >=
                sizeof "-170141183460469231731687303715884105728") {
            return 0;
        }
        intmax_t num_value;
        char buf[num_value_len  + (size_t) 1U];
        memcpy(buf, num_value_s, num_value_len);
        buf[num_value_len] = 0;
        num_value = strtoimax(buf, NULL, 10);

        intmax_t inum_value;
        char ibuf[value_len  + (size_t) 1U];
        memcpy(ibuf, value, value_len);
        ibuf[value_len] = 0;
        inum_value = strtoimax(ibuf, NULL, 10);

        num_value += inum_value;

        char buf_s[sizeof "170141183460469231731687303715884105728"];
        snprintf(buf_s, sizeof buf_s, "%" PRIdMAX, num_value);
        if (*context->target_map_pnt == NULL) {
            *context->target_map_pnt = new_slip_map
                                       (PROPERTIES_DEFAULT_SLIP_MAP_BUFFER_SIZE);
            if (*context->target_map_pnt == NULL) {
                return -1;
            }
        }
        replace_entry_in_slip_map
        (context->target_map_pnt,
         (void *) ((const unsigned char *) key +
                   (sizeof INT_PROPERTY_ADD_INT_PREFIX - (size_t) 1U)),
         key_len - (sizeof INT_PROPERTY_ADD_INT_PREFIX - (size_t) 1U),
         buf_s, strlen(buf_s));

        return 0;
    }

    return 0;
}
Exemplo n.º 3
0
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) {
Exemplo n.º 4
0
int handle_domain_records(struct evhttp_request * const req,
                          HttpHandlerContext * const context,
                          char *uri, char *opts, _Bool * const write_to_log,
                          const _Bool fake_req)
{
    Key *layer_name;
    Key *key;

    (void) opts;
    if (req->type == EVHTTP_REQ_GET) {
        Op op;
        RecordsGetOp * const get_op = &op.records_get_op;
        char *sep;

        if ((sep = strchr(uri, '/')) == NULL) {
            return HTTP_NOTFOUND;
        }
        *sep = 0;
        if ((layer_name = new_key_from_c_string(uri)) == NULL) {
            *sep = '/';
            return HTTP_SERVUNAVAIL;
        }
        *sep++ = '/';
        if (*sep == 0) {
            release_key(layer_name);
            return HTTP_NOTFOUND;
        }
        if ((key = new_key_from_c_string(sep)) == NULL) {
            release_key(layer_name);
            return HTTP_SERVUNAVAIL;
        }
        RecordsOptParseCBContext cb_context = {
            .with_links = 0
        };
        if (opts != NULL &&
                query_parse(opts, records_opt_parse_cb, &cb_context) != 0) {
            release_key(layer_name);
            return HTTP_BADREQUEST;
        }
        *get_op = (RecordsGetOp) {
            .type = OP_TYPE_RECORDS_GET,
             .req = req,
              .fake_req = fake_req,
               .op_tid = ++context->op_tid,
                .layer_name = layer_name,
                 .key = key,
                  .with_links = cb_context.with_links
        };
        pthread_mutex_lock(&context->mtx_cqueue);
        if (push_cqueue(context->cqueue, get_op) != 0) {
            pthread_mutex_unlock(&context->mtx_cqueue);
            release_key(layer_name);
            release_key(key);

            return HTTP_SERVUNAVAIL;
        }
        pthread_mutex_unlock(&context->mtx_cqueue);
        pthread_cond_signal(&context->cond_cqueue);

        return 0;
    }

    if (req->type == EVHTTP_REQ_PUT) {
        Op op;
        RecordsPutOp * const put_op = &op.records_put_op;
        char *sep;

        if ((sep = strchr(uri, '/')) == NULL) {
            return HTTP_NOTFOUND;
        }
        *sep = 0;
        if ((layer_name = new_key_from_c_string(uri)) == NULL) {
            return HTTP_SERVUNAVAIL;
        }
        *sep++ = '/';
        if (*sep == 0) {
            release_key(layer_name);
            return HTTP_NOTFOUND;
        }
        if ((key = new_key_from_c_string(sep)) == NULL) {
            release_key(layer_name);
            return HTTP_SERVUNAVAIL;
        }
        evbuffer_add(evhttp_request_get_input_buffer(req), "", (size_t) 1U);
        const char *body =
            (char *) evbuffer_pullup(evhttp_request_get_input_buffer(req), -1);

        *put_op = (RecordsPutOp) {
            .type = OP_TYPE_RECORDS_PUT,
             .req = req,
              .fake_req = fake_req,
               .op_tid = ++context->op_tid,
                .layer_name = layer_name,
                 .key = key,
            .position = {
                .latitude  = (Dimension) -1,
                .longitude = (Dimension) -1
            },
            .position_set = 0,
             .properties = NULL,
              .special_properties = NULL,
               .expires_at = (time_t) 0
        };
        RecordsPutOptParseCBContext cb_context = {
            .put_op = put_op
        };
        if (query_parse(body, records_put_opt_parse_cb, &cb_context) != 0) {
            free_slip_map(&put_op->properties);
            free_slip_map(&put_op->special_properties);
            release_key(layer_name);
            release_key(key);
            return HTTP_BADREQUEST;
        }
        pthread_mutex_lock(&context->mtx_cqueue);
        if (push_cqueue(context->cqueue, put_op) != 0) {
            pthread_mutex_unlock(&context->mtx_cqueue);
            free_slip_map(&put_op->properties);
            free_slip_map(&put_op->special_properties);
            release_key(layer_name);
            release_key(key);

            return HTTP_SERVUNAVAIL;
        }
        pthread_mutex_unlock(&context->mtx_cqueue);
        pthread_cond_signal(&context->cond_cqueue);
        *write_to_log = 1;

        return 0;
    }

    if (req->type == EVHTTP_REQ_DELETE) {
        Op op;
        RecordsDeleteOp * const delete_op = &op.records_delete_op;
        char *sep;
        if ((sep = strchr(uri, '/')) == NULL) {
            return HTTP_NOTFOUND;
        }
        *sep = 0;
        if ((layer_name = new_key_from_c_string(uri)) == NULL) {
            return HTTP_SERVUNAVAIL;
        }
        *sep++ = '/';
        if (*sep == 0) {
            release_key(layer_name);
            return HTTP_NOTFOUND;
        }
        if ((key = new_key_from_c_string(sep)) == NULL) {
            release_key(layer_name);
            return HTTP_SERVUNAVAIL;
        }
        *delete_op = (RecordsDeleteOp) {
            .type = OP_TYPE_RECORDS_DELETE,
             .req = req,
              .fake_req = fake_req,
               .op_tid = ++context->op_tid,
                .layer_name = layer_name,
                 .key = key
        };
        pthread_mutex_lock(&context->mtx_cqueue);
        if (push_cqueue(context->cqueue, delete_op) != 0) {
            pthread_mutex_unlock(&context->mtx_cqueue);
            release_key(layer_name);
            release_key(key);

            return HTTP_SERVUNAVAIL;
        }
        pthread_mutex_unlock(&context->mtx_cqueue);
        pthread_cond_signal(&context->cond_cqueue);
        *write_to_log = 1;

        return 0;
    }
    return HTTP_NOTFOUND;
}