示例#1
0
文件: daemon.c 项目: plepe/mod_tile
enum protoCmd rx_request(const struct protocol *req, int fd)
{
    struct protocol *reqnew;
    struct item *list = NULL, *item;
    enum protoCmd pend;

    // Upgrade version 1 to version 2
    if (req->ver == 1) {
        reqnew = (struct protocol *)malloc(sizeof(struct protocol));
        memcpy(reqnew, req, sizeof(struct protocol_v1));
        reqnew->xmlname[0] = 0;
        req = reqnew;
    }
    else if (req->ver != 2) {
        syslog(LOG_ERR, "Bad protocol version %d", req->ver);
        return cmdIgnore;
    }

    syslog(LOG_DEBUG, "DEBUG: Got command %s fd(%d) xml(%s), z(%d), x(%d), y(%d)",
            cmdStr(req->cmd), fd, req->xmlname, req->z, req->x, req->y);

    if ((req->cmd != cmdRender) && (req->cmd != cmdRenderPrio) && (req->cmd != cmdDirty) && (req->cmd != cmdRenderBulk))
        return cmdIgnore;

    item = (struct item *)malloc(sizeof(*item));
    if (!item) {
            syslog(LOG_ERR, "malloc failed");
            return cmdNotDone;
    }

    item->req = *req;
    item->duplicates = NULL;
    item->fd = (req->cmd == cmdDirty) ? FD_INVALID : fd;

    item_load(item, req);

#ifdef METATILE
    /* Round down request co-ordinates to the neareast N (should be a power of 2)
     * Note: request path is no longer consistent but this will be recalculated
     * when the metatile is being rendered.
     */
    item->mx = item->req.x & ~(METATILE-1);
    item->my = item->req.y & ~(METATILE-1);
#else
    item->mx = item->req.x;
    item->my = item->req.y;
#endif

    pthread_mutex_lock(&qLock);

    // Check for a matching request in the current rendering or dirty queues
    pend = pending(item);
    if (pend == cmdNotDone) {
        // We found a match in the dirty queue, can not wait for it
        pthread_mutex_unlock(&qLock);
        free(item);
        return cmdNotDone;
    }
    if (pend == cmdIgnore) {
        // Found a match in render queue, item added as duplicate
        pthread_mutex_unlock(&qLock);
        return cmdIgnore;
    }

    // New request, add it to render or dirty queue
    if ((req->cmd == cmdRender) && (reqNum < REQ_LIMIT)) {
        list = &reqHead;
        item->inQueue = queueRequest;
        reqNum++;
    } else if ((req->cmd == cmdRenderPrio) && (reqPrioNum < REQ_LIMIT)) {
        list = &reqPrioHead;
        item->inQueue = queueRequestPrio;
        reqPrioNum++;
    } else if ((req->cmd == cmdRenderBulk) && (reqBulkNum < REQ_LIMIT)) {
        list = &reqBulkHead;
        item->inQueue = queueRequestBulk;
        reqBulkNum++;
    } else if (dirtyNum < DIRTY_LIMIT) {
        list = &dirtyHead;
        item->inQueue = queueDirty;
        dirtyNum++;
        item->fd = FD_INVALID; // No response after render
    } else {
        // The queue is severely backlogged. Drop request
        stats.noReqDroped++;
        pthread_mutex_unlock(&qLock);
        free(item);
        return cmdNotDone;
    }

    if (list) {
        item->next = list;
        item->prev = list->prev;
        item->prev->next = item;
        list->prev = item;
        /* In addition to the linked list, add item to a hash table index
         * for faster lookup of pending requests.
         */
        insert_item_idx(item);

        pthread_cond_signal(&qCond);
    } else
        free(item);

    pthread_mutex_unlock(&qLock);

    return (list == &reqHead)?cmdIgnore:cmdNotDone;
}
示例#2
0
enum protoCmd request_queue_add_request(struct request_queue * queue, struct item *item) {
    enum protoCmd status;
    const struct protocol *req;
    struct item *list = NULL;
    req = &(item->req);
    if (queue == NULL) {
        printf("queue os NULL");
        exit(3);
    }

    pthread_mutex_lock(&(queue->qLock));

    // Check for a matching request in the current rendering or dirty queues
    status = pending(queue, item);
    if (status == cmdNotDone) {
        // We found a match in the dirty queue, can not wait for it
        pthread_mutex_unlock(&(queue->qLock));
        free(item);
        return cmdNotDone;
    }
    if (status == cmdIgnore) {
        // Found a match in render queue, item added as duplicate
        pthread_mutex_unlock(&(queue->qLock));
        return cmdIgnore;
    }

    // New request, add it to render or dirty queue
    if ((req->cmd == cmdRender) && (queue->reqNum < REQ_LIMIT)) {
        list = &(queue->reqHead);
        item->inQueue = queueRequest;
        item->originatedQueue = queueRequest;
        queue->reqNum++;
    } else if ((req->cmd == cmdRenderPrio) && (queue->reqPrioNum < REQ_LIMIT)) {
        list = &(queue->reqPrioHead);
        item->inQueue = queueRequestPrio;
        item->originatedQueue = queueRequestPrio;
        queue->reqPrioNum++;
    } else if ((req->cmd == cmdRenderLow) && (queue->reqLowNum < REQ_LIMIT)) {
        list = &(queue->reqLowHead);
        item->inQueue = queueRequestLow;
        item->originatedQueue = queueRequestLow;
        queue->reqLowNum++;
    } else if ((req->cmd == cmdRenderBulk) && (queue->reqBulkNum < REQ_LIMIT)) {
        list = &(queue->reqBulkHead);
        item->inQueue = queueRequestBulk;
        item->originatedQueue = queueRequestBulk;
        queue->reqBulkNum++;
    } else if (queue->dirtyNum < DIRTY_LIMIT) {
        list = &(queue->dirtyHead);
        item->inQueue = queueDirty;
        item->originatedQueue = queueDirty;
        queue->dirtyNum++;
        item->fd = FD_INVALID; // No response after render
    } else {
        // The queue is severely backlogged. Drop request
        queue->stats.noReqDroped++;
        pthread_mutex_unlock(&(queue->qLock));
        free(item);
        return cmdNotDone;
    }

    if (list) {
        item->next = list;
        item->prev = list->prev;
        item->prev->next = item;
        list->prev = item;
        /* In addition to the linked list, add item to a hash table index
         * for faster lookup of pending requests.
         */
        insert_item_idx(queue, item);

        pthread_cond_signal(&queue->qCond);
    } else
        free(item);

    pthread_mutex_unlock(&queue->qLock);

    return (list == &(queue->dirtyHead))?cmdNotDone:cmdIgnore;
}