Example #1
0
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;
    }
}
Example #2
0
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;
		}