/* Run the queue service routines until there is no more work to be done. If flags & HTTP_BLOCK, this routine may block while yielding. Return true if actual work was done. */ PUBLIC bool httpServiceQueues(HttpConn *conn, int flags) { HttpQueue *q; bool workDone; workDone = 0; while (conn->state < HTTP_STATE_COMPLETE && (q = httpGetNextQueueForService(conn->serviceq)) != NULL) { if (q->servicing) { /* Called re-entrantly */ q->flags |= HTTP_QUEUE_RESERVICE; } else { assert(q->schedulePrev == q->scheduleNext); httpServiceQueue(q); workDone = 1; } if (mprNeedYield() && (flags & HTTP_BLOCK)) { mprYield(0); } } /* Always do a yield if requested even if there are no queues to service */ if (mprNeedYield() && (flags & HTTP_BLOCK)) { mprYield(0); } return workDone; }
/* Prepare a data packet for sending downstream. This involves reading file data into a suitably sized packet. Return the 1 if the packet was sent entirely, return zero if the packet could not be completely sent. Return a negative error code for write errors. This may split the packet if it exceeds the downstreams maximum packet size. */ static int prepPacket(HttpQueue *q, HttpPacket *packet) { HttpQueue *nextQ; ssize size, nbytes; if (mprNeedYield()) { httpScheduleQueue(q); return 0; } nextQ = q->nextQ; if (packet->esize > nextQ->packetSize) { httpPutBackPacket(q, httpSplitPacket(packet, nextQ->packetSize)); size = nextQ->packetSize; } else { size = (ssize) packet->esize; } if ((size + nextQ->count) > nextQ->max) { /* The downstream queue is full, so disable the queue and service downstream queue. Will re-enable via a writable event on the connection. */ httpSuspendQueue(q); if (!(nextQ->flags & HTTP_QUEUE_SUSPENDED)) { httpScheduleQueue(nextQ); } return 0; } if ((nbytes = readFileData(q, packet, q->ioPos, size)) != size) { return MPR_ERR_CANT_READ; } q->ioPos += nbytes; return 1; }