/* * dbuf_put - put a sequence of bytes in a dbuf */ int dbuf_put(struct DBuf* dyn, const char* buf, size_t length) { struct DBufBuffer** h; struct DBufBuffer* d; int chunk; /* * Locate the last non-empty buffer. If the last buffer is * full, the loop will terminate with 'd==NULL'. This loop * assumes that the 'dyn->length' field is correctly * maintained, as it should--no other check really needed. */ if (0 == dyn->length) h = &(dyn->head); else h = &(dyn->tail); /* * Append users data to buffer, allocating buffers as needed */ dyn->length += length; for ( ; length > 0; h = &(d->next)) { if (0 == (d = *h)) { if (0 == (d = dbuf_alloc())) return dbuf_malloc_error(dyn); dyn->tail = d; *h = d; /* prev->next = d */ } chunk = (d->data + DBUF_SIZE) - d->end; if (chunk) { if (chunk > length) chunk = length; memcpy(d->end, buf, chunk); length -= chunk; buf += chunk; d->end += chunk; } } return 1; }
/** Append bytes to a data buffer. * @param[in] dyn Buffer to append to. * @param[in] buf Data to append. * @param[in] length Number of bytes to append. * @return Non-zero on success, or zero on failure. */ int dbuf_put(struct DBuf *dyn, const char *buf, unsigned int length) { struct DBufBuffer** h; struct DBufBuffer* db; unsigned int chunk; assert(0 != dyn); assert(0 != buf); /* * Locate the last non-empty buffer. If the last buffer is full, * the loop will terminate with 'db==NULL'. * This loop assumes that the 'dyn->length' field is correctly * maintained, as it should--no other check really needed. */ if (!dyn->length) h = &(dyn->head); else h = &(dyn->tail); /* * Append users data to buffer, allocating buffers as needed */ dyn->length += length; for (; length > 0; h = &(db->next)) { if (0 == (db = *h)) { if (0 == (db = dbuf_alloc())) { if (feature_bool(FEAT_HAS_FERGUSON_FLUSHER)) { /* * from "Married With Children" episode were Al bought a REAL toilet * on the black market because he was tired of the wimpy water * conserving toilets they make these days --Bleep */ /* * Apparently this doesn't work, the server _has_ to * dump a few clients to handle the load. A fully loaded * server cannot handle a net break without dumping some * clients. If we flush the connections here under a full * load we may end up starving the kernel for mbufs and * crash the machine */ /* * attempt to recover from buffer starvation before * bailing this may help servers running out of memory */ flush_connections(0); db = dbuf_alloc(); } if (0 == db) return dbuf_malloc_error(dyn); } dyn->tail = db; *h = db; db->next = 0; db->start = db->end = db->data; } chunk = (db->data + DBUF_SIZE) - db->end; if (chunk) { if (chunk > length) chunk = length; memcpy(db->end, buf, chunk); length -= chunk; buf += chunk; db->end += chunk; } } return 1; }