Ejemplo n.º 1
0
void FileLib::getFileSystemStatus(
		const char8_t *path, FileSystemStatus *status) {
#ifdef _WIN32
	std::wstring pathStr;
	CodeConverter(Code::UTF8, Code::WCHAR_T)(path, pathStr);

	ULARGE_INTEGER availableBytes;
	ULARGE_INTEGER totalBytes;
	ULARGE_INTEGER freeBytes;
	if (!GetDiskFreeSpaceExW(pathStr.c_str(),
			&availableBytes, &totalBytes, &freeBytes)) {
		UTIL_THROW_PLATFORM_ERROR(NULL);
	}

	SYSTEM_INFO systemInfo;
	GetSystemInfo(&systemInfo);

	const DWORD blockSize = systemInfo.dwPageSize;
	status->blockSize_ = blockSize;
	status->fragmentSize_ = blockSize;
	status->blockCount_ = totalBytes.QuadPart / blockSize;
	status->freeBlockCount_ = freeBytes.QuadPart / blockSize;
	status->availableBlockCount_ = availableBytes.QuadPart / blockSize;
#else
	std::string pathStr;
	CodeConverter(Code::UTF8, Code::CHAR)(path, pathStr);

	struct statvfs stvBuf;
	if (statvfs(pathStr.c_str(), &stvBuf) != 0) {
		UTIL_THROW_PLATFORM_ERROR(NULL);
	}

	status->blockSize_ = stvBuf.f_bsize;
	status->fragmentSize_ = stvBuf.f_frsize;
	status->blockCount_ = stvBuf.f_blocks;
	status->freeBlockCount_ = stvBuf.f_bfree;
	status->availableBlockCount_ = stvBuf.f_bavail;

	status->iNodeCount_ = stvBuf.f_files;
	status->freeINodeCount_ = stvBuf.f_ffree;
	status->availableINodeCount_ = stvBuf.f_favail;
	status->id_ = stvBuf.f_fsid;
	status->flags_ = stvBuf.f_flag;
	status->maxFileNameSize_ = stvBuf.f_namemax;
#endif
}
Ejemplo n.º 2
0
/*
*每个socket对应的线程的入口函数,客户端的socket信息处理.主要是区分web端和一般的lmt端
*此线程针对单独的客户端进行处理
*/
void * proClientSocket(void *socketHandle)
{
	bool                bWebType = false;       //是否为web类型
	int					iErrorCount		= 0;	//计数器
	int					i				= 0;
	u_short             iClientID       = CARICCP_MAX_SHORT;

	CSocketHandle		*socket_handle	= ((CSocketHandle *) socketHandle);

	//SOCKET	  sock_client = socket_handle->sock_client;//此socket需要保持起来
	//sockaddr_in addr_client = socket_handle->addr_client;

	//int nNetTimeout=3000;//3秒
	//接收时限,此处设置会影响网络状态的情况判断
	//setsockopt(sock_client,SOL_SOCKET,SO_RCVTIMEO,(char *)&nNetTimeout,sizeof(int));

	//int nZero=0;
	//setsockopt(sock_client,SOL_SOCKET,SO_RCVBUF,(char *)&nZero,sizeof(int));


	char				*pClientIP;
	int					sock_client		= socket_handle->sock_client; //此socket需要保持起来

#if defined(_WIN32) || defined(WIN32)
	struct sockaddr_in	addr_client		= socket_handle->addr_client;
	pClientIP = inet_ntoa(addr_client.sin_addr);  

#else
	struct sockaddr	addr_client	= socket_handle->addr_client;
	//pClientIP  =  /*inet_ntoa(addr_client)*/addr_client.sa_data;
	//要获得client端的ip地址,必须把sockaddr结构强制转换成sockaddr_in结构,因为字节大小是相同的
	pClientIP = inet_ntoa(((struct sockaddr_in *) (&addr_client))->sin_addr);

	//打印16进制的mac地址信息
	//printf("%02x:%02x:%02x:%02x:%02x:%02x\n", 
	//	(unsigned char)addr_client.sa_data[0], 
	//	(unsigned char)addr_client.sa_data[1], 
	//	(unsigned char)addr_client.sa_data[2], 
	//	(unsigned char)addr_client.sa_data[3], 
	//	(unsigned char)addr_client.sa_data[4], 
	//	(unsigned char)addr_client.sa_data[5]); 


#endif

	//及时释放销毁当前socket句柄对象
	CARI_CCP_VOS_DEL(socket_handle);

	switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "+++ begin :Succeed linked with client(IP :%s, socketID :%d).\n", pClientIP, sock_client);

	//定义socket的三元组
	socket3element	clientSocketElement;//是否需要新创建,每个线程独享的临时变量
	initSocket3element(clientSocketElement);
	clientSocketElement.socketClient = sock_client;//保存此socket号
	clientSocketElement.addr = addr_client;

	//方式1: 分配客户端号,此处预先分配好,等待client下发命令查询的时候直接返回即可
	//iClientID = CModuleManager::getInstance()->assignClientID();
	//clientSocketElement.sClientID = iClientID;

	//方式2: client下发命令的时候再进行分配,考虑到以前使用的id号能重用
	//目前采用这种方式

	//把此客户端的socket保存起来
	CModuleManager::getInstance()->saveSocket(clientSocketElement);

	//switch_status_t ret;
	int	recvbytes	= 0;//命名接收处理结果

#ifdef WIN32
#else
	//test 字符转换
	CodeConverter cc = CodeConverter("gb2312","UTF-8");
#endif

	//针对于固定的客户端,对应的线程一直循环处理,设置时限/监测连接是否正常
	while (loopFlag){//使用循环标识控制
		bool bWeb = false;
		char	recvBuf[sizeof(common_CmdReq_Frame)]; 
		memset(recvBuf, 0, sizeof(recvBuf));
		recvbytes = recv(sock_client, recvBuf, sizeof(recvBuf), 0);  //要保证是阻塞模式的,如果客户端(异常)退出,会导致死循环
		
		//网络出现异常,网络中断
		if (-1 == recvbytes) {
			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "--- end  :Disconnect with client (IP :%s, socketID :%d)! \n", 
				pClientIP, 
				sock_client);

			break;
		}
		
		//收到的数据帧错误或客户端退出,或者初始建立连接,此时收到的数据帧的大小都是0
		if (0 == recvbytes) {
			iErrorCount ++;

			//连续收到不正确的数据N次,就要退出循环,重新等待客户端的连接
			if (CARICCP_MAX_ERRRORFRAME_COUNT < iErrorCount) {
				switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "--- end  :Client %s already exited.\n",
					pClientIP);

				iErrorCount = 0;
				break;
			}
			continue;
		}
		//shutdown指令
		if (shutdownFlag){
			break;
		}

		//////////////////////////////////////////////////////////////////////////
		//帧的销毁遵守:谁调用谁负责销毁!!!!!!!!!!!!!!!!!!!
		//关键的命令逻辑处理,逆解析来自客户端的请求帧
		//新建客户端的请求帧,由调用者负责清除
		common_CmdReq_Frame	*clientReqFrame	= CARI_CCP_VOS_NEW(common_CmdReq_Frame);
		initCommonRequestFrame(clientReqFrame);

		//add by xxl 2010-5-5: 需要判断一下此命令是来自web还是一般的client
		if(!bWebType){
			char chHeader = recvBuf[0];
			if ('[' ==chHeader){//判断是否为web发送的命令格式
				bWeb = true;
			}
		}
		//需要重新解析构造请求帧,根据字符串进行转换
		if (bWebType || bWeb){
			string strres = recvBuf,strHeader,strCmd,strParam,strVal,strName;
			int ival =0;
			int index = strres.find_first_of("]");
			strHeader = strres.substr(1,index-1);
			strCmd= strres.substr(index+1);
			
			//1 先构造消息头
			vector<string> resultVec;
			splitString(strHeader, ",", resultVec);
			vector<string>::const_iterator it = resultVec.begin();
			for (;it != resultVec.end(); it++){
				strVal = *it;
				index = strVal.find_first_of("=");
				if (0 < index){
					strName = strVal.substr(0,index);
					strVal  = strVal.substr(index+1);
                    trim(strName);
					trim(strVal);

					//解析关键的参数
					if(isEqualStr("clientID",strName)){
						clientReqFrame->header.sClientID = 0;//web的比较固定
					}
					else if(isEqualStr("modId",strName)){
						clientReqFrame->header.sClientChildModID = stringToInt(strVal.c_str());
					}
					else if(isEqualStr("cmdID",strName)){
						clientReqFrame->body.iCmdCode = stringToInt(strVal.c_str());
					}
					else if(isEqualStr("logUserName",strName)){
						myMemcpy(clientReqFrame->header.strLoginUserName,strVal.c_str(),strVal.length());
					}
				}
			}//end for

			//2 再解析命令名和参数区
			strName = "";
			trim(strCmd);
			index = strCmd.find_first_of(":");
			if (0 < index){
				strName = strCmd.substr(0,index);
				strParam = strCmd.substr(index+1);
			}
			else{
				strParam = strCmd;
			}

			myMemcpy(clientReqFrame->body.strCmdName,strName.c_str(),strName.length());
			myMemcpy(clientReqFrame->param.strParamRegion,strParam.c_str(),CARICCP_MIN(strParam.length(),CARICCP_MAX_LENGTH));

			//3 其他区域的初始化
			clientReqFrame->body.bSynchro = 1;
			clientReqFrame->header.sClientID = 0;//web的比较固定

			//4 重新设置socket,只需要设置一次即可
			if(!bWebType){
				bWebType = true;

				//重新设置clientID号
				CModuleManager::getInstance()->eraseSocket(clientSocketElement.socketClient);
				clientSocketElement.sClientID = 0;//默认情况为CARICCP_MAX_SHORT
				CModuleManager::getInstance()->saveSocket(clientSocketElement);
			}
		}
		else{//一般的lmt,按照以前的方式处理
			memcpy(clientReqFrame,recvBuf,sizeof(recvBuf));
		}
		//add by xxl 2010-5-5 end

		//char strParamRegion[CARICCP_MAX_LENGTH];    
#ifdef WIN32
#else
		//printf("before: %s\n",clientReqFrame->param.strParamRegion);
		////test 字符转换
		//char out[CARICCP_MAX_LENGTH];
		//memset(out,0,sizeof(out));
		//cc.convert(clientReqFrame->param.strParamRegion, CARICCP_MAX_LENGTH,out,CARICCP_MAX_LENGTH);
		//printf("convert: %s\n",out);
		//memset(clientReqFrame->param.strParamRegion,0,sizeof(clientReqFrame->param.strParamRegion));
		//myMemcpy(clientReqFrame->param.strParamRegion,out,sizeof(out));
		//printf("after: %s\n",clientReqFrame->param.strParamRegion);
#endif

		//如果此命令执行时间过长,此处会产生阻塞,当前客户端一直收不到信息!!!!!!!!!
		//如果再另起线程处理,将不能保证命令执行的有序性,所以上述情况还是较少的
		//不必再过多考虑!!!!

		//由请求帧的处理模块(入口函数)负责细节处理
		//帧的销毁遵守:谁调用谁负责销毁!!!!!!!!!!!!!!!!!!!!!!
		CMsgProcess::getInstance()->proCmd(sock_client, clientReqFrame);

		//结果集合的发送不再此处设计,直接放到对应的syncProCmd函数中
		//另外,如果结果集分块发送显示,此处也不适合
		//发送send单独考虑
		//如何保证结果集能正确的发送给对应的客户端呢???

		iErrorCount = 0;
	}//end while(client端循环获得请求帧)

	//如果是强制退出(shutdown命令操作),不需要考虑释放client id号等
	if (!shutdownFlag){
		//先释放client id号
		CModuleManager::getInstance()->releaseClientIDBySocket(sock_client);

		//下面进行清除客户端连接,从保存的容器中清除掉
		CModuleManager::getInstance()->eraseSocket(sock_client);

		//关闭当前客户端的socket
		CARI_CLOSE_SOCKET(sock_client);
	}

	//登录的用户数量减少
	global_client_num--;

	//线程实例清除掉
	//CModuleManager::getInstance()->eraseThrd(sock_client);

	//退出重连接的线程
	//pthread_exit(NULL);

	return NULL;		 //return也会导致本函数所在的线程退出
}