/*

 I added these "queue" function to have the structure somewhat ready
 if real queing is implemented.

*/

#include <stdio.h>
#include <glib.h>
#include "gxsnmpdb_types.h"
#include "pdu.h"
#include "g_sql.h"
#include "g_sql-table.h"

extern GList *tranq;
extern GList *profiles;
extern G_sql_connection *dbhandler;

/* tranq_check()
 *
 * check queue for transaction requests.
 *
 *
 */

extern gchar buffer[2000];

void tranrec_free(tranrec *req)
{
  if(req->members)
      g_free(req->members);
  g_free(req);
}

gint tranq_check()
{
static gint num_write;
static GList *gl, *gl2;
static tranrec *req;
static gchar sqlstr[2000];
static G_sql_query *sql;
static G_sql_table *tbh;
gchar *outbuf1 = 0;
gchar *outbuf2 = 0;
gint outi, n=0;

  if(!(gl = g_list_first(tranq))) return;			/* get oldest request from list, return if queue is empty */
  sqlstr[0] = 0;
  req = gl->data;
  switch(req->action)
    {
      case AUTH:
      break;
      case ROW_ADD: /* TAR */
fprintf(stderr,"Adding row\n");
fprintf(stderr,"MemberRecords tot len: %d\n", req->mlen);
            if(!((req->prf->value & DBCTL_AUTH) && (req->prf->value & DBCTL_RW))) break;
            tbh = db_table_lookup(req->table);                               /* identify and point me to right table plugin*/
            if(!g_sql_encode_sql(tbh, req->members, sqlstr, SQL_INSERT, &n, req->mlen)){  /* build a SQL INSERT string */
              debug_decode_output(&n, req->members, 20, 80);
              break;
            }
            if(sql = g_sql_query(dbhandler, sqlstr, strlen(sqlstr))){
              g_sql_free_query(sql);
            }
                /*IF g_sql_query fails, we must build a failure 
                  request and send to source */
      break;
      case ROW_UPDATE: /* TUR */
fprintf(stderr,"Updating row\n");
fprintf(stderr,"MemberRecords tot len: %d\n", req->mlen);
            if(!((req->prf->value & DBCTL_AUTH) && (req->prf->value & DBCTL_RW))) break;
            tbh = db_table_lookup(req->table);                               /* identify and point me to right table plugin*/
            if(!g_sql_encode_sql(tbh, req->members, sqlstr, SQL_UPDATE, &n, req->mlen)){  /* build a SQL UPDATE string */
              debug_decode_output(&n, req->members, 20, 80);
              break;
            }
            if(sql = g_sql_query(dbhandler, sqlstr, strlen(sqlstr))){
              g_sql_free_query(sql);
            }
      break;
      case ROW_DELETE: /* TDR */
fprintf(stderr,"row_delete\n");
            if(!((req->prf->value & DBCTL_AUTH) && (req->prf->value & DBCTL_RW))) break;
            tbh = db_table_lookup(req->table);                               /* identify and point me to right table plugin*/
            g_sql_encode_sql(tbh, req->members, sqlstr, SQL_DELETE, &n, req->mlen);  /* build a SQL DELETE string */
            if(sql = g_sql_query(dbhandler, sqlstr, strlen(sqlstr))){
              g_sql_free_query(sql);
            }
      break;
      case TABLE_LOAD:
            /* lookup table to use
               make a SQL string and send to database
               go through each row of results and compile memberrecords
               send packet back to requesting client ( req->source ) */
fprintf(stderr,"    table_load\n");
            tbh = db_table_lookup(req->table);                               /* identify and point me to right table plugin*/
            outi = 2000;
            if(!(outbuf1 = malloc(outi))) break;				/* alloc initial buffer */
fprintf(stderr,"A");
            g_sql_encode_sql(tbh, 0, sqlstr, SQL_SELECT_ALL,0, 0);
            n = RESULT;
            memcpy(outbuf1, &n, sizeof(gint));					/* set GxSNMP_APICMD type */           
            n=0;
fprintf(stderr,"B");
            sql = g_sql_query(dbhandler, sqlstr, strlen(sqlstr));
            if(!(sql = g_sql_query(dbhandler, sqlstr, strlen(sqlstr)))){
              /*FIX: Notify user, else he must timeout */
              break;
            }
fprintf(stderr,"C");

            while(g_sql_next_row(sql)){						/*walk through each database row*/
              g_sql_decode_sql(tbh, sql, outbuf1+(sizeof(gint)*2), 0, &n);	/* That zero means fetch ALL fields */
              if(n > outi - 1000){						/* we are almost out of buffer */
                outi += 2000;
                if(!(outbuf2 = malloc(outi))){					/* alloc new buffer */
                  /*FIX: Notify user, else he must timeout */
                  g_free(outbuf1);
                  g_sql_free_query(sql);
                  break;
                }
                memcpy(outbuf2, outbuf1, n + (sizeof(gint) * 2));		/* move over old buffer to new */
                g_free(outbuf1);						/* release old buffer */
                outbuf1 = outbuf2;						/* set new buffer pointer */
              }
            }
fprintf(stderr,"D");
            /* ALL data in table has been fetched, send result back to user */
            g_sql_free_query(sql);
            n += sizeof(gint) * 2;						/* Total packet length */
            memcpy(outbuf1+sizeof(gint), &n, sizeof(gint));			/*write packet total length*/
fprintf(stderr,"E");
            g_io_channel_write(req->source, outbuf1, n, &num_write);
            g_free(outbuf1);
fprintf(stderr,"F");
      break;
      case ROW_READ:
fprintf(stderr,"row_read\n");
/* this code isn't so nice to*/

            tbh = db_table_lookup(req->table);                               /* identify and point me to right table plugin*/
            n = RESULT;
            memcpy(buffer, &n, sizeof(gint));    				/* build action_cmd in header */
            n=0;
            g_sql_encode_sql(tbh, req->members, sqlstr, SQL_SELECT_PRI, &n, req->mlen);  /* build a SQL SELECT string */
            if(sql = g_sql_query(dbhandler, sqlstr, strlen(sqlstr))){
              break;
            }
            g_sql_next_row(sql);
            g_sql_decode_sql(tbh, sql, buffer+11+sizeof(guint), 0, &n);	/* That zero means fetch ALL fields */
            g_sql_free_query(sql);					/* all SQL result data fetched */

            n += sizeof(gint) * 2;					/* total packet length*/
            memcpy(buffer+sizeof(gint), &n, sizeof(gint));                        /* write total packet length*/
            g_io_channel_write(req->source, buffer, n, &num_write);
      break;
      case NOTIFY: /*just copy req->table to the connection profile */
            req->prf->value = req->table;
      break;

      case TABLE_LOAD_FILTERED: /* translate the IP address to a hostname */
            if(!(tbh = db_table_lookup(req->table))){                               /* identify and point me to right table plugin*/
              fprintf(stderr,"Cant carry out request: No table named: %d\n", req->table);
              break;
            }
            g_sql_encode_sql(tbh, req->members, sqlstr, SQL_SELECT, &n, req->mlen);  /* build a SQL_SELECT string */
            if(!(sql = g_sql_query(dbhandler, sqlstr, strlen(sqlstr)))){
              break;
            }
               /* we have now sent the SQL string that is originally built out of a
                  object filter converted into member-records, now we convert all
                  answers from SQL-DB into member-records */

            outi = 2000;
            if(!(outbuf1 = malloc(outi))) break;				/* alloc initial buffer */
            n = RESULT;
            memcpy(outbuf1, &n, sizeof(gint));					/* set GxSNMP_APICMD type */           
            n=0;

            while(g_sql_next_row(sql)){						/*walk through each database row*/
              g_sql_decode_sql(tbh, sql, outbuf1+(sizeof(gint)*2), 0, &n);	/* That zero means fetch ALL fields */
              if(n > outi - 1000){						/* we are almost out of buffer */
                outi += 2000;
                if(!(outbuf2 = malloc(outi))){					/* alloc new buffer */
                  g_free(outbuf1);
                  break;
                }
                memcpy(outbuf2, outbuf1, n + (sizeof(gint) * 2));		/* move over old buffer to new */
                g_free(outbuf1);						/* release old buffer */
                outbuf1 = outbuf2;						/* set new buffer pointer */
              }
            }

            /* all data in table has been fetched, send result back to user */

            g_sql_free_query(sql);
            n += sizeof(gint) * 2;						/* Total packet length */
            memcpy(outbuf1+sizeof(gint), &n, sizeof(gint));			/*write packet total length*/
            g_io_channel_write(req->source, outbuf1, n, &num_write);
            g_free(outbuf1);
      break;

      default:
        fprintf(stderr,"Unknown request action\n");
            /*maybe we should notify the client about this, 
              he could be running a old version or something*/
   }
fprintf(stderr,"Freeing request\n");
  tranrec_free(req);
fprintf(stderr,"removing request from queue\n");
  tranq = g_list_remove(tranq, req);
  return 0;
}
