RuntimeQueue* RuntimeQueue::CreateNewThreadQueue(const CString& name, rqe& ec) { C_PTR_CHECK(context); try { DProfContext _(DTEXT(RQ_API "Creating new task queue")); ShPtr<semaphore_t> sem = MkShared<semaphore_t>(); UqLock temp_lock(sem->start_mutex); sem->running.store(true); /* Spawn the thread */ Thread t(ImpCreateNewThreadQueue, name, &sem); auto tid = ThreadId(t.get_id()).hash(); /* Wait for the RuntimeQueue to be created on the thread */ sem->condition.wait(temp_lock); { Lock _(context->globalMod); context->queueThreads[tid] = std::move(t); context->queueFlags.insert({tid, sem}); } return &context->queues.find(tid)->second; } catch(std::exception const& e) { ec = RQE::ThreadSpawn; ec = e.what(); return nullptr; } }
int decoder::decode_file(ec_io_service_pool& ec_io_service, vector<socket_ptr> ec_socket, request& ori_req, int server_id, string local_ip, string obj_id, unsigned int ori_size, int master_node, int decode_level) { int argc = 2; char* source_path = "I://VS2010_Workspace//for_all_kinds_of_servers//for_all_kinds_of_servers//test.txt"; FILE *fp; char **data; char **coding; int *erasures = NULL; int *erased = NULL; int *matrix = NULL; int *bitmatrix = NULL; //int k, m, w, packetsize, buffersize; int k = ERASURE_CODE_K; int m = ERASURE_CODE_M; int w = ERASURE_CODE_W; int packetsize = ERASURE_CODE_PACKETSIZE; int buffersize = buffer_size; /* If decode_level is 0, ori_size stands for the whole file size, req.content_length stands for the size of one segment If decode_level > 0, ori_size stands for the size of one segment ,req.content_length stands for the size of updated content which could be ignored */ int origsize = ori_size; if (decode_level > 0) origsize = ori_size * k; int i, j; // loop control variables int blocksize; // size of individual files int total; // used to write data, not padding to file int numerased = 0; // number of erased files /* Used to recreate file names */ char *temp; char *cs1, *cs2; char *fname; char *curdir; /* Used to time decoding */ /* Timing variables */ LARGE_INTEGER t1, t2, t3, t4, tc; /* tsec and totalsec are expressed in second */ double tsec, totalsec; /* Initial time counting */ QueryPerformanceFrequency(&tc); totalsec = 0.0; /* Start timing */ QueryPerformanceCounter(&t1); /* Error checking parameters */ curdir = (char *)malloc(sizeof(char)*100); _getcwd(curdir, 100); /* Begin recreation of file names */ cs1 = (char*)malloc(sizeof(char)*strlen(source_path)); cs2 = strrchr(source_path, '/'); if (cs2 != NULL) { cs2++; strcpy(cs1, cs2); } else { strcpy(cs1, source_path); } cs2 = strchr(cs1, '.'); if (cs2 != NULL) { *cs2 = '\0'; } cs2 = (char*)malloc(sizeof(char)*strlen(source_path)); fname = strchr(source_path, '.'); strcpy(cs2, fname); fname = (char *)malloc(sizeof(char*)*(100+strlen(source_path)+10)); /* Allocate memory */ erased = (int *)malloc(sizeof(int)*(k+m)); for (i = 0; i < k + m; i++) erased[i] = 0; erasures = (int *)malloc(sizeof(int)*(k+m)); data = (char **)malloc(sizeof(char *)*k); coding = (char **)malloc(sizeof(char *)*m); int *decoding_matrix; int *dm_ids; decoding_matrix = talloc(int, k*k); dm_ids = talloc(int, k); /* Allocating ends */ if (buffersize != origsize) { for (i = 0; i < k; i++) { data[i] = (char *)malloc(sizeof(char)*(buffersize/k)); } for (i = 0; i < m; i++) { coding[i] = (char *)malloc(sizeof(char)*(buffersize/k)); } blocksize = buffersize/k; } /* ***************************************************************************** */ /* Before preparation has been done and the distributed contact should be on board*/ /* First connect all the accountable nodes, and if the first K node response all well, then conduct a light-weight reconstruction. And here are some points worthy of noticing : If this is a full reconstruct behaviour initiated by the master node ,than it follows the simpliest process. If this is a one-segment reconstruct initiated by one certain data or parity node ,than the server id should be carefully set.*/ /* These to control the http visit sequence and the right servers */ int positive_response = 0; int next_target_server = -1; int loop_control = 0; if (server_id = master_node) { loop_control = k + m; } else if (server_id != master_node) { /* If this a individual segment reconstruction, then connect the server starting from the first data node */ loop_control = k + m - 1; } cout << "Decoding ! " << endl << "Level: " << decode_level << endl << "Connecting all the accountable nodes.." << endl; server::ec_port_lock.lock(); int temp_ec_port = get_random_ec_port(server_id); server::ec_port_lock.unlock(); for (int i = 1; i <= loop_control ; i++) { if (decode_level == i) { continue; } //Connect the next targeted server and send a transmit_data request next_target_server = master_node + i; // Round circle calculation if (next_target_server > STARTING_SERVER_ID + NUMBER_OF_SERVER - 1) { next_target_server -= NUMBER_OF_SERVER; } string remote_ip = ""; map<string, string>::iterator temp_it = server::ip_port_table.find(int_to_string(next_target_server)); if (temp_it != server::ip_port_table.end()) { remote_ip = temp_it->second; } tcp::endpoint remote_end_point(boost::asio::ip::address_v4::from_string(remote_ip.c_str()), next_target_server); tcp::endpoint local_end_point(boost::asio::ip::address_v4::from_string(local_ip.c_str()), temp_ec_port); ec_socket.at(i - 1)->open(local_end_point.protocol()); ec_socket.at(i - 1)->set_option(boost::asio::ip::tcp::socket::reuse_address(true)); ec_socket.at(i - 1)->bind(local_end_point); ec_socket.at(i - 1)->connect(remote_end_point); /* The "ori_req" is the exact same one from client's update, except for the content-length has been modified to whole object size or one segment size depending on decode level, and server_id stands for the target updating server */ request recon_request(ori_req); recon_request.method = RECONSTRUCT_REQUEST; boost::system::error_code err_code; boost::asio::write(*(ec_socket.at(i - 1)), recon_request.header_to_buffers(), err_code); //After ready response , prepare the socket for the transmition from the client boost::asio::socket_base::receive_buffer_size option(blocksize); ec_socket.at(i - 1)->set_option(option); } /* Set the server which initiate this process to erased status */ if (decode_level > 0) { erased[decode_level - 1] = 1; erasures[numerased] = decode_level - 1; numerased ++; } for (int i = 1; i <= k + m ; i++) { /* Confirm all the status and version condition on all related servers */ if (decode_level == i) { continue; } for(;;) { cout << "Checking the ready-or-not status of server: " << master_node + i << endl; boost::asio::streambuf tmp_response; boost::asio::read_until(*(ec_socket.at(i - 1)), tmp_response, "\r\n"); istream response_stream(&tmp_response); string response_string; response_stream >> response_string; if(response_string.find(READY_FOR_RECONSTRUCTION_STATUS) < NO_SUCH_SUBSTRING) { positive_response ++; break; } else if(response_string.find(OBJECT_NOT_FOUND_STATUS) < NO_SUCH_SUBSTRING) { erased[i - 1] = 1; erasures[numerased] = i - 1; numerased ++; break; } else if(response_string.find(TRY_AGAIN_STATUS) < NO_SUCH_SUBSTRING) { //The "ori_req" is the exact same one from client's update, and server_id stands for the target updating server request recon_request_again(ori_req); recon_request_again.method = RECONSTRUCT_REQUEST; boost::system::error_code err_code; boost::asio::write(*(ec_socket.at(i - 1)), recon_request_again.header_to_buffers(), err_code); } } #pragma region light_weight_reconstruct if ((positive_response == ERASURE_CODE_K) && (i == ERASURE_CODE_K) && (decode_level == 0)) { /* It means the K data node is normal, light weight reconstruction could be executed, and it's totally ok to happen entirely in this for-loop. And the last handshake-like communication is send in a reply way but not a request way */ /* If decode_level isn't equal to 0 ,then this for-loop is just for building connection */ cout << "A light weight reconstruction is being conducting !!!!!!!" << endl; /* Inform the M nodes that they could take a rest */ for (int ec_count = ERASURE_CODE_K; ec_count < ERASURE_CODE_K + ERASURE_CODE_M ; ec_count ++) { boost::asio::streambuf tmp_response; boost::asio::read_until(*(ec_socket.at(ec_count)), tmp_response, "\r\n"); boost::system::error_code err_code; reply tmp_reply; tmp_reply.server_status = MISSION_ABORT_STATUS; boost::asio::write(*(ec_socket.at(ec_count)), tmp_reply.simple_ready_buffers(), err_code); } for (int ec_count = 0; ec_count < ERASURE_CODE_K ; ec_count ++) { boost::system::error_code err_code; reply tmp_reply; tmp_reply.server_status = CALL_FOR_LIGHT_WEIGHT_RECONSTRUCT_STATUS; boost::asio::write(*(ec_socket.at(ec_count)), tmp_reply.simple_ready_buffers(), err_code); } /* Open the local path to get ready for the overwritting */ string local_path = return_full_path(ori_req.obj_id); string locking_file = get_locking_file_path(local_path); boost::interprocess::file_lock temp_lock(locking_file.c_str()); temp_lock.lock(); ofstream output_for_trans(local_path.c_str(), ios::out | ios::binary); for(int ec_count = 0; ec_count < ERASURE_CODE_K; ec_count ++) { unsigned int per_receive = 0; unsigned int tmp_count = 0; char* for_recv = new char[RECEIVE_BUFFER_SIZE]; cout << endl << "Now collecting sub data block : " << ec_count + 1 << " with the size of" << ori_req.content_length << endl; for(;;) { //per_receive = boost::asio::read(socket_, boost::asio::buffer(for_recv, RECEIVE_BUFFER_SIZE)); per_receive = (unsigned int)recv(ec_socket.at(ec_count)->native_handle(), for_recv, RECEIVE_BUFFER_SIZE, 0); if (per_receive <= 0 && tmp_count > 0) { cout << ori_req.obj_id << "Per_receive is ZERO !!! Receiving quits !!!Total amount: " << tmp_count << endl; break; } if (per_receive <=0 && tmp_count <= 0) { cout << "Something realy really weired happens!" << endl; cin >> tmp_count; break; } tmp_count += per_receive; cout << "Accumulated received size: " << tmp_count << endl; output_for_trans.write(for_recv, per_receive); output_for_trans.flush(); /* Cause the content_length in ori_req is equal to the size of one data segment which is formed by the data node in update request Therefore, the whole object reconstruction needs the original size .*/ if (tmp_count >= ori_req.content_length) { break; } } delete []for_recv; } output_for_trans.close(); temp_lock.unlock(); return 0; }