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

messages_fifo.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: messages_fifo.c,v 1.42 2008-02-23 08:35:03 anton Exp $ */

#include "netams.h"

//////////////////////////////////////////////////////////////////////////
MessageManager *MsgMgr;
//////////////////////////////////////////////////////////////////////////
// Message class

Message::Message(message_type t){
      type=t;
      next=NULL;
      active=0;
      netams_mutex_init(&lock, NULL);
}

Message::~Message(){
      netams_mutex_destroy(&lock);
}

void Message::Push(){
      netams_mutex_lock(&lock);
      active++;
      netams_mutex_unlock(&lock);
}

void Message::Pop(){
      netams_mutex_lock(&lock);
      active--;
      if(active==0) MsgMgr->Delete(this);
      netams_mutex_unlock(&lock);
}

//////////////////////////////////////////////////////////////////////////
Message_Read::Message_Read(): Message(MSG_READ) {
      ap=netunit=0;
      pdata=NULL;
}

Message_Read::~Message_Read() {
}
//////////////////////////////////////////////////////////////////////////
Message_Store::Message_Store(): Message(MSG_STORE) {
      ap=netunit=0;
      ts=0;
      data=(pstat*)aMalloc(sizeof(pstat));
}

Message_Store::~Message_Store() {
      aFree(data);
}
//////////////////////////////////////////////////////////////////////////
Message_Alert::Message_Alert(): Message(MSG_ALERT) {
      al=(alert*)aMalloc(sizeof(alert));
}

Message_Alert::~Message_Alert() {
      aFree(al);
}
//////////////////////////////////////////////////////////////////////////
Message_AclServer::Message_AclServer(): Message(MSG_ACLSERVER) {
      flag=0;
      ip.s_addr=INADDR_ANY;
}

Message_AclServer::~Message_AclServer() {
}
//////////////////////////////////////////////////////////////////////////
// FIFO class
FIFO::FIFO(unsigned max){
      root=last=ready=NULL;
      num_items=total_items=0;
      num_holders=0;
      max_items=max;
      netams_mutex_init(&lock, NULL);
}

FIFO::~FIFO(){
      MsgHolder *h;
      while(root) {
            h=root;
            root=root->next;
            MsgMgr->Delete(h->msg);
            aFree(h);
      }

      while(ready) {
            h=ready;
            ready=ready->next;
            aFree(h);
      }
      netams_mutex_destroy(&lock);
}

MsgHolder* FIFO::newHolder() {
      MsgHolder *h;

      if(ready) {
            h=ready;
            ready=ready->next;
      } else {
            h=(MsgHolder*)aMalloc(sizeof(MsgHolder));
            num_holders++;
      }
      return h;
}

void FIFO::freeHolder(MsgHolder *h) {
      h->next=ready;
      ready=h;
}

u_char FIFO::Push(Message *msg){
      MsgHolder *h;

//    printf("FIFO push: root:%p last:%p\n", root, last);
      netams_mutex_lock(&lock);
      
      h=newHolder();
      msg->Push();
      h->msg=msg;
      if (root==NULL) root=h;
      else last->next=h;
      last=h;
      h->next=NULL; 
      num_items++;
      total_items++;
      
      if (num_items>max_items) {
            aLog(D_WARN, "FIFO %p overloaded, discarding message %p\n",this,root);
            msg=root->msg;
            h=root;
            root=root->next;
            num_items--;
            msg->Pop();
            freeHolder(h);
        }

      netams_mutex_unlock(&lock);
//    printf("FIFO push: %p\n", msg);
      return 1;
//    printf("FIFO push:  %p lock:%p\n", msg,lock);
}

Message* FIFO::Pop(){
      Message *m=NULL;

//    printf("FIFO pop: root:%p last:%p\n", root, last);
      netams_mutex_lock(&lock);
      
      if (root) {
            MsgHolder *h;

            m=root->msg;
            h=root;
            root=root->next;
            num_items--;
            m->Pop();
            freeHolder(h);
      }
      netams_mutex_unlock(&lock);
//    printf("FIFO pop:  %p lock:%p\n", m,lock);
      return m;
}

Message* FIFO::TryPop(){
        if(root) return root->msg;
      else return NULL;
}
//////////////////////////////////////////////////////////////////////////
//MessageManager
MessageManager::MessageManager() {
      bzero(ready, NUM_MSG_TYPES*sizeof(Message*));;
      bzero(ready_items, NUM_MSG_TYPES*sizeof(unsigned));
      bzero(allocated, NUM_MSG_TYPES*sizeof(unsigned));
      
      total_ready_items=0;
      total_allocated=0;
      netams_mutex_init(&lock, NULL);
}

MessageManager::~MessageManager() {
      Message *m,*ptr;
      
      for(u_char t=0; t<NUM_MSG_TYPES; t++) {
            ptr=ready[t];
            ready[t]=NULL;
            while(ptr) {
                  m=ptr->next;
                  delete ptr;
                  ptr=m;
            }
      }
      netams_mutex_destroy(&lock);
}

Message* MessageManager::New(message_type t) {
      Message *m;
      netams_mutex_lock(&lock);
      if(ready[t]) {
            m=ready[t];
            ready[t]=ready[t]->next;
            ready_items[t]--;
            total_ready_items--;
      } else {
            switch(t) {
                  case MSG_STORE:
                        m=(Message*) new Message_Store();
                        break;
                  case MSG_READ:
                        m=(Message*) new Message_Read();
                        break;
                  case MSG_ALERT:
                  case MSG_COMMAND:
                        m=(Message*) new Message_Alert();
                        break;
                  case MSG_ACLSERVER:
                        m=(Message*) new Message_AclServer();
                        break;
                  default:
                        aLog(D_WARN, "Trying to allocate wrong message type %u\n",t);
                        netams_mutex_unlock(&lock);
                        return NULL;
            }
            total_allocated++;
            allocated[t]++;
      }
      netams_mutex_unlock(&lock);
      return m;
}

void MessageManager::Delete(Message *m) {
      if(!m) return;
      netams_mutex_lock(&lock);
      message_type t=m->type;
      m->next=ready[t];
      ready[t]=m;
      ready_items[t]++;
      total_ready_items++;
      netams_mutex_unlock(&lock);
}

#define SHOW_MGR_INFO(name, type, class) cli_print(cli, \
      "\t%s: %u used, %u ready = %u bytes", name, \
      allocated[type]-ready_items[type], ready_items[type],\
      allocated[type]*sizeof(class));

void MessageManager::Usage(struct cli_def *cli) {
      cli_print(cli, "Total messages:");
      SHOW_MGR_INFO("Store",MSG_STORE,Message_Store);
      SHOW_MGR_INFO("Read",MSG_READ,Message_Read);
      SHOW_MGR_INFO("Alert",MSG_ALERT,Message_Alert);
      SHOW_MGR_INFO("Command",MSG_COMMAND,Message_Alert);
      SHOW_MGR_INFO("ACL Server",MSG_ACLSERVER,Message_AclServer);
}
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////




Generated by  Doxygen 1.6.0   Back to index