-
Notifications
You must be signed in to change notification settings - Fork 16
io 모듈
io 모듈은 연결이 수립된 socket file descriptor를 통해 send() system call과 recv() system call을 호출하여 arcus-memcached 서버와 실질적인 통신을 담당합니다.
io 모듈의 진입은 memcached_io_write() 함수, memcached_io_read() 함수 등으로 이뤄집니다.
send() system call을 호출하기 위해 진입점이 되는 함수로는 memcached_io_write() 함수와 memcached_io_writev() 함수가 있습니다.
memcached_io_write() 함수는 byte array를 매개변수로 받고, memcached_io_writev()는 vector 객체의 array를 매개변수로 받습니다.
내부 동작은 두 함수 모두 _io_write() 함수를 사용합니다.
memcached_io_write() 함수는 byte array를 곧바로 _io_write() 함수에 전달하고 memcached_io_writev() 함수는 vector 객체 array를 반복문으로 순회하며 vector 객체에 담긴 byte array를 _io_write() 함수에 전달합니다.
_io_write() 함수는 byte array를 8KB의 write buffer 단위로 잘라 io_flush() 함수를 호출하도록 합니다.
-
send() system call을 호출하는 함수입니다.
-
send() system call을 호출했을 때 socket의 read buffer가 가득 차서 실패할 경우 repack_input_buffer() 함수를 호출하여 read buffer를 임시적으로 다른 buffer에 옮겨두고 재시도합니다.
-
다른 buffer도 가득 차 있을 경우 process_input_buffer() 함수를 호출합니다. process_input_buffer() 함수에서는 arcus-memcached response에 대한 콜백 함수가 지정되어 있을 경우 read buffer를 소비하고 콜백을 호출합니다.
-
다른 buffer도 가득 차 있고 response 콜백 함수도 지정되어 있지 않은 경우 io_wait() 함수를 호출합니다.
-
io_wait() 함수는 connect 모듈의 connect_poll() 함수와 유사하게 동작하여 poll() system call을 통해 socket이 write 가능한 상태인지 확인합니다.
-
connect_poll() 함수는 socket이 write 가능한 상태인지만을 확인하는 반면, io_wait() 함수는 send() system call을 사용하는 상황이라면 socket이 write 가능한지를 확인하고 recv() system call을 사용하는 상황이라면 socket이 read 가능한지를 확인합니다.
-
send() system call에서 socket의 read buffer가 가득 찬 경우 외에 다른 실패 상황, 혹은 io_wait() 함수에서 poll() system call이 실패한 상황에서는 memcached_quit_server() 함수를 호출하여 read buffer와 write buffer를 비우고 socket 연결을 해제합니다.
recv() system call을 호출하기 위해 진입점이 되는 함수로는 memcached_io_read() 함수와 memcached_io_readline() 함수가 있습니다.
memcached_io_readline() 함수는 read buffer에서 \n
으로 끝나는 한 라인을 읽기 위해 사용되며, read buffer가 비워져 있을 경우 내부적으로 memcached_io_read() 함수를 사용합니다.
memcached_io_read() 함수는 read buffer가 비어 있으면 _io_fill() 함수를 호출하여 read buffer를 채웁니다.
read buffer가 비어 있지 않으면 read buffer의 크기인 8KB 단위로 반복하여 read buffer를 소비해서 매개변수의 byte array에 데이터를 memcpy() system call로 복제합니다.
recv() system call을 호출하는 함수입니다. read buffer의 크기인 8KB 단위로 recv() system call을 호출합니다.
recv() system call에서 EINTR 에러가 날 경우 재시도를 합니다.
ETIMEDOUT, EWOULDBLOCK, EAGAIN, ERESTART인 경우 io_wait() 함수를 통해 socket이 read 가능한 상태인지 확인합니다.
io_wait() 함수에서 성공하면 recv() system call을 재시도하고, 실패할 경우엔 연산 수행 중으로 마크한 뒤 _io_fill() 함수를 종료합니다.
EINTR 에러나 io_wait() 함수를 호출하는 에러를 제외하면 memcached_quit_server() 함수를 통해 read buffer와 write buffer를 비우고 socket 연결을 해제합니다.