Ejemplo n.º 1
0
/*
 * 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;
}
Ejemplo n.º 2
0
/** 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;
}