* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * $Id$
*/
-
#include "dbuf.h"
-#include "common.h"
-#include "sys.h"
+#include "ircd_alloc.h"
+#include "ircd_chattr.h"
+#include "ircd_features.h"
+#include "send.h"
+#include "sys.h" /* MIN */
#include <assert.h>
#include <string.h>
-RCSTAG_CC("$Id$");
-
/*
* dbuf is a collection of functions which can be used to
* maintain a dynamic buffering of a byte stream.
#define DBUF_SIZE 2048
struct DBufBuffer {
- struct DBufBuffer *next; /* Next data buffer, NULL if last */
- char *start; /* data starts here */
- char *end; /* data ends here */
- char data[DBUF_SIZE]; /* Actual data stored here */
+ struct DBufBuffer *next; /* Next data buffer, NULL if last */
+ char *start; /* data starts here */
+ char *end; /* data ends here */
+ char data[DBUF_SIZE]; /* Actual data stored here */
};
void dbuf_count_memory(size_t *allocated, size_t *used)
*/
static struct DBufBuffer *dbuf_alloc(void)
{
- struct DBufBuffer *db = dbufFreeList;
+ struct DBufBuffer* db = dbufFreeList;
- if (db)
- {
- ++DBufUsedCount;
+ if (db) {
dbufFreeList = db->next;
+ ++DBufUsedCount;
}
- else if (DBufAllocCount * DBUF_SIZE < BUFFERPOOL)
- {
- if ((db = (struct DBufBuffer *)RunMalloc(sizeof(struct DBufBuffer))))
- {
- ++DBufAllocCount;
- ++DBufUsedCount;
- }
+ else if (DBufAllocCount * DBUF_SIZE < feature_int(FEAT_BUFFERPOOL)) {
+ db = (struct DBufBuffer*) MyMalloc(sizeof(struct DBufBuffer));
+ assert(0 != db);
+ ++DBufAllocCount;
+ ++DBufUsedCount;
}
return db;
}
* buf: Pointer to data to be stored
* length: Number of bytes to store
*/
-int dbuf_put(struct DBuf *dyn, const char *buf, size_t length)
+int dbuf_put(struct DBuf *dyn, const char *buf, unsigned int length)
{
- struct DBufBuffer **h;
- struct DBufBuffer *db;
- size_t chunk;
+ struct DBufBuffer** h;
+ struct DBufBuffer* db;
+ unsigned int chunk;
assert(0 != dyn);
assert(0 != buf);
*/
dyn->length += length;
- for (; length > 0; h = &(db->next))
- {
- if (0 == (db = *h))
- {
- if (0 == (db = dbuf_alloc()))
- return dbuf_malloc_error(dyn);
-
+ 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) {
if (chunk > length)
- chunk = length;
+ chunk = length;
memcpy(db->end, buf, chunk);
* dyn: Dynamic buffer header
* length: Return number of bytes accessible
*/
-const char *dbuf_map(const struct DBuf *dyn, size_t *length)
+const char *dbuf_map(const struct DBuf* dyn, unsigned int* length)
{
assert(0 != dyn);
assert(0 != length);
* dyn: Dynamic buffer header
* length: Number of bytes to delete
*/
-void dbuf_delete(struct DBuf *dyn, size_t length)
+void dbuf_delete(struct DBuf *dyn, unsigned int length)
{
struct DBufBuffer *db;
- size_t chunk;
+ unsigned int chunk;
if (length > dyn->length)
length = dyn->length;
* buf: Pointer to buffer to receive the data
* length: Max amount of bytes that can be received
*/
-size_t dbuf_get(struct DBuf *dyn, char *buf, size_t length)
+unsigned int dbuf_get(struct DBuf *dyn, char *buf, unsigned int length)
{
- size_t moved = 0;
- size_t chunk;
+ unsigned int moved = 0;
+ unsigned int chunk;
const char *b;
assert(0 != dyn);
return moved;
}
-static size_t dbuf_flush(struct DBuf *dyn)
+static unsigned int dbuf_flush(struct DBuf *dyn)
{
struct DBufBuffer *db = dyn->head;
/*
* flush extra line terms
*/
- while (isEol(*db->start))
+ while (IsEol(*db->start))
{
if (++db->start == db->end)
{
dbuf_free(db);
if (0 == (db = dyn->head))
{
- dyn->tail = 0;
- dyn->length = 0;
- break;
+ dyn->tail = 0;
+ dyn->length = 0;
+ break;
}
}
--dyn->length;
* possible (determined by length) into buf and return the amount copied
* else return 0.
*/
-size_t dbuf_getmsg(struct DBuf *dyn, char *buf, size_t length)
+unsigned int dbuf_getmsg(struct DBuf *dyn, char *buf, unsigned int length)
{
struct DBufBuffer *db;
char *start;
char *end;
- size_t count;
- size_t copied = 0;
+ unsigned int count;
+ unsigned int copied = 0;
assert(0 != dyn);
assert(0 != buf);
*/
while (length > 0)
{
- end = MIN(db->end, (start + length));
- while (start < end && !isEol(*start))
+ end = IRCD_MIN(db->end, (start + length));
+ while (start < end && !IsEol(*start))
*buf++ = *start++;
count = start - db->start;