/*
**  $Id: util.c,v 1.2 2001/02/16 16:28:41 remlali Exp $
**
**  GXSNMP -- An snmp management application
**  Copyright (c) 1998 Gregory McLean
**
**  This program is free software; you can redistribute it and/or modify
**  it under the terms of the GNU General Public License as published by
**  the Free Software Foundation; either version 2 of the License, or
**  (at your option) any later version.
**
**  This program is distributed in the hope that it will be useful,
**  but WITHOUT ANY WARRANTY; without even the implied warranty of
**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
**  GNU General Public License for more details.
**
**  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.,  59 Temple Place - Suite 330, Cambridge, MA 02139, USA.
*/

/*
**  util.c contains utility functions related to the creation and destruction
**  of DB_host items, and functions used to manage the DB_host database.
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <stdio.h>
#include <glib.h>

#include "dbapi.h"
#include "gxsnmp/gxsnmp_dbapi.h"

#include "debug.h"

/******************************************************************************
 *
 *  Function to load the graph table into storage.
 *
 *  Before calling graph_load, you must be sure that you have previously
 *  loaded the map, the host, and the network tables.
 *
 *  In order to detect bad database records, things are done in as
 *  conservative a manner as possible.
 *
 *  First, we check and see that the rowids that are supposed to be there
 *  are actually there, and that the rowid fields that are supposed to be
 *  zero are actually zero.
 *
 *  Then we lookup all of the rowids.
 *
 *  Finally, we add the new record to the GList data structures.
 *
 *  The return value from graph_load is a glist of all defective records.
 *  or NULL if no records were defective.
 *
 *****************************************************************************/
GList *
graph_load ()
{
  GList         * gl;
  DB_graph      * dbg;
  DB_map        * dbm;
  DB_host       * dbh;
  DB_network    * dbn;
  GList         * bad_records = NULL;
  D_FUNC_START;

/* Register all graph classes by calling gtk_type_class()
 * for all of them
 */

fprintf(stderr,"loading graph table\n");
  g_sqldb_table_load (graph_sqldb);

  if (!graph_sqldb)
    {
      g_warning ("graph_load: Failed to load the graph table.");
      return NULL;
    }
  gl = g_sqldb_table_list (graph_sqldb);
  while (gl)
    {
      dbh = NULL;
      dbm = NULL;
      dbn = NULL;
      dbg = (DB_graph *) gl->data;

      if (dbg->type != DB_GRAPH_HOST &&
          dbg->type != DB_GRAPH_NETWORK &&
          dbg->type != DB_GRAPH_WIRE)
        {
          g_print ("graph_load: entry with rowid %d is bad -- "
                   "unknown type %d\n", dbg->rowid, dbg->type);
          goto failed;
        }
         
      if (!dbg->map)
        {
          g_print ("graph_load: entry with rowid %d is bad -- "
                   "map rowid is zero\n", dbg->rowid);
          goto failed;
        }
         
      if (dbg->type == DB_GRAPH_HOST || dbg->type == DB_GRAPH_WIRE)
      if (dbg->type == DB_GRAPH_HOST || dbg->type == DB_GRAPH_WIRE)
        if (!dbg->host)
          {
            g_print ("graph_load: entry with rowid %d is bad -- "
                     "host rowid is zero\n", dbg->rowid);
            goto failed;
          }

      if (dbg->type == DB_GRAPH_NETWORK || dbg->type == DB_GRAPH_WIRE)
        if (!dbg->network)
          {
            g_print ("graph_load: entry with rowid %d is bad -- "
                     "network rowid is zero\n", dbg->rowid);
            goto failed;
          }

      if (dbg->type == DB_GRAPH_HOST)
        if (dbg->network)
          {
            g_print ("graph_load: entry with rowid %d is bad -- "
                     "network rowid is %d instead of zero\n",
                     dbg->rowid, dbg->network);
            goto failed;
          }

      if (dbg->type == DB_GRAPH_NETWORK)
        if (dbg->host)
          {
            g_print ("graph_load: entry with rowid %d is bad -- "
                     "host rowid is %d instead of zero\n",
                     dbg->rowid, dbg->network);
            goto failed;
          }

      dbm = g_sqldb_row_find (map_sqldb, "_rowid", &dbg->map);
      if (!dbm)
        {
          g_print ("graph_load: entry with rowid %d is bad -- "
                   "map lookup failed on rowid %d\n",
                   dbg->rowid, dbg->map);
          goto failed;
        }
         
      if (dbg->host)
        {
          dbh = g_sqldb_row_find (host_sqldb, "_rowid", &dbg->host);
          if (!dbh)
            {
              g_print ("graph_load: entry with rowid %d is bad -- "
                       "host lookup failed on rowid %d\n",
                       dbg->rowid, dbg->host);
              goto failed;
            }
        }
         
      if (dbg->network)
        {
          dbn = g_sqldb_row_find (network_sqldb, "_rowid", &dbg->network);
          if (!dbn)
            {
              g_print ("graph_load: entry with rowid %d is bad -- "
                       "network lookup failed on rowid %d\n",
                       dbg->rowid, dbg->network);
              goto failed;
            }
        }
         
      if (dbm)
        {
          dbm->DB_graphs = g_list_append (dbm->DB_graphs, dbg);
          dbg->DB_map = dbm;
        }
         
      if (dbh)
        {
          d_print (DEBUG_TRACE, "Adding dbg->rowid '%d' to dbh->name '%s'\n",
                 dbg->rowid, dbh->name);
          dbg->DB_host = dbh;
        }
         
      if (dbn)
        {
          d_print (DEBUG_TRACE, "Adding dbg->rowid '%d' to dbn->name '%s'\n",
                 dbg->rowid, dbn->name);
          dbg->DB_network = dbn;
        }
         
      switch (dbg->type)
        {
          case DB_GRAPH_HOST:
            d_print (DEBUG_TRACE, "Adding new host\n");
            if (dbh)
              dbh->DB_graphs = g_list_append (dbh->DB_graphs, dbg);
            gxsnmp_host_new (dbg);
            break;
          case DB_GRAPH_NETWORK:
            d_print (DEBUG_TRACE, "Adding new network\n");
            if (dbn)
              dbn->DB_graphs = g_list_append (dbn->DB_graphs, dbg);
            gxsnmp_network_new (dbg);
            break;

        default:
          break;
        }
         
      gl = gl->next;
      continue;

failed:
       
      bad_records = g_list_append (bad_records, dbg);
      gl = gl->next;
    }
  D_FUNC_END;
  return bad_records;
}

/******************************************************************************
**
**  Subroutine to load and initialize the SNMP, host, interface, and network
**  databases -- the non-graphical topological definition of the network.
**
******************************************************************************/
void
table_load_topology (GIOChannel *ddchannel)
{
 
  GList   * gl;
  D_FUNC_START;
  fprintf(stderr,"loading host table\n");
  host_sqldb->channel = ddchannel;
  g_sqldb_table_load (host_sqldb);
  fprintf(stderr,"loading snmp table\n");
  snmp_sqldb->channel = ddchannel;
  g_sqldb_table_load (snmp_sqldb);
  fprintf(stderr,"loading interface table\n");
  interface_sqldb->channel = ddchannel;
  g_sqldb_table_load (interface_sqldb);
  fprintf(stderr,"loading network table\n");
  network_sqldb->channel = ddchannel;
  g_sqldb_table_load (network_sqldb);
  fprintf(stderr,"all tables loaded\n");

/*
**  Each interface table entry needs a pointer to the correct host entry
**  and a pointer to the correct SNMP entry.  The host and SNMP table
**  entries both need GLists of all associated interfaces.
**
**  An interface with no SNMP definition will have dbi->snmp == 0.
*/

fprintf(stderr,"listing interface table\n");

  gl = g_sqldb_table_list (interface_sqldb);
  while (gl)
    {
      DB_interface      * dbi;
      DB_host           * dbh;
      DB_snmp           * dbs;

      dbi = (DB_interface *) gl->data;

      dbh = g_sqldb_row_find (host_sqldb, "_rowid", &dbi->host);
      if (dbh)
        {
          dbh->DB_interfaces = g_list_append (dbh->DB_interfaces, dbi);

         dbi->DB_host = dbh;
        }
      else g_print ("Interface with rowid %d specified nonexistent host "
                    "with rowid %d\n", dbi->rowid, dbi->host);
      if (dbi->snmp)
        {
          dbs = g_sqldb_row_find (snmp_sqldb, "_rowid", &dbi->snmp);
          if (dbs)
            {     
              dbs->DB_interfaces = g_list_append (dbs->DB_interfaces, dbi);
              dbi->DB_snmp = dbs;
            }
          else g_print ("Interface with rowid %d specified nonexistent SNMP "
                        "definition with rowid %d\n", dbi->rowid, dbi->snmp);
        }
      else dbi->DB_snmp = NULL;

      gl = gl->next;
    }
  D_FUNC_END;
}

