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; }
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; }