[Develope]/Network

posix proactor library

하늘을닮은호수M 2008. 7. 1. 18:07
반응형

++++++++++++++++++++++++++
+ Header File
++++++++++++++++++++++++++


// posix_proactor.h, v 0.1 2005/05/19
// ============================================================================
/**
 *
 *   
 *
 * @file    posix_proactor.h
 *
 * @brief  posix_proactor which use RT Signal.
 *
 * struct aiocb
 *       int             aio_fildes;     //file descriptor
 *      volatile void   *aio_buf;   //buffer allocation
 *      size_t          aio_nbytes; //length of transfer
 *      off_t           aio_offet;      //file offset. starting position
 *      int             aio_reqprio;  //request priority offset(_POSIX_PRIORITIZED_IO and _POSIX_PRORITY_SCHEDULING
 *      struct sigevent aio_sigevent;   //signal number and offset
 *      int             aio_lio_opcode; //listio operation
 *
 *  @author sunsson <sunsson@varovision.com>
 */
// ============================================================================
#ifndef __POSIX_PROACTOR__
#define __POSIX_PROACTOR__

#include <signal.h>
#include <time.h>
#include <aio.h>

#define AIOCB_MAX_SIZE 2048      //서버가 지원하는 최대 클라이언트 수(1024) * 클라이언트 당 요청한 파일의 미디어 수(평균 2)
#define PROACTOR_DEBUG 1

#ifdef __cplusplus
extern "C" {
#endif//__cplusplus

//typedef void (*SIGNAL_C_FUNC)(int, siginfo_t *, void *);

/**
 *  posix asynchronous result
 *  <BR>
 *  asynchronous reqeust를 요청한 곳 ( handler, data ) 에 요청된 결과가 처리되었을 때
 *  알리기 위한 구조
 */
typedef struct posix_asynch_result{

    /// allocated aiocb
    struct aiocb *aiocb;

    /// file description
    int fd;
   
    /// Bytes transferred by this operation.
    size_t size;

    /**
      * This really make sense only when doing file I/O.
      *
      * @@ On POSIX4-Unix, offset_high should be supported using
      *     aiocb64.
      *
      */
    unsigned long offset;
    unsigned long offset_high;

    /// Priority of the operation.
    int priority;

    /**
    * POSIX4 realtime signal number to be used for the
    * operation. <signal_number> ranges from SIGRTMIN to SIGRTMAX. By
    * default, SIGRTMIN is used to issue <aio_> calls.
    */
    int signal_number;
   
    /// Success indicator.
    int success;
   
    /// Error if operation failed.
    unsigned long error;

    /// on receiving signal in signal_hander, to call media's handler function
    void * (*hndlr)(void *);

    /// on receiving signal in signal_hander, to give a parameter to media's handler function
    void * data;

}posix_asynch_result;
/**
 * aiocb에 대한 요청이 READ인지, WRITE인지를 나타내는 값
 */
typedef enum{
  READ = 1,
  WRITE = 2
}Opcode;

/// number of aiocb
struct aiocb **aiocb_list;  //AIOCB_MAX_SIZE만큼
posix_asynch_result **result_list;

/// signal set
static sigset_t RT_completion_signal;

/// To maintain the maximum size of the array (list).
size_t aiocb_list_max_size;
/// To maintain the current size of the array (list).
size_t aiocb_list_cur_size;
/// Number of posix_asynch_result's waiting for start
/// i.e. deferred AIOs
size_t num_deferred_aiocb;
/// Number active,i.e. running requests
size_t num_started_aio;


/////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////PROACTOR INIT////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////
/**
 * @author 박학선
 * @param max_aio_operations System Interface에서 사용할 aiocb_list의 최대 갯수
 * @retval -1 proactor init error
 * @retval 0 proactor init ok
 * @brief System Interface이 초기화될 때 posix_proactor를 초기화
 *            하면서 시그널 세팅!!
 */
int
posix_proactor_init(size_t max_aio_operations);

/**
 * @author 박학선
 * @param
 * @retval
 * @brief System의 max aio size를 체크!!
 */
void
check_max_aio_num();

/**
 * @author 박학선
 * @param
 * @retval 0 result create ok
 * @brief System이 관리할 aiocb_list, result_list를 만듬
 */
int
create_result_aiocb_list();

/**
 * @author 박학선
 * @param
 * @retval -1 setup signal init or setup signal_hanlder fail
 * @retval 0 setup signal init(handler) success
 * @brief System이 사용할 signal(RTSIG_MIN) set up!!
 */
int
signal_init();

/**
 * @author 박학선
 * @param signal_number signal handler를 띄울 RTSIG
 * @retval -1 setup signal handler fail
 * @retval 0 setup signal handler success
 * @brief System Interface이 초기화될 때 시그널 핸들러 세팅!!
 */
int
setup_signal_handler(int signal_number);


/////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////CALLBACK/////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////
/**
 * @author 박학선
 * @param signal_number signal handler를 깨운 signal
 * @param info signal과 연관된 정보들(aiocb_list의 index)
 * @param context 사용한 바 없음.
 * @retval
 * @brief 요청된 read를 수행한 후에 호출되는 signal_handler
 */
void
rtsig_handler (int signal_number, siginfo_t* info, void* context);

/**
 * @author 박학선
 * @param
 * @retval -1 handler event error
 * @retval 0   run_event_loop complete
 * @brief loop을 돌면서 완료된 aiocb_list가 있는지 검사
 */
 int
run_event_loop();

/**
 * @author 박학선
 * @param
 * @retval -1 sigtimedwait error
 * @retval 0   handler_event complete
 * @brief 요청된 read를 수행한 후에 호출되는 signal_handler
 *      ====> signal_handler에서 signal을 감지했을 때완료된 요청이 있는지 검사
 */
int
handle_event(void);


//posix_asynch_result *
//find_completed_aio(int *error_status, size_t *transfer_count, size_t index, size_t count);

/**
 * @author 박학선
 * @param aiocb
 * @param error_status
 * @param transfer_count
 * @retval 1  AIO completed
 * @retval 0  not completed yet
 * @brief AIO가 completed되었는지를 체크
 */
int
get_result_status (struct aiocb *aiocb, int *error_status, size_t *transfer_count);

/**
 * @author 박학선
 * @param idx
 * @param transfer_count
 * @param error_status
 * @brief completed된 aiocb_list의 callback handler를 호출
 */
void
application_specific_code(size_t idx, int transfer_count, int error_status);


/////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////REQEUEST////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////
/**
 * @author 박학선
 * @param file_fd
 * @param size
 * @param offset
 * @param buf
 * @param data
 * @param hndlr_ftn
 * @param priority
 * @param op
 * @brief media에서 asynchronous read를 요청하기 위해 호출하는 함수.
 *           실제로는 이 파일안에 정의되어 있지는 않음. 단지 테스트를 위해서...
 */
 int
si_read_req(int file_fd, int size, int offset, void *buf, void *data, void *hndlr_ftn, int priority, Opcode op);

/**
 * @author 박학선
 * @param result
 * @param op
 * @retval 0 started OK
 * @retval 1 OS AIO queue overflow
 * @retval -1 do not started
 * @brief System Interface(si_read_req())에서 Proactor에
 *       read를 요청하기 위해 사용!!
 */
int
issue_aio_calls (posix_asynch_result *result, Opcode op);

/**
 * @author 박학선
 * @param aiocb
 * @retval 0 AIO was started successfully
 * @retval 1 AIO was not started, OS AIO queue overflow
 * @retval -1 AIO was not started, other errors
 * @brief 파일의 미디어 트랙에서 aio_read, aio_write를 실행!!
 */
int
execute_aio_calls (struct aiocb * aiocb);

/**
 * @author 박학선
 * @param aiocb
 * @retval retval > 0 allocated aiocb_list's slot
 * @retval -1   no free slot
 * @brief  이 시스템에서 관리하는 aiocb_list의 free slot을 반환한다.
 */
ssize_t
allocate_aio_slot(struct aiocb * aiocb);

#ifdef __cplusplus
}
#endif//__cplusplus


#endif //__POSIX_PROACTOR__

++++++++++++++++++++++++++
+ Source File
++++++++++++++++++++++++++

// posix_proactor.c, v 0.1 2005/05/19
// ============================================================================
/**
 *
 *   
 *
 * @file    posix_proactor.c
 *
 * posix_proactor which use RT Signal.
 *
 * struct aiocb
 *       int             aio_fildes;     //file descriptor
 *      volatile void   *aio_buf;   //buffer allocation
 *      size_t          aio_nbytes; //length of transfer
 *      off_t           aio_offet;      //file offset. starting position
 *      int             aio_reqprio;  //request priority offset(_POSIX_PRIORITIZED_IO and _POSIX_PRORITY_SCHEDULING
 *      struct sigevent aio_sigevent;   //signal number and offset
 *      int             aio_lio_opcode; //listio operation
 *
 *  @author sunsson <sunsson@varovision.com>
 */
// ============================================================================

#include "posix_proactor.h"
#include "test/test_posix_proactor.h"

#include <unistd.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/resource.h>       //getrlimit, strlimit : control maximum resource consumption
#include <signal.h>
#include <string.h>
#include <errno.h>
#include <stdio.h>
#include <limits.h>
#include <aio.h>
#include <time.h>
#include <assert.h>


/////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////PROACTOR INIT////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////
/**
 * @author 박학선
 * @param max_aio_operations System Interface에서 사용할 aiocb_list의 최대 갯수
 * @retval -1 proactor init error
 * @retval 0 proactor init ok
 * @brief System Interface이 초기화될 때 posix_proactor를 초기화
 *            하면서 시그널 세팅!!
 */
int
posix_proactor_init(size_t max_aio_operations)
{
    aiocb_list = 0;
    result_list = 0;
    aiocb_list_max_size = max_aio_operations;
    aiocb_list_cur_size = 0;
    num_deferred_aiocb = 0;
    num_started_aio = 0;

    check_max_aio_num();
    if(create_result_aiocb_list() != 0){
        fprintf(stderr, "aiocb list make error\n");
        return -1;
    }
    if(signal_init() != 0){
        fprintf(stderr, "signal init error\n");
        return -1;
    }
    ///run_event_loop에서 완료된 sigset이 있는지 체크..
    //run_event_loop();
    return 0;
}

/**
 * @author 박학선
 * @param
 * @retval
 * @brief System의 max aio size를 체크!!
 */
void
check_max_aio_num()
{
    long max_aio_num;
    int max_num_files, r;
    struct rlimit rl;

    max_aio_num = sysconf (_SC_AIO_MAX);
        if (max_aio_num > 0 &&  aiocb_list_max_size > (unsigned long) max_aio_num)
            aiocb_list_max_size = max_aio_num;

    if (aiocb_list_max_size <= 0 || aiocb_list_max_size > AIOCB_MAX_SIZE)
        aiocb_list_max_size = AIOCB_MAX_SIZE;


#if defined (RLIM_INFINITY)
    r = getrlimit (RLIMIT_NOFILE, &rl);
    if (r == 0 && rl.rlim_cur != RLIM_INFINITY)
       max_num_files =  rl.rlim_cur;
#endif //RLIM_INFINITY

    if (max_num_files > 0 && aiocb_list_max_size > (unsigned long) max_num_files){
#if defined (RLIM_INFINITY)
    rl.rlim_cur = max_num_files;
    r = setrlimit (RLIMIT_NOFILE, &rl);
    if (r == 0 && rl.rlim_cur != RLIM_INFINITY)
#endif //RLIM_INFINITY
        aiocb_list_max_size = max_num_files;
    }
}

/**
 * @author 박학선
 * @param
 * @retval 0 result create ok
 * @brief System이 관리할 aiocb_list, result_list를 만듬
 */
int create_result_aiocb_list()
{
    size_t ai;
   
    if (aiocb_list != 0)
      return 0;

    aiocb_list = (struct aiocb**)malloc(sizeof(struct aiocb *[aiocb_list_max_size]));
    result_list = (posix_asynch_result **)malloc(sizeof(posix_asynch_result * [aiocb_list_max_size]));

    for (ai = 0; ai < aiocb_list_max_size; ai++){
        aiocb_list[ai] = 0;
        result_list[ai] = 0;
    }
    return 0;
}

/**
 * @author 박학선
 * @param
 * @retval -1 setup signal init or setup signal_hanlder fail
 * @retval 0 setup signal init(handler) success
 * @brief System이 사용할 signal(RTSIG_MIN) set up!!
 */
int signal_init()
{
    int ret_val;
    /// Get full set
    if(sigemptyset(&RT_completion_signal) == -1)
        fprintf(stderr, "[Error] Couldnt empty signal set\n");
   
    if(sigaddset(&RT_completion_signal, SIGRTMIN) == -1)
        fprintf(stderr, "[Error] Couldnt init the RT completion signal set\n");

    ///block the signal
    if(sigprocmask(SIG_BLOCK, &RT_completion_signal, 0) == -1) {
        fprintf(stderr, "Could not block SIGRTMAX or SIGRTMAX-1");
        return -1;
    }

     ret_val = setup_signal_handler(SIGRTMIN);

    ///unblock the signal
    //if(sigprocmask(SIG_UNBLOCK, &newact.sa_mask, NULL) == -1){
    if(sigprocmask(SIG_UNBLOCK, &RT_completion_signal, 0) == -1) {
        fprintf(stderr, "Could not unblock SIGRTMAX or SIGRTMAX-1");
        return -1;
    }

    return ret_val;
}

/**
 * @author 박학선
 * @param signal_number signal handler를 띄울 RTSIG
 * @retval -1 setup signal handler fail
 * @retval 0 setup signal handler success
 * @brief System Interface이 초기화될 때 시그널 핸들러 세팅!!
 */
int
setup_signal_handler(int signal_number)
{
    struct sigaction newact;
    int sigaction_return;

    sigemptyset(&newact.sa_mask);   //Nothing else to mask
    newact.sa_flags = SA_SIGINFO;    // Realtime flag.
    newact.sa_sigaction = rtsig_handler ;  //set up "null_handler"
    sigaction_return = sigaction (signal_number, &newact, 0);  //specify the action to be associated with a specific signal
    if(sigaction_return == -1){
        fprintf(stderr, "[Error]couldnt do sigaction for the RT SIGNAL\n");
        return -1;
    }
    return 0;
}


/////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////CALLBACK/////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////
/**
 * @author 박학선
 * @param signal_number signal handler를 깨운 signal
 * @param info signal과 연관된 정보들(aiocb_list의 index)
 * @param context 사용한 바 없음.
 * @retval
 * @brief 요청된 read를 수행한 후에 호출되는 signal_handler
 */
void
rtsig_handler (int signal_number, siginfo_t* info, void* context)
{
    int result = 0;
//    struct timespec timeout;

#if 0
    fprintf(stderr, "[info]Signal number %d\n", signal_number);
    if(query_aio_completions() < 0)
        fprintf(stderr, "null handler error\n");
    else
        fprintf(stdout, "rtsig_handler\n");
#else//0

#ifdef PROACTOR_DEBUG
    fprintf(stdout, "\n\nrtsig_handler\n");
#endif//PROACTOR_DEBUG
    result = handle_event ();
    if (result != 0 || errno == ETIME)
        perror("handle_event \n");
#endif//0
 exit(1);
}

/**
 * @author 박학선
 * @param
 * @retval -1 handler event error
 * @retval 0   run_event_loop complete
 * @brief loop을 돌면서 완료된 aiocb_list가 있는지 검사
 */
int run_event_loop()
{
    int ret_val;
    // Run the event loop.
    for (;;){
       ret_val = handle_event();
       if(ret_val == -1)
        break;
    }
    return 0;
}

/**
 * @author 박학선
 * @param
 * @retval -1 sigtimedwait error
 * @retval 0   handler_event complete
 * @brief 요청된 read를 수행한 후에 호출되는 signal_handler
 *      ====> signal_handler에서 signal을 감지했을 때완료된 요청이 있는지 검사
 */
int
handle_event (void)
{
    int sig_return = 0, error_status = 0;
    int ret_aio, ret_val;
    size_t aiocb_index = 0, transfer_count = 0, count = 1, idx;;
    posix_asynch_result* asynch_result;
   
    ///To get back the signal info.
    siginfo_t sig_info;
    struct timespec timeout;       //set to "INFINITE"

#ifdef PROACTOR_DEBUG 
    printf("handle_event called\n");
#endif

    timeout.tv_sec = 0;  
    timeout.tv_nsec = 0;
    sig_return = sigtimedwait(&RT_completion_signal, &sig_info, &timeout);

    ///Error case.
    if (sig_return== -1 && errno == EAGAIN)
        return -1;
   
    if (sig_return == -1){
        fprintf(stderr, "[Error] Error waiting for RT completion signals\n");
        return -1;
    }

    if(sig_return != SIGRTMIN){
        fprintf(stderr, "[Error] Unexpected Signal\n");
        return -1;
    }

    // @@ Debugging.
    //fprintf (stderr, "[Info] Sig number found in the sig_info block[RTSIG] : %d\n", sig_info.si_signo);       

    // @@ Debugging.
    //fprintf (stderr, "[Info] Signal code for this signal delivery : %d\n", sig_info.si_code);

    // Is the signal code an aio completion one?
    if(sig_info.si_code == SI_ASYNCIO){
        aiocb_index = (size_t)sig_info.si_value.sival_int;
#ifdef PROACTOR_DEBUG
        fprintf(stderr, "[Info] aiocb_index : %d\n", aiocb_index);
#endif
    }
    else if(sig_info.si_code == SI_QUEUE){
        assert(sig_info.si_code == SI_QUEUE);
        fprintf(stderr, "[Info] sigqueue caught... good\n");
    }
    else //(sig_info.si_code != SI_ASYNCIO) && (sig_info.si_code != SI_QUEUE))
        fprintf(stderr, "[Error] Unexpected signal code (%d) returned on completion querying\n", sig_info.si_code);

    for(idx = 1; idx<aiocb_list_max_size; idx++){
        ret_val = get_result_status(aiocb_list[idx], &error_status, &transfer_count);
 
        if( ret_val == 1){   // "1" ; AIO Complete
            // Call the application code.
            application_specific_code (idx, transfer_count, error_status);
        }
    }//for

#ifdef PROACTOR_DEBUG 
        printf("handle_event end\n");
#endif

    return 0;
}
/*
posix_asynch_result *
find_completed_aio(int *error_status, size_t *transfer_count, size_t index, size_t count)
{
    size_t idx;
#ifdef PROACTOR_DEBUG
    printf(" %d\t%d\t%d\t%d\n", *error_status, *transfer_count, index, count);
#endif

#if 0

    posix_asynch_result* asynch_result = 0;
    for (; count > 0; index++ , count--){  

        if (index >= aiocb_list_max_size) // like a wheel
            index = 0;

        if (aiocb_list[index] == 0) // Dont process null blocks.
            continue;

#ifdef PROACTOR_DEBUG
        printf(" %p\t%d\t%d\n", aiocb_list[index], *error_status, *transfer_count);
#endif

        if(get_result_status(aiocb_list[index], error_status, transfer_count) != 0)
            break;
    }
   
    if (count == 0) // all processed , nothing found
      return 0;

    asynch_result->aiocb = aiocb_list[index];
    aiocb_list[index] = 0;   
    aiocb_list_cur_size--;

    num_started_aio--;  // decrement count active aios
    index++;             // for next iteration
    count--;             // for next iteration

//    start_deferred_aio();

#else //0
    posix_asynch_result* asynch_result = 0;

    for(idx = count; idx<aiocb_list_max_size; idx++){
        if (index >= aiocb_list_max_size) // like a wheel
            index = 0;
       
        if (aiocb_list[idx] == 0) // Dont process null blocks.
            continue;
       
#ifdef PROACTOR_DEBUG
        printf(" %p\t%d\t%d\n", aiocb_list[idx], *error_status, *transfer_count);
#endif
       
        if(get_result_status(aiocb_list[idx], error_status, transfer_count) != 0)
            continue;
            }
#if 0           
    if (count == 0) // all processed , nothing found
      return 0;

    asynch_result->aiocb = aiocb_list[idx];
    aiocb_list[idx] = 0;   
    aiocb_list_cur_size--;

    num_started_aio--;  // decrement count active aios
    idx++;                  // for next iteration
    count--;                // for next iteration
#endif
#endif

    return asynch_result;
}
*/

/**
 * @author 박학선
 * @param aiocb
 * @param error_status
 * @param transfer_count
 * @retval 1  AIO completed
 * @retval 0  not completed yet
 * @brief AIO가 completed되었는지를 체크
 */
int
get_result_status (struct aiocb *aiocb, int *error_status, size_t *transfer_count)
{
    ssize_t op_return;
    transfer_count = 0;

#ifdef PROACTOR_DEBUG
    printf("get_result_status\n");
#endif
 
    // Get the error status of the aio_ operation.
    *error_status  = aio_error (aiocb);
    if (*error_status == EINPROGRESS)
        return 0;  // not completed

    op_return = aio_return (aiocb);
    if (op_return > 0){
        transfer_count = (size_t *) op_return;

        // Successful.
#ifdef PROACTOR_DEBUG
        fprintf(stderr,"nbytes : %d\n", op_return);
        write(STDERR_FILENO, (char *)aiocb->aio_buf, op_return);
        printf("\n");
#endif       

    }
    return 1; // completed
}

/**
 * @author 박학선
 * @param idx
 * @param transfer_count
 * @param error_status
 * @brief completed된 aiocb_list의 callback handler를 호출
 */
void
application_specific_code(size_t idx, int transfer_count, int error_status)
{
    void *handler, *data;

#ifdef PROACTOR_DEBUG
    printf("application_specific_code\n");
#endif

    ///    media interface에서 aio_read request를 던진 caller의 handler function으로 callback
    result_list[idx]->hndlr(result_list[idx]->data);
}


/////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////REQEUEST////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////
/**
 * @author 박학선
 * @param file_fd
 * @param size
 * @param offset
 * @param buf
 * @param data
 * @param hndlr_ftn
 * @param priority
 * @param op
 * @brief media에서 asynchronous read를 요청하기 위해 호출하는 함수.
 *           실제로는 이 파일안에 정의되어 있지는 않음. 단지 테스트를 위해서...
 */
int
si_read_req(int file_fd, int size, int offset, void *buf, void *data, void *hndlr_ftn, int priority, Opcode op)
{
    posix_asynch_result *result;
    struct aiocb * aiocb;

    int ret_val;

   
    aiocb = (struct aiocb*)malloc(sizeof(struct aiocb));
   
    aiocb->aio_fildes = file_fd;
    aiocb->aio_offset = offset;
    aiocb->aio_nbytes =  size;
    aiocb->aio_buf = buf;
    aiocb->aio_reqprio = priority;

    result = (struct posix_asynch_result*)malloc(sizeof(struct posix_asynch_result));
    result->aiocb = aiocb;
    result->hndlr = hndlr_ftn;
    result->data = data;

    ret_val =  issue_aio_calls(result, op);
    if(ret_val == -1)
        free(result);

    return ret_val;
}

/**
 * @author 박학선
 * @param result
 * @param op
 * @retval 0 started OK
 * @retval 1 OS AIO queue overflow
 * @retval -1 do not started
 * @brief System Interface(si_read_req())에서 Proactor에
 *       read를 요청하기 위해 사용!!
 */
int
issue_aio_calls (posix_asynch_result *result, Opcode op)
{
    struct aiocb * aiocb;
    int ret_val;
  
    printf("issue_aio_calls\n");

    aiocb = result->aiocb;

    ret_val = (aiocb_list_cur_size >= aiocb_list_max_size) ? -1 : 0;
    if (ret_val != 0){   // No free slot
        errno = EAGAIN;
        return -1;
    }
   
    if (aiocb == 0) // Just check the status of the list
        return ret_val;

   
    // Save operation code in the aiocb
    switch (op){
        case READ:
            aiocb->aio_lio_opcode = LIO_READ;
            break;
        case WRITE:
            aiocb->aio_lio_opcode = LIO_WRITE;
            break;
        default:
            fprintf(stderr, "start_aio: Invalid operation code\n");
    }

    // Find a free slot and store.
    ssize_t slot = allocate_aio_slot (aiocb);
    if (slot < 0)
       return -1;
    size_t index = (size_t) slot;

    // setup OS notification methods for this aio
    // store index!!, not pointer in signal info
    aiocb->aio_sigevent.sigev_notify = SIGEV_SIGNAL;   
    aiocb->aio_sigevent.sigev_signo = SIGRTMIN;        //Proactor에서 사용하는 signal
    aiocb->aio_sigevent.sigev_value.sival_int = (int)index; //시그널이 발생했을 때 사용할 index


    result_list[index]= result;   //Store result ptr anyway
    aiocb_list_cur_size++;

    ret_val = execute_aio_calls (aiocb);
#ifdef PROACTOR_DEBUG
    printf("ret_val from execute_aio_calls : %d\n", ret_val);
#endif
    switch (ret_val){
        case 0:     // started OK
            aiocb_list[index] = aiocb;      //요청을 처리한 aiocb를 aiocb_list에 저장해 놓았다가 signal_handler에서 처리
            return 0;
        case 1:     // OS AIO queue overflow
            num_deferred_aiocb ++;
            return 0;

        default:    // Invalid request, there is no point
            break;    // to start it later
    }
    result_list[index] = 0;
    aiocb_list_cur_size--;
    return -1;
}


/**
 * @author 박학선
 * @param aiocb
 * @retval 0 AIO was started successfully
 * @retval 1 AIO was not started, OS AIO queue overflow
 * @retval -1 AIO was not started, other errors
 * @brief 파일의 미디어 트랙에서 aio_read, aio_write를 실행!!
 */
int
execute_aio_calls (struct aiocb * aiocb)
{
    int ret_val;

    // Start IO
    switch (aiocb->aio_lio_opcode ){
        case LIO_READ :
            ret_val = aio_read (aiocb);
            break;
        case LIO_WRITE :
            ret_val = aio_write (aiocb);
            break;
        default:
            ret_val = -1;
            break;
    }

    if (ret_val == 0){
        printf("aio_call excuted..\n");
        num_started_aio++;
    }
    else{ // if (ret_val == -1)
        if (errno == EAGAIN || errno == ENOMEM)  //Ok, it will be deferred AIO
            ret_val = 1;
    }
    return ret_val;
}

/**
 * @author 박학선
 * @param aiocb
 * @retval retval > 0 allocated aiocb_list's slot
 * @retval -1   no free slot
 * @brief  이 시스템에서 관리하는 aiocb_list의 free slot을 반환한다.
 */
ssize_t allocate_aio_slot(struct aiocb * aiocb)
{
    size_t i = 0;
    //try to find free slot as usual, starting from 0
    for (i = 1; i < aiocb_list_max_size; i++)
        if (aiocb_list[i] == 0)
            break;
#ifdef PROACTOR_DEBUG
    printf("aiocblist_free_index found : %d\n", i);
#endif

    if (i >= aiocb_list_max_size){
        fprintf(stderr, "allocate_aio_slot internal error\n");
        return -1;
    }

    return (ssize_t) i;
}

++++++++++++++++++++++++++
+ Makefile
++++++++++++++++++++++++++

.SUFFIXES: .c .o

CC= gcc
CFLAGS= -Wall -c -g
AR= ar
export CC AR CFLAGS

OBJS= posix_proactor.o
SUBDIR= test


TARGET= libsys_i.a

all: $(TARGET)

$(TARGET): $(OBJS)
    $(AR) -r $(TARGET) $(OBJS)
clean:
    $(RM) -rf *.o *.a

new:
    $(MAKE) clean
    $(MAKE)

subdirs:
    @for i in $(SUBDIR); do (cd $$i && $(MAKE)); done
.c.o:
    $(CC) $(CFLAGS) $<

ctags:
    ctags -R .


 

반응형

'[Develope] > Network' 카테고리의 다른 글

TCP State Diagram  (0) 2008.07.28
posix proactor library test  (0) 2008.07.01
netstat  (0) 2008.03.17
Aptana  (0) 2008.02.21
Protocol-Map  (0) 2008.01.24