static inline gboolean
_has_movable_message(LogQueueDiskNonReliable *self)
{
  return self->qoverflow->length > 0
         && ((HAS_SPACE_IN_QUEUE(self->qout) && qdisk_get_length (self->super.qdisk) == 0)
             || qdisk_is_space_avail (self->super.qdisk, 4096));
}
Example #2
0
static gboolean
_write_message(LogQueueDisk *self, LogMessage *msg)
{
  GString *serialized;
  SerializeArchive *sa;
  gboolean consumed = FALSE;
  if (qdisk_initialized(self->qdisk) && qdisk_is_space_avail(self->qdisk, 64))
    {
      serialized = g_string_sized_new(64);
      sa = serialize_string_archive_new(serialized);
      log_msg_serialize(msg, sa);
      consumed = qdisk_push_tail(self->qdisk, serialized);
      serialize_archive_free(sa);
      g_string_free(serialized, TRUE);
    }
  return consumed;
}
Example #3
0
gboolean
qdisk_push_tail(QDisk *self, GString *record)
{
  guint32 n = GUINT32_TO_BE(record->len);

  /* write follows read (e.g. we are appending to the file) OR
   * there's enough space between write and read.
   *
   * If write follows read we need to check two things:
   *   - either we are below the maximum limit (GINT64_FROM_BE(self->hdr->write_head) < self->options->disk_buf_size)
   *   - or we can wrap around (GINT64_FROM_BE(self->hdr->read_head) != QDISK_RESERVED_SPACE)
   * If neither of the above is true, the buffer is full.
   */
  if (!qdisk_is_space_avail(self, record->len))
    return FALSE;

  if (n == 0)
    {
      msg_error("Error writing empty message into the disk-queue file");
      return FALSE;
    }

  if (!pwrite_strict(self->fd, (gchar *) &n, sizeof(n), self->hdr->write_head) ||
      !pwrite_strict(self->fd, record->str, record->len, self->hdr->write_head + sizeof(n)))
    {
      msg_error("Error writing disk-queue file",
          evt_tag_errno("error", errno));
      return FALSE;
    }

  self->hdr->write_head = self->hdr->write_head + record->len + sizeof(n);


  /* NOTE: we only wrap around if the read head is before the write,
   * otherwise we'd truncate the data the read head is still processing, e.g.
   *
   * start                limit       file size
   *   |                     |           |
   *       ^ read         ^write
   *
   * We can truncate in the scenario above, once we surpass the limit,
   * however if this is the case:
   *
   * start                limit       file size
   *   |                     |           |
   *                      ^write    ^read
   *
   * In this case cannot wrap around, even if the limit is surpassed, as
   * in that case data still unprocessed by the read head would be lost.
   * This can happen if the size of the queue file got decreased while
   * it still had more data.
   * */

  /* NOTE: if these were equal, that'd mean the queue is empty, so we spoiled something */
  g_assert(self->hdr->write_head != self->hdr->backlog_head);

  if (self->hdr->write_head > MAX(self->hdr->backlog_head,self->hdr->read_head))
    {
      if (self->file_size > self->hdr->write_head)
        {
          _truncate_file(self, self->hdr->write_head);
        }
      self->file_size = self->hdr->write_head;

      if (self->hdr->write_head > self->options->disk_buf_size && self->hdr->backlog_head  != QDISK_RESERVED_SPACE)
        {
          /* we were appending to the file, we are over the limit, and space
           * is available before the read head. truncate and wrap.
           *
           * Otherwise we let the write_head over size limits for a bit and
           * for the next message, the condition at the beginning of this
           * function will cause the push to fail */
          self->hdr->write_head = QDISK_RESERVED_SPACE;
        }
    }
  self->hdr->length++;
  return TRUE;
}