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

s_storage.c

/*************************************************************************
***   Authentication, authorization, accounting + firewalling package
***   Copyright 1998-2002 Anton Vinokurov <anton@netams.com>
***   Copyright 2002-2008 NeTAMS Development Team
***   This code is GPL v3
***   For latest version and more info, visit this project web page
***   located at http://www.netams.com
***
*************************************************************************/
/* $Id: s_storage.c,v 1.115 2009-08-01 09:23:55 anton Exp $ */

#include "netams.h"
#include "st_any.h"

static int initialized=0;

/////////////////////////////////////////////////////////////////////////
//defined commands
static const  struct CMD_DB cmd_db[] = {
//STORAGE
{ 27, 0, 0, "type",     PRIVILEGE_UNPRIVILEGED, MODE_STORAGE, NULL,                 NULL },
#if defined(USE_HASH)
{ 0, 27, 0, "hash",     PRIVILEGE_UNPRIVILEGED, MODE_STORAGE, cServiceProcessCfg,   NULL },
#endif
#if defined(USE_MYSQL)
{ 0, 27, 0, "mysql",    PRIVILEGE_UNPRIVILEGED, MODE_STORAGE, cServiceProcessCfg,   NULL },
#endif
#if defined(USE_POSTGRES)
{ 0, 27, 0, "postgresql", PRIVILEGE_UNPRIVILEGED, MODE_STORAGE, cServiceProcessCfg, NULL },
#endif
#if defined(USE_ORACLE)
{ 0, 27, 0, "oracle",   PRIVILEGE_UNPRIVILEGED, MODE_STORAGE, cServiceProcessCfg,   NULL },
#endif
#if defined(USE_LIBRADIUS)
{ 0, 27, 0, "radius",   PRIVILEGE_UNPRIVILEGED, MODE_STORAGE, cServiceProcessCfg,   NULL },
{ 0, 0, 0, "retry",     PRIVILEGE_UNPRIVILEGED, MODE_STORAGE, cServiceProcessCfg,   NULL },
{ 0, 0, 0, "timeout",   PRIVILEGE_UNPRIVILEGED, MODE_STORAGE, cServiceProcessCfg,   NULL },
{ 0, 0, 0, "nas-ip",    PRIVILEGE_UNPRIVILEGED, MODE_STORAGE, cServiceProcessCfg,   NULL },
#endif
{ 0, 0, 0, "user",      PRIVILEGE_UNPRIVILEGED, MODE_STORAGE, cServiceProcessCfg,   NULL },
{ 0, 0, 0, "path",      PRIVILEGE_UNPRIVILEGED, MODE_STORAGE, cServiceProcessCfg,   NULL },
{ 0, 0, 0, "password",  PRIVILEGE_UNPRIVILEGED, MODE_STORAGE, cServiceProcessCfg,   NULL },
{ 0, 0, 0, "host",      PRIVILEGE_UNPRIVILEGED, MODE_STORAGE, cServiceProcessCfg,   NULL },
{ 0, 0, 0, "dbname",    PRIVILEGE_UNPRIVILEGED, MODE_STORAGE, cServiceProcessCfg,   NULL },
{ 0, 0, 0, "socket",    PRIVILEGE_UNPRIVILEGED, MODE_STORAGE, cServiceProcessCfg,   NULL },
{ 0, 0, 0, "port",      PRIVILEGE_UNPRIVILEGED, MODE_STORAGE, cServiceProcessCfg,   NULL },
{ 0, 0, 0, "accept",    PRIVILEGE_UNPRIVILEGED, MODE_STORAGE, cServiceProcessCfg,   NULL },
{ 0, 0, 0, "start",     PRIVILEGE_UNPRIVILEGED, MODE_STORAGE, cServiceStart,            NULL },
{ 0, 0, 0, "stop",      PRIVILEGE_UNPRIVILEGED, MODE_STORAGE, cServiceStop,             NULL },
{ -1, 0, 0, NULL,  0, 0, NULL, NULL }
};
//////////////////////////////////////////////////////////////////////////
class Service_Storage: public Service_Storage_Interface {
      public:
            storage_type st_type;
            Storage *storage;

            FIFO *in;
            FIFO *out;

            u_char accept[ST_CONN_TYPES_NUM];

            Service_Storage();
            ~Service_Storage();

            void ShowCfg(struct cli_def *cli, u_char flags);
            int ProcessCfg(struct cli_def *cli, char **argv, int argc, u_char no_flag);
            void ShowInfo(struct cli_def *cli);
            void ShowPerf(struct cli_def *cli, u_char isheader);
            void Worker();
            void Cancel();
            int ProcessMessage(void *ptr);

            void stStore();

            //interface calls
            int stLoad(st_conn_type type,
                  void (*FillData)(void *res, void *row, char* (*getRowData)(void*, void* , u_char))=NULL);
            int SaveFile(char *filename, st_conn_type type);
            int isAccepted(st_conn_type type);
            void Close(st_conn_type type);
};
//////////////////////////////////////////////////////////////////////////
Service* InitStorageService() {
        if(!initialized) {
                InitCliCommands(cmd_db);
                initialized = 1;
        }
        return (Service*)new Service_Storage();
}
//////////////////////////////////////////////////////////////////////////
const char *db_type_name[ST_DB_TYPES_NUM]={ "UNKNOWN", "hash", "mysql", "postgres", "oracle", "radius" };
//////////////////////////////////////////////////////////////////////////
Service_Storage::Service_Storage():Service_Storage_Interface() {
      in=new FIFO(MAX_UNITS*5);
      out=new FIFO(MAX_UNITS*5);

      for (int i=0; i<ST_CONN_TYPES_NUM; i++) accept[i]=1; // by default, each storage accepts everything

      st_type=UNKNOWN;
      storage=NULL;
}

Service_Storage::~Service_Storage() {
      delete in;
      delete out;
      if(storage) delete storage;
}

//////////////////////////////////////////////////////////////////////////
Storage::Storage(storage_type type, u_char id) {
      st_type=type;
      instance=id;

      bzero(FD, ST_CONN_TYPES_NUM*sizeof(void*));
}

Storage::~Storage() {

}

void Storage::Cancel() {
      for(u_char conn_type=0;conn_type<ST_CONN_TYPES_NUM;conn_type++)
            if(FD[conn_type]) Close((st_conn_type)conn_type);
}

//////////////////////////////////////////////////////////////////////////
int Service_Storage::ProcessCfg(struct cli_def *cli, char **param, int argc, u_char no_flag){

      if (STREQ(param[0], "type")) {
            if(0) ;
      #if defined(USE_HASH)
            else if (STREQ(param[1], "hash")) {
                  st_type = ST_HASH;
                  storage = InitHashStorage(st_type, instance);
            }
      #endif
      #if defined(USE_MYSQL)
            else if (STREQ(param[1], "mysql")) {
                  st_type = ST_MYSQL;
                  storage = InitSqlStorage(st_type, instance);
            }
      #endif
      #if defined(USE_POSTGRES)
            else if (STREQ(param[1], "postgres")) {
                  st_type = ST_POSTGRES;
                  storage = InitSqlStorage(st_type, instance);
            }
      #endif
      #if defined(USE_ORACLE)
            else if (STREQ(param[1], "oracle")) {
                  st_type = ST_ORACLE;
                  storage = InitSqlStorage(st_type, instance);
            }
      #endif
      #if defined(USE_LIBRADIUS)
            else if (STREQ(param[1], "radius")) {
                  st_type = ST_RADIUS;
                  storage = InitRadiusStorage(st_type, instance);
            }
      #endif
            else {
                  cli_error(cli, "This type not exist or not compiled in!\n");
                  return CLI_OK;
            }
            cli_error(cli, "storage type is set to %s", db_type_name[st_type]);

      }
      else if (STREQ(param[0], "accept")) {
            for (int i=0; i<ST_CONN_TYPES_NUM; i++) accept[i]=0; // if accept is specified, flush everything
            int except=1;
            for (int j=1; j<argc; j++ ){
                  if (STREQ(param[j], "except")) {
                        except=0;
                  }
                  else if (STREQ(param[j], "all")) {
                        for (int i=0; i<ST_CONN_TYPES_NUM; i++) accept[i]=except;
                  }
                  else {
                        for (int i=1; i<ST_CONN_TYPES_NUM; i++) {
                              if (STREQ(st_table_name[i], param[j])) accept[i]=except;
                        }
                  }
            }
            char *tmp=NULL;
            for (int i=1; i<ST_CONN_TYPES_NUM; i++)
                  if (accept[i]==1) print_to_string(&tmp, " %s", st_table_name[i]);
            cli_error(cli, "this storage will accept following data:%s", tmp);
            aFree(tmp);
      } else
            return storage?storage->ProcessCfg(cli, param, argc, no_flag): CLI_ERROR;

      return CLI_OK;
}
//////////////////////////////////////////////////////////////////////////
void Service_Storage::Worker(){
      if(!storage) {
            aLog(D_WARN, "storage type undefined, service will be finished\n");
            return;
      }

      aLog(D_INFO, "storage:%d working with %s\n", instance, db_type_name[st_type]);
      while(1) {
            stStore();
            Sleep();
      }
}
//////////////////////////////////////////////////////////////////////////
void Service_Storage::Cancel(){
      stStore();
      if(storage) storage->Cancel();
}
//////////////////////////////////////////////////////////////////////////
void Service_Storage::ShowPerf(struct cli_def *cli, u_char isheader) {
      if (isheader) cli_bufprint(cli, " StWRITE:%u", instance);
      else cli_bufprint(cli, " %7lu", in->total_items);
}

void Service_Storage::ShowInfo (struct cli_def *cli) {
      cli_print(cli, " Storage ID=%u type %s wr_q %u/%lu rd_q %u/%lu",
            instance, db_type_name[st_type],
            in->num_items, in->total_items,
            out->num_items, out->total_items);
}
//////////////////////////////////////////////////////////////////////////
void Service_Storage::ShowCfg(struct cli_def *cli, u_char flags){

      if(storage) storage->ShowCfg(cli, flags);

      if (accept[ST_CONN_UNDEF]==1) {
            cli_bufprint(cli, "accept all");
            int except_printed=0;
            for (int i=1; i<ST_CONN_TYPES_NUM; i++)
                  if (accept[i]==0) {
                        if (except_printed==0) {
                              except_printed=1;
                              cli_bufprint(cli, " except");
                        }
                        cli_bufprint(cli, " %s", st_table_name[i]);
                  }
      } else {
            cli_bufprint(cli, "accept");
            for (int i=1; i<ST_CONN_TYPES_NUM; i++) if (accept[i]==1) {
                  cli_bufprint(cli, " %s", st_table_name[i]);
            }
      }
      cli_bufprint(cli, "\n"); // accept ...
}
//////////////////////////////////////////////////////////////////////////
int Service_Storage::ProcessMessage(void *ptr) {
      in->Push((Message*)ptr);
      return 1;
}
//////////////////////////////////////////////////////////////////////////
//transparent calls to storage
int Service_Storage::stLoad(st_conn_type conn_type,
                  void (*FillData)(void *res, void *row, char* (*getRowData)(void*, void* , u_char))) {
      return storage?storage->Load(conn_type, FillData):0;
}
void Service_Storage::Close(st_conn_type type) {
      if(storage) storage->Close(type);
}
int Service_Storage::SaveFile(char *filename, st_conn_type type){
      return storage?storage->SaveFile(filename, type):-1;
}
//////////////////////////////////////////////////////////////////////////
void Service_Storage::stStore() {
      Message *msg;

      while((msg=in->TryPop())) {
            if (msg->type==MSG_STORE) {
                  Message_Store *smsg=(Message_Store*)msg;
                  aDebug(DEBUG_STORAGE, "ST->%s/%c wr st:%u unit:%06X acct:%06X from:%u to:%u\n",
                        db_type_name[st_type],
                        smsg->prefix, instance, smsg->netunit, smsg->ap, smsg->data->from, smsg->ts);
                  if(storage->StoreMSG(msg)<0) return;
            } else {
                  aDebug(DEBUG_STORAGE, "message type %u not STORE - discarded\n",msg->type);
            }
            msg=in->Pop();
      }
      storage->StoreMSG(NULL);
}
//////////////////////////////////////////////////////////////////////////
int Service_Storage::isAccepted(st_conn_type conn_type) {
      if(accept[conn_type]==1)
            return 1;
      return 0;
}
//////////////////////////////////////////////////////////////////////////


Generated by  Doxygen 1.6.0   Back to index