char buf[2048];
int cc;
while ((cc = Sys::read(fd, buf, sizeof (buf)-1)) > 0) {
+ if (cc == sizeof(buf)-1)
+ logWarning("FIFO Read full: %d", cc);
buf[cc] = '\0';
char* bp = &buf[0];
do {
* Setup the unpacking work and dispatch it.
*/
TriggerMsgHeader h;
- memcpy(&h, bp, sizeof (h)); // copy to align fields
- if (&buf[cc]-bp < h.length) {
- // XXX need more data to complete msg/should not happen
+ int left = &buf[cc]-bp;
+ bool needy = false;
+ if (left < sizeof(TriggerMsgHeader))
+ {
+ needy = true;
+ } else
+ {
+ memcpy(&h, bp, sizeof (h)); // copy to align fields
+ if (left < h.length)
+ needy = true;
+ }
+ if (needy)
+ {
+ /*
+ * Handle the case where the buffer was read full. This means that
+ * we have a "partial" message at the end of buf, and the rest in
+ * the FIFO.
+ *
+ * buf[n] is NEVER read from the file, it's always 1-past. If we
+ * have reached buf[n], we know we are past the read data.
+ *
+ * We have (left) bytes of the message at the end of the buf.
+ * We move them to the front, and read as much more as we can to
+ * fill buf back up, leaving it in the same state as if this was
+ * the initial read.
+ */
+ memmove(buf, bp, left);
+ cc = Sys::read(fd, buf+left, (sizeof(buf)-1) - left) + left;
+ buf[cc] = '\0';
+ bp = &buf[0];
} else {
triggerEvent(h, bp+sizeof (h));
+ bp += h.length;
}
- bp += h.length;
} else {
/*
* Break up '\0'-separated records and strip
* works (i.e. echo appends a '\n' character).
*/
char* cp = strchr(bp, '\0');
+
+ /*
+ * Handle the case where the buffer was read full. This means that
+ * we have a "partial" message at the end of buf, and the rest in
+ * the FIFO.
+ *
+ * buf[n] is NEVER read from the file, it's always 1-past. If we
+ * have reached buf[n], we know we are past the read data.
+ *
+ * We have (cp - bp) bytes of the message at the end of the buf.
+ * We move them to the front, and read as much more as we can to
+ * fill buf back up, leaving it in the same state as if this was
+ * the initial read.
+ */
+ if (cp == &buf[sizeof(buf)-1])
+ {
+ memmove(buf, bp, cp-bp);
+ cc = Sys::read(fd, buf+(cp-bp), (sizeof(buf)-1) - (cp-bp)) + (cp-bp);
+ buf[cc] = '\0';
+ bp = &buf[0];
+ cp = strchr(bp, '\0');
+ }
+
if (cp > bp) {
if (cp[-1] == '\n') {
cp[-1] = '\0';
if (!getCmdLine(line, sizeof (line))) {
reply(221, "You could at least say goodbye.");
dologout(0);
- } else if (strcasecmp(line, "ABOR\r\n") == 0) {
+ } else if (strcasecmp(line, "ABOR\n") == 0) {
/*
* Abort the operation in progress. Two reply
* codes are sent on the control channel; one
reply(426, "Operation aborted. Data connection closed.");
reply(226, "Abort successful");
longjmp(urgcatch, 1); // XXX potential memory leak
- } else if (strcasecmp(line, "STAT\r\n") == 0) {
+ } else if (strcasecmp(line, "STAT\n") == 0) {
if (file_size != (off_t) -1)
reply(213, "Status: %lu of %lu bytes transferred",
byte_count, file_size);
if (!checkJobState(job))
emsg = "job deleted by another party";
} else {
+ /*
+ * We can only afford a certain amount of space,
+ * unfortunately, there is no "bright" way to remove jobs
+ * Ideally we'ld have an "aging" method, so the LRU job
+ * would be the one deleted...
+ */
+ if (jobs.size() > 10)
+ {
+ JobDictIter iter(jobs);
+ job = iter.value();
+ logError("Removing: %s", (const char*)job->jobid);
+ jobs.remove(job->jobid);
+ delete job;
+ }
+
job = findJobOnDisk(jobid, emsg);
if (job)
jobs[job->jobid] = job;