/* $Id: phase4.pc 3956 2010-01-05 20:56:56Z zacheiss $
 *
 * (c) Copyright 1988-1998 by the Massachusetts Institute of Technology.
 * For copying and distribution information, please see the file
 * <mit-copyright.h>.
 */

#include <mit-copyright.h>
#include <moira.h>
#include "dbck.h"

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

EXEC SQL INCLUDE sqlca;

RCSID("$HeadURL: svn+ssh://svn.mit.edu/moira/trunk/moira/dbck/phase4.pc $ $Id: phase4.pc 3956 2010-01-05 20:56:56Z zacheiss $");

EXEC SQL WHENEVER SQLERROR DO dbmserr();

void count_boxes(int id, void *user, void *boxes);
void check_box_counts(int id, void *cnt, void *counts);
void check_nfs_counts(int id, void *nfsphys, void *hint);

void count_boxes(int id, void *user, void *boxes)
{
  struct user *u = user;
  int i;

  if (u->potype == 'P')
    {
      if ((i = (int)(long) hash_lookup(boxes, u->pobox_id)))
	{
	  if (hash_store(boxes, u->pobox_id, (void *)(long)(i + 1)) == -1)
	    out_of_mem("storing poboxes in hash table");
	}
      else
	{
	  printf("User %s(%s) has pobox on non-POP server %d\n",
		 u->fullname, u->login, u->pobox_id);
	  printf("Not fixing this error\n");
	}
    }
}


void check_box_counts(int id, void *cnt, void *counts)
{
  EXEC SQL BEGIN DECLARE SECTION;
  int oldval, rowcount, iid = id, icnt = (int)(long)cnt;
  EXEC SQL END DECLARE SECTION;

  oldval = (int)(long) hash_lookup(counts, id);
  icnt--;
  if (oldval != icnt)
    {
      printf("Count wrong on POBox machine %s; is %d in db, counted %d\n",
	     ((struct machine *) hash_lookup(machines, id))->name,
	     oldval, icnt);
      if (single_fix("Update", 1))
	{
	  EXEC SQL UPDATE serverhosts SET value1 = :icnt
	    WHERE service = 'POP' AND mach_id = :iid;
	  rowcount = sqlca.sqlerrd[2];
	  if (rowcount > 0)
	    printf("%d entr%s fixed\n", rowcount, rowcount == 1 ? "y" : "ies");
	  else
	    printf("Not fixed\n");
	  modified("serverhosts");
	}
    }
}


void check_nfs_counts(int id, void *nfsphys, void *hint)
{
  struct nfsphys *n = nfsphys;
  EXEC SQL BEGIN DECLARE SECTION;
  int iid = id, rowcount;
  unsigned long long val;
  char valstr[40] = {0};
  EXEC SQL END DECLARE SECTION;

  val = n->count;
  if (n->allocated != val)
    {
      printf("Count wrong on NFSphys %s:%s; is %lld in db, counted %lld\n",
	     ((struct machine *) hash_lookup(machines, n->mach_id))->name,
	     n->dir, n->allocated, val);
      if (single_fix("Update", 1))
	{
	  sprintf(valstr, "%lld", val);
	  EXEC SQL UPDATE nfsphys SET allocated = TO_NUMBER(:valstr)
	    WHERE nfsphys_id = :iid;
	  rowcount = sqlca.sqlerrd[2];
	  if (rowcount > 0)
	    printf("%d entr%s fixed\n", rowcount, rowcount == 1 ? "y" : "ies");
	  else
	    printf("Not fixed\n");
	  modified("nfsphys");
	}
    }
}


void phase4(void)
{
  struct hash *boxes, *counts;
  int id, cnt;

  printf("Phase 4 - Checking counts\n");

  dprintf("Doing POBoxes...\n");
  boxes = create_hash(10);
  counts = create_hash(10);
  EXEC SQL DECLARE csr401 CURSOR FOR
    SELECT mach_id, value1 FROM serverhosts
    WHERE service = 'POP';
  EXEC SQL OPEN csr401;
  while (1)
    {
      EXEC SQL FETCH csr401 INTO :id, :cnt;
      if (sqlca.sqlcode)
	break;

      if (hash_store(boxes, id, (void *)1) == -1)
	out_of_mem("storing poboxes");
      if (hash_store(counts, id, (void *)(long)cnt) == -1)
	out_of_mem("storing pobox counts in hash table");
    }
  EXEC SQL CLOSE csr401;
  hash_step(users, count_boxes, boxes);
  hash_step(boxes, check_box_counts, counts);

  dprintf("Doing NFSphys...\n");
  hash_step(nfsphys, check_nfs_counts, 0);
}
