- #include <pthread.h>
- #include <iostream>
- #include <errno.h>
- #include <sys/types.h>
- #include <sys/socket.h>
- #include <semaphore.h>
- #include <netinet/in.h>
- #include <arpa/inet.h>
- #include <iterator>
- #include "connection.hpp"
- #include "table.hpp"
- const int NET_BUFFER_NUMBER=1024;
- const int THREAD_BUFFER_NUMBER=10;
- const int WORK_THREAD_NUMBER=100;
- const int THREAD_STACK_SIZE=PTHREAD_STACK_MIN*3;
- const int WAIT_TIME=3;
- //this struct for thread deal socket need data
- struct data_buffer
- {
- char data_array[NET_BUFFER_NUMBER];
- int data_len;//data_array actual length
- struct sockaddr_in src_socket;
- const data_buffer& operator=(const data_buffer& rhs)
- {
- data_len = rhs.data_len;
- for (int i=0; i<data_len; i++)
- {
- data_array[i] = rhs.data_array[i];
- }
- src_socket = rhs.src_socket;
- return rhs;
- }
- };
- //main thread and dispatch thread
- struct data_buffer globe_buffer[THREAD_BUFFER_NUMBER];
- int globe_actual_len;//globe_buffer actual len
- pthread_mutex_t main_mutex;
- pthread_cond_t main_cond;
- bool can_read;
- //use threads pool manage
- //pthread_mutex_t mutex[WORK_THREAD_NUMBER];
- pthread_mutex_t mutex;
- pthread_cond_t cond;
- bool is_start[WORK_THREAD_NUMBER];
- struct thread_arg
- {
- const struct data_buffer* ptr_data;
- const int* ptr_work_len;
- int self_index;//is_start array index,also mutex array
- };
- void* thread_function(void* args)
- {
- //because of after args will changes value
- struct thread_arg* ptr_arg = (struct thread_arg*)args;
- int index = ptr_arg->self_index;
- const struct data_buffer* ptr_src_data = ptr_arg->ptr_data;
- const int* ptr_src_work_len = ptr_arg->ptr_work_len;
- sqlpp::Connection conn("mysql", "127.0.0.1", "root", "yi_jun_jun");
- if (!conn.is_open())
- {
- perror("database connection failure");
- pthread_exit(NULL);
- }
- sqlpp::Table table("select * from user", conn);
- int my_socket = socket(AF_INET, SOCK_DGRAM, 0);
- if (my_socket == -1)
- {
- perror("create my socket failure in thread function");
- pthread_exit(NULL);
- }
- struct data_buffer deal_data[THREAD_BUFFER_NUMBER];
- int work_count=0;
- while (true)
- {
- pthread_mutex_lock(&mutex);
- while (!is_start[index])
- {
- pthread_cond_wait(&cond, &mutex);
- }
- work_count = *ptr_src_work_len;
- for (int j=0; j<work_count; j++)
- {
- deal_data[j] = ptr_src_data[j];//copy self will deal data
- }
- pthread_mutex_unlock(&mutex);
- //copy the same data to client
- for (int i=0; i<work_count; i++)
- {
- table.download();
- sqlpp::Table::rows rows = table.get_rows<sqlpp::Table::row>();
- int k = random()%rows.size();
- std::copy(rows[k]["User"].begin(),rows[k]["User"].end(), deal_data[i].data_array);
- deal_data[i].data_len = rows[k]["User"].size();
- sendto(my_socket, deal_data[i].data_array, deal_data[i].data_len, 0, (sockaddr*)&(deal_data[i].src_socket), sizeof(deal_data[i].src_socket));
- }
- work_count = 0;
- is_start[index] = false;//notice self is idle
- }//end of while
- close(my_socket);
- return NULL;
- }
- bool create_threads(int create_count, struct data_buffer data_args[], int* ptr_len)
- {
- pthread_attr_t attr;
- std::size_t stack_size;
- struct thread_arg args;
- args.ptr_data = data_args;
- args.ptr_work_len = ptr_len;
- pthread_attr_init(&attr);
- pthread_attr_setstacksize(&attr, THREAD_STACK_SIZE);
- for (int i=0; i<WORK_THREAD_NUMBER; i++)
- {
- pthread_t ptd;
- args.self_index = i;
- if (pthread_create(&ptd, &attr, &thread_function, (void*)&args) != 0)
- {
- perror("create failure");
- return false;
- }
- }
- return true;
- }
- void* dispatch(void* args)
- {
- struct data_buffer temp[THREAD_BUFFER_NUMBER];
- int work_len = 0;
- if (pthread_mutex_init(&mutex, NULL) != 0)
- {
- perror("init lock failure in dispatch function");
- pthread_exit(NULL);
- }
- if (pthread_cond_init(&cond, NULL) != 0)
- {
- perror("inin cond failure");
- pthread_exit(NULL);
- }
- for (int i=0; i<WORK_THREAD_NUMBER; i++)
- {
- is_start[i] = false;//block all work thread
- }
- if (!create_threads(WORK_THREAD_NUMBER, temp, &work_len))
- {
- perror("create threads failure");
- pthread_exit(NULL);
- }
- while (true)
- {
- pthread_mutex_lock(&main_mutex);
- while (!can_read)
- {
- pthread_cond_wait(&main_cond, &main_mutex);
- }
- for (int i=0; i<globe_actual_len; i++)
- {
- temp[i] = globe_buffer[i];
- }
- work_len = globe_actual_len;
- //dispatch work start, if not idle thread, it will be block.
- while (true)
- {
- int j;
- for (j=0; j<WORK_THREAD_NUMBER; j++)
- {
- //find one idle thread, no need lock
- if (!is_start[j])
- {
- //signal this thread start work
- pthread_mutex_lock(&mutex);
- is_start[j] = true;
- pthread_cond_broadcast(&cond);
- pthread_mutex_unlock(&mutex);
- //std::cout<<"find an idle thread:"<<j<<std::endl;
- break;//only break for
- }
- }
- if (j<WORK_THREAD_NUMBER)//find one idle thread and start it
- {
- //std::cout<<"find an idle thread:"<<j<<std::endl;
- break;//break dispatch while
- }
- }//end of find idle
- can_read = false;
- pthread_mutex_unlock(&main_mutex);
- }//end of dispatch
- pthread_mutex_destroy(&mutex);
- pthread_cond_destroy(&cond);
- }
- int main(int argc, char* argv[])
- {
- srand((unsigned long)time(NULL));
- int listen_socket = socket(PF_INET, SOCK_DGRAM, 0);
- if (listen_socket == -1)
- {
- perror("create listen socket failure");
- return -1;
- }
- //sizeof(sockaddr_in) = sizeof(sockaddr)
- //sockaddr purose = sockaddr_in purose
- struct sockaddr_in addr;
- bzero(&addr, sizeof(sockaddr_in));
- addr.sin_family = PF_INET;
- addr.sin_port = htons(1120);
- addr.sin_addr.s_addr = inet_addr("127.0.0.1");
- if (bind(listen_socket, (sockaddr*)&addr, sizeof(sockaddr_in)) == -1)
- {
- perror("bind listen_socket failure");
- close(listen_socket);
- return -1;
- }
- timeval timeout = {WAIT_TIME,0};
- if (setsockopt(listen_socket, SOL_SOCKET, SO_RCVTIMEO, (char *)&timeout, sizeof(struct timeval)) == -1)
- {
- perror("set time out failure");
- close(listen_socket);
- return -1;
- }
- if (pthread_mutex_init(&main_mutex, NULL) != 0)
- {
- perror("main_mutex init failure");
- close(listen_socket);
- return -1;
- }
- if (pthread_cond_init(&main_cond, NULL) != 0)
- {
- perror("main_cond init failure");
- close(listen_socket);
- return -1;
- }
- //create distpach thread
- can_read = false;
- globe_actual_len = 0;
- pthread_t pt;
- if (pthread_create(&pt, NULL, &dispatch, NULL) != 0)
- {
- perror("create dispatch thread failure");
- close(listen_socket);
- return -1;
- }
- //main receive loop
- char buffer[NET_BUFFER_NUMBER];
- bzero(buffer, sizeof(buffer));
- struct sockaddr_in client;
- int actual_len=0;
- socklen_t sock_len = sizeof(sockaddr_in);
- struct data_buffer temp[THREAD_BUFFER_NUMBER];
- int index=0;
- while (true)
- {
- if ((actual_len=recvfrom(listen_socket, buffer, NET_BUFFER_NUMBER, 0, (sockaddr*)&client, &sock_len)) <= 0)
- {
- //maybe it is timeout,check exists old socket not dispatch
- if ((index>0) && (index<=THREAD_BUFFER_NUMBER))
- {
- pthread_mutex_lock(&main_mutex);
- globe_actual_len = index;
- for (int i=0; i<globe_actual_len; i++)
- {
- globe_buffer[i] = temp[i];
- }
- index = 0;
- can_read = true;
- pthread_cond_broadcast(&main_cond);
- pthread_mutex_unlock(&main_mutex);
- }
- continue;
- }
- else
- {
- if ( index >= THREAD_BUFFER_NUMBER)
- {
- pthread_mutex_lock(&main_mutex);
- globe_actual_len = THREAD_BUFFER_NUMBER;
- for (int i=0; i<globe_actual_len; i++)
- {
- globe_buffer[i] = temp[i];
- }
- index = 0;
- can_read = true;
- pthread_cond_broadcast(&main_cond);
- pthread_mutex_unlock(&main_mutex);
- }
- temp[index].data_len = actual_len;
- for (int k=0; k<actual_len; k++)
- {
- temp[index].data_array[k] = buffer[k];
- }
- temp[index++].src_socket = client;
- }
- }
- pthread_mutex_destroy(&main_mutex);
- pthread_cond_destroy(&main_cond);
- return 0;
- }