Example #1
0
int RTFileData::GetData(tagFileResponse * stResponse, char * buf, int & buflen, tagGetDataParam * pParam)
{
	unsigned long		nsize, ret, readsize, rret;
	int					i;
	int					recordsize;
	char			*	buf1 = buf;

	unsigned long		stDateTime;
	int					roffset;
	MFile				stFile;
	MDateTime			stTmpTime;

	stResponse->nFlag = 0;

	//从文件中获得数据
	if(stFile.OpenRead(pParam->Name) != 1)
	{
		return FLAG_NO_FILE;
	}

	if(stFile.LockFile(0, stFile.GetFileLength()) != 1)
	{
		return FLAG_SERVER_RETRY;
	}

	pParam->stCreateTime = stFile.GetCreateDateTime();
	pParam->nFileSize = stFile.GetFileLength();
	stTmpTime = stFile.GetUpdateDateTime();

	if(stTmpTime > pParam->stUpdateTime)
	{
		pParam->stUpdateTime = stTmpTime;
		if(!pParam->inCall)
		{
			stFile.UnLockFile(0, stFile.GetFileLength());
			return FLAG_CHANGED;
		}
	}
	pParam->stUpdateTime = stTmpTime;

	switch(pParam->updatemode)
	{
	case UPDATEMODE_DBF:
		if(stResponse->stOffsetTime != -1)
		{
			ret = pParam->Dbf.GetData(stResponse, buf, buflen, pParam->inCall, &stFile);

			if(ret < 0)
			{
				return ret;
			}
			else
				break;
		}

	case UPDATEMODE_RECORD:
		if(stResponse->stOffsetTime != -1)
		{
			recordsize = pParam->recordsize;

			if(pParam->inCall)
			{
				roffset = pParam->fileheadsize;
				i = (pParam->nFileSize - pParam->fileheadsize) / recordsize;
				if(i > (buflen / recordsize))
					roffset = pParam->fileheadsize + (i - (buflen / recordsize)) * recordsize;

				stFile.Seek(roffset, 0);
				
				if(stFile.Read((char*)&stDateTime, 4) != 4)
				{
					return FLAG_FILE_ERROR;
				}
				memset(&stResponse->stOffsetTime, 0, sizeof(stResponse->stOffsetTime));
				memcpy(&stResponse->stOffsetTime, &stDateTime, 4);
			}
			else
			{
				roffset = stResponse->nOffset;
				
				if(roffset != -1)
				{
					stFile.Seek(roffset, 0);
					if(stFile.Read((char*)&stDateTime, 4) != 4)
					{
						roffset = -1;
					}
					if(RTFile::IsNewer(&stDateTime, &stResponse->stOffsetTime))
					{
						if(roffset >= pParam->fileheadsize + recordsize)
						{
							stFile.Seek(roffset - recordsize, 0);
							if(stFile.Read((char*)&stDateTime, 4) != 4)
							{
								roffset = -1;
							}
							if(*(unsigned long *)&stDateTime != *(unsigned long *)&stResponse->stOffsetTime)
							{
								roffset = -1;
							}
						}
						else
						{
							roffset = -1;
						}
					}
					else
					{
						roffset = -1;
					}
				}
				
				if(roffset == -1)//无效的偏移量,需要计算偏移, 采用2分法查找。
				{//返回大于指定日期的
					int offset1, offset2;
					offset1 = 0;
					//begin lufubo add 20131008 for只包含文件头时更新失败
					if(stFile.Read((char*)&stDateTime, 4) != 4)
					{
						return FLAG_FILE_ERROR;
					}
					//end lufubo add 20131008 for只包含文件头时更新失败
					offset2 = ((pParam->nFileSize - pParam->fileheadsize) / recordsize) - 1;

					stFile.Seek(pParam->fileheadsize, 0);
					if(stFile.Read((char*)&stDateTime, 4) != 4)
					{
						return FLAG_FILE_ERROR;
					}

					if(RTFile::IsNewer(&stDateTime, &stResponse->stOffsetTime))
					{
						roffset = pParam->fileheadsize;
					}
					else
					{
						stFile.Seek(pParam->nFileSize - ((pParam->nFileSize - pParam->fileheadsize) % recordsize) - recordsize, 0);
						if(stFile.Read((char*)&stDateTime, 4) != 4)
						{
							return FLAG_FILE_ERROR;
						}
						
						if(!RTFile::IsNewer(&stDateTime, &stResponse->stOffsetTime))
						{
							roffset = pParam->nFileSize - ((pParam->nFileSize - pParam->fileheadsize) % recordsize);
						}
						else
						{
							while(1)
							{
								roffset = (offset1 + offset2)/2 * recordsize + pParam->fileheadsize;
								stFile.Seek(roffset, 0);
								if(stFile.Read((char*)&stDateTime, 4) != 4)
								{
									return FLAG_FILE_ERROR;
								}
								if(RTFile::IsNewer(&stDateTime, &stResponse->stOffsetTime))
								{
									roffset -= recordsize;
									stFile.Seek(roffset, 0);
									if(stFile.Read((char*)&stDateTime, 4) != 4)
									{
										return FLAG_FILE_ERROR;
									}
									if(!RTFile::IsNewer(&stDateTime, &stResponse->stOffsetTime))
									{
										roffset += recordsize;
										break;
									}
									else
									{
										offset2 = (offset1 + offset2)/2;
									}
								}
								else if(RTFile::IsNewer(&stResponse->stOffsetTime, &stDateTime))
								{
									roffset += recordsize;
									stFile.Seek(roffset, 0);
									//返回大于指定日期的
									if(stFile.Read((char*)&stDateTime, 4) != 4)
									{
										return FLAG_FILE_ERROR;
									}
									if(RTFile::IsNewer(&stDateTime, &stResponse->stOffsetTime))
									{
										break;
									}
									else if(RTFile::IsNewer(&stResponse->stOffsetTime, &stDateTime))
									{
										offset1 = (offset1 + offset2)/2;
									}
									else
									{
										roffset += recordsize;
										break;
									}
								}
								else
								{
									roffset += recordsize;
									break;
								}
								//if(offset1 == (offset1 + recordsize) / 2)
								 if(offset1 >= offset2)
								{
									return FLAG_FILE_ERROR;
								}
							}
						}
					}
					stResponse->nOffset = roffset;
				}
			}

			nsize = (buflen / recordsize) * recordsize;
			
			if(pParam->nFileSize - roffset <= nsize)
			{
				nsize = pParam->nFileSize - roffset;
				stResponse->nFlag |= FLAG_LAST_PACKET;
			}

			stFile.Seek(roffset, 0);
			readsize = 0;
			while(readsize < nsize){
				rret = stFile.Read(buf1, nsize - readsize);
				if(rret <= 0){
					stResponse->nFlag |= FLAG_LAST_PACKET;
					break;
				}
				readsize += rret;
				buf1 += rret;
			}
			buflen = nsize;
			stResponse->nNextOffset = stResponse->nOffset + nsize;
			memset(&stResponse->stNextDateTime, 0, sizeof(stResponse->stNextDateTime));
			memcpy(&stResponse->stNextDateTime, &buf[nsize - recordsize], 4);
	
			break;

		}

	case UPDATEMODE_FILE:
		nsize = buflen;
		if(pParam->nFileSize - stResponse->nOffset <= nsize)
		{
			nsize = pParam->nFileSize - stResponse->nOffset;
			stResponse->nFlag |= FLAG_LAST_PACKET;
		}
		stFile.Seek(stResponse->nOffset, 0);
		readsize = 0;
		while(readsize < nsize){
			rret = stFile.Read(buf1, nsize - readsize);
			if(rret <= 0){
				stResponse->nFlag |= FLAG_LAST_PACKET;
				break;
			}
			readsize += rret;
			buf1 += rret;
		}
		buflen = nsize;
		stResponse->nNextOffset = stResponse->nOffset + readsize;
		stResponse->stNextDateTime = stResponse->stOffsetTime;

		break;

	default:
		return FLAG_SERVER_ERROR;
	}

	stFile.UnLockFile(0, stFile.GetFileLength());

	return stResponse->nFlag;
}