Logo Search packages:      
Sourcecode: dcc version File versions  Download package

flod.c

/* Distributed Checksum Clearinghouse
 *
 * open, create, and check DCC server output flood mapped file
 *
 * Copyright (c) 2005 by Rhyolite Software
 *
 * Permission to use, copy, modify, and distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND RHYOLITE SOFTWARE DISCLAIMS ALL
 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL RHYOLITE SOFTWARE
 * BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES
 * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
 * WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
 * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
 * SOFTWARE.
 *
 * Rhyolite Software DCC 1.2.74-1.34 $Revision$
 */

#include "srvr_defs.h"

FLOD_MMAPS *flod_mmaps;

static int mmap_fd = -1;


u_char
flod_sync(DCC_EMSG emsg)
{
      u_char result = 1;

      if (flod_mmaps
          && 0 > MSYNC(flod_mmaps, sizeof(*flod_mmaps), MS_SYNC)) {
            dcc_pemsg(EX_IOERR, emsg, "msync(%s): %s",
                    FLOD_MMAP_PATH(grey_on), ERROR_STR());
            result = 0;
            emsg = 0;
      }

      if (mmap_fd >= 0
          && 0 > fsync(mmap_fd)) {
            dcc_pemsg(EX_IOERR, emsg, "fsync(%s): %s",
                    FLOD_MMAP_PATH(grey_on), ERROR_STR());
            result = 0;
            emsg = 0;
      }

      return result;
}



u_char                              /* 1=no problems, 0=complaints */
flod_unmap(DCC_EMSG emsg, const DCCD_STATS *dccd_stats)
{
      u_char result = 1;

      if (!flod_sync(emsg)) {
            result = 0;
            emsg = 0;
      }

      if (flod_mmaps) {
            if (dccd_stats)
                  memcpy(&flod_mmaps->dccd_stats, dccd_stats,
                         sizeof(flod_mmaps->dccd_stats));
            if (0 > munmap((void *)flod_mmaps, sizeof(*flod_mmaps))) {
                  dcc_pemsg(EX_IOERR, emsg, "munmap(%s,%d): %s",
                          FLOD_MMAP_PATH(grey_on),
                          ISZ(*flod_mmaps), ERROR_STR());
                  result = 0;
                  emsg = 0;
            }
            flod_mmaps = 0;
      }

      if (mmap_fd >= 0) {
            if (close(mmap_fd) < 0) {
                  dcc_pemsg(EX_IOERR, emsg, "close(%s): %s",
                          FLOD_MMAP_PATH(grey_on), ERROR_STR());
                  result = 0;
                  emsg = 0;
            }
            mmap_fd = -1;
      }

      return result;
}



static int                    /* 1=success, 0=retry, -1=fatal */
flod_mmap_try(DCC_EMSG emsg,
            const DB_SN sn,
            u_char rw)        /* 0=rdonly/unlocked, 1=write/locked */
{
      int flags;
      struct stat sb;
      FLOD_MMAPS init;
      FLOD_MMAP *mp;
      const char *nm;
      void *p;
      int i;

      nm = FLOD_MMAP_PATH(grey_on);

      if (rw)
            mmap_fd = dcc_lock_open(emsg, nm, O_RDWR|O_CREAT,
                              DCC_LOCK_OPEN_NOWAIT,
                              DCC_LOCK_ALL_FILE, 0);
      else
            mmap_fd = dcc_lock_open(emsg, nm, O_RDONLY,
                              DCC_LOCK_OPEN_EXT, 0, 0);
      if (mmap_fd == -1)
            return (errno == EWOULDBLOCK) ? -1 : 0;

      if (fstat(mmap_fd, &sb) < 0) {
            dcc_pemsg(EX_IOERR, emsg, "stat(%s): %s",
                    nm, ERROR_STR());
            flod_unmap(0, 0);
            return 0;
      }
      if (0 > fcntl(mmap_fd, F_SETFD, FD_CLOEXEC)) {
            dcc_pemsg(EX_IOERR, emsg, "fcntl(%s, FD_CLOEXEC): %s",
                    nm, ERROR_STR());
            flod_unmap(0, 0);
            return 0;
      }

      if (sb.st_size == 0 && rw) {
            memset(&init, 0, sizeof(init));
            strcpy(init.magic, FLOD_MMAP_MAGIC);
            if (sn)
                  memcpy(&init.sn, sn, sizeof(init.sn));
            for (mp = init.mmaps; mp <= LAST(init.mmaps); ++mp)
                  mp->su.sa.sa_family = AF_UNSPEC;
            i = write(mmap_fd, &init, sizeof(init));
            if (i < 0) {
                  dcc_pemsg(EX_IOERR, emsg, "write(%s, init): %s",
                          nm, ERROR_STR());
                  return -1;
            } else if (i != sizeof(init)) {
                  dcc_pemsg(EX_IOERR, emsg,
                          "write(%s, init)=%d instead of %d",
                          nm, i, ISZ(init));
                  flod_unmap(0, 0);
                  return -1;
            }
      }

      flags = rw ? (PROT_READ|PROT_WRITE) : PROT_READ;
      p = mmap(0, sizeof(*flod_mmaps), flags, MAP_SHARED, mmap_fd, 0);
      if (p == MAP_FAILED) {
            dcc_pemsg(EX_IOERR, emsg, "mmap(%s): %s",
                    nm, ERROR_STR());
            flod_unmap(0, 0);
            return 0;
      }
      flod_mmaps = p;

      if (sb.st_size >= (off_t)sizeof(flod_mmaps->magic)
          && strcmp(flod_mmaps->magic, FLOD_MMAP_MAGIC)) {
            dcc_pemsg(EX_IOERR, emsg, "wrong magic in %s;"
                    " \"%s\" instead of \"%s\"",
                    nm, flod_mmaps->magic, FLOD_MMAP_MAGIC);
            flod_unmap(0, 0);
            return 0;
      }
      if (sb.st_size == 0) {
            dcc_pemsg(EX_IOERR, emsg, "%s (re)created", nm);
      } else if (sb.st_size != sizeof(FLOD_MMAPS)) {
            dcc_pemsg(EX_IOERR, emsg, "%s has size %d instead of %d",
                    nm, (int)sb.st_size, ISZ(FLOD_MMAPS));
            flod_unmap(0, 0);
            return 0;
      }

      if (sn
          && memcmp(flod_mmaps->sn, sn, sizeof(flod_mmaps->sn))) {
            char sn1_buf[30], sn2_buf[32];
            dcc_pemsg(EX_IOERR, emsg, "s/n %s instead of %s in %s",
                    dcc_ts2str(sn1_buf, sizeof(sn1_buf), flod_mmaps->sn),
                    dcc_ts2str(sn2_buf, sizeof(sn2_buf), sn),
                    nm);
            flod_unmap(0, 0);
            return 0;
      }

      return 1;
}



u_char                              /* 0=failed, 1=mapped */
flod_mmap(DCC_EMSG emsg,
        const DB_SN sn,
        const DCCD_STATS *dccd_stats,
        u_char rw,                  /* 0=rdonly/unlocked, 1=write/locked */
        u_char trace)
{
      int i;

      if (!flod_unmap(emsg, dccd_stats) && emsg) {
            if (trace)
                  dcc_trace_msg("%s", emsg);
            *emsg = '\0';
      }

      /* try to open the existing file */
      i = flod_mmap_try(emsg, sn, rw);

      if (i != 0 || !rw)
            return i > 0;

      /* delete and recreate it if it is broken */
      if (emsg && *emsg != '\0') {
            if (trace)
                  dcc_trace_msg("%s", emsg);
            *emsg = '\0';
      }
      if (0 > unlink(FLOD_MMAP_PATH(grey_on))
          && errno != ENOENT) {
            dcc_pemsg(EX_IOERR, emsg, "unlink(%s): %s",
                    FLOD_MMAP_PATH(grey_on), ERROR_STR());
            flod_unmap(0, 0);
            return 0;
      }
      flod_unmap(0, 0);

      /* try to recreate the file */
      if (flod_mmap_try(emsg, sn, rw) > 0) {
            if (emsg) {
                  if (trace)
                        dcc_trace_msg("%s", emsg);
                  *emsg = '\0';
            }
            return 1;
      }

      flod_unmap(0, 0);
      return 0;
}



char *
flod_stats_printf(char *buf, u_int buf_len,
              int st,         /* 0=off, 1=restarting, 2=on */
              int oflods_total,
              int oflods_active,
              int iflods_active)
{
      snprintf(buf, buf_len,
             "flood %s %3d streams %3d out active %d in",
             st == 0 ? "off" : st == 1 ? "restarting" : "on",
             oflods_total, oflods_active, iflods_active);
      return buf;
}



/* this function lets clients such as dbclean know when flooding is quiet */
int                           /* -1=sick, 0=off, 1=not off */
flod_running(const char *st)
{
      char off_buf[11];
      int out, active, in;

      if (4 != sscanf(st, "flood %10s %d streams %d out active %d in",
                  off_buf, &out, &active, &in))
            return 1;

      if (strcmp(off_buf, "off"))
            return 1;
      return active != 0 || in != 0;
}

Generated by  Doxygen 1.6.0   Back to index