bool Test1() { CKl_BasicBuffer<ULONG> TestBuffer( 100 ); TestBuffer.Zeromem(); TestBuffer[4] = 1; ULONG m = TestBuffer[4]; ULONG n = TestBuffer[3]; return true; }
/** * Send is calles from CEMSocket like for a usual TCP socket, * The function copyes the data to the socket intern upload buffer and splits tham in segments, * every segment gets an uniqie segment number. * * Synchronisation note: This function locks the Uplaod Buffer Mutex. * * @param lpBuf: pointer on the data buffer to read. * * @param nBufLen: buffer length. * * @param nFlags: unused yet. */ int CNatSocket::Send(const void* lpBuf, int nBufLen, int /*nFlags*/) { // NOTE: *** This function is invoked from a *different* thread! //T_TRACE("%s: used buffer size=%d, max size=%d\n", __FUNCTION__, // m_uUploadBufferSize + (unsigned)nBufLen, // MAX_BUF_SIZE); ASSERT(m_UserModeTCPConfig); if(m_UserModeTCPConfig == NULL || m_UploadBuffer.GetCount()> MAX_UPLOAD_SEGS || m_dwConnAskNumber==0) { SetLastError(WSAEWOULDBLOCK); //T_TRACE("send buffer overflow"); return SOCKET_ERROR; } //if(MAX_BUF_SIZE < m_uUploadBufferSize) return 0; uint32 toSend = nBufLen;//min((unsigned)nBufLen, m_UserModeTCPConfig->MaxUploadBufferSize - m_uUploadBufferSize); //m_UpLocker.Lock(); CList<sTransferBufferEntry*, sTransferBufferEntry*> EntryLstToSend; uint32 Sent = 0; while(toSend > Sent) { uint32 uSequenceNr; sTransferBufferEntry* BufferEntry; POSITION pos = m_UploadBuffer.GetTailPosition();//.GetHeadPosition(); // Note: on a CRBMap this points always on the object with the lowest key, // bu becouse we rever the map keys (mapkey = UINT_MAX-key) if(pos) { // it points always on the entry with the highest Sequence Number BufferEntry = m_UploadBuffer.GetValueAt(pos); if(BufferEntry->uSize < m_UserModeTCPConfig->MaxSegmentSize && BufferEntry->uSendCount == 0) { // if this segment is not full and wsn't already sent, fill it up uSequenceNr = 0; } else { // create a new segment uSequenceNr = ++m_uMaxSendSequenceNr; BufferEntry = NULL; } } else { // no pending segments uSequenceNr = ++m_uMaxSendSequenceNr; BufferEntry = NULL; } // We Split the data into segments uint32 Size = min((toSend - Sent),m_UserModeTCPConfig->MaxSegmentSize); try { if(BufferEntry == NULL) { BufferEntry = new sTransferBufferEntry(Size, (const BYTE*)lpBuf+Sent, uSequenceNr); m_UploadBuffer.SetAt(uSequenceNr, BufferEntry); } else { // to save overhead we try to send only full segments when there are some not full bufferes Size = min(Size, (uint32)abs(int(m_UserModeTCPConfig->MaxSegmentSize - BufferEntry->uSize))); uint32 tmpSize = BufferEntry->uSize; BYTE* tmpBuffer = BufferEntry->pBuffer; BufferEntry->uSize += Size; BufferEntry->pBuffer = new BYTE[BufferEntry->uSize]; memcpy(BufferEntry->pBuffer,tmpBuffer,tmpSize); memcpy((BYTE*)BufferEntry->pBuffer+tmpSize,(const BYTE*)lpBuf+Sent,Size); delete [] tmpBuffer; } } catch(...) { break; } EntryLstToSend.AddTail(BufferEntry); Sent += Size; // increment our send buffer size m_uUploadBufferSize += Size; #ifdef _DEBUG TestBuffer(); #endif } Output(); return Sent; // return the number if bytes we actualy tooken }
// Test the CacheBlock utility object Read() and LastAccessTick(). bool TestCacheBlock() { uint32 offset = 13; uint32 segment_id = 0; uint32 block_size = file_bundle_size_ / 4; CachedReadAccessor::CacheBlockAddress address1(segment_id, 0); uint64 access_tick = 1033; CachedReadAccessor::CacheBlock block1(address1, block_size); // Check the initial access tick TestAssert(block1.LastAccessTick() == 0); block1.SetLastAccessTick(access_tick - 1); TestAssert(block1.LastAccessTick() == (access_tick - 1)); // Test Read // Read request that is contained in 1 block. uint32 request_count = block_size - offset - 10; FileBundleReaderSegment segment(file_pool_, path_base_, segment_names_[segment_id], segment_names_[segment_id], segment_id); std::string buffer; buffer.reserve(block_size); buffer.resize(request_count); char* out_buffer = const_cast<char*>(buffer.data()); // Test read within non-cached (uninitialized) block uint64 stats_bytes_read = 0; uint64 stats_disk_accesses = 0; uint32 read_count = block1.Read(segment, out_buffer, request_count, offset, access_tick++, stats_bytes_read, stats_disk_accesses); TestAssert(block1.LastAccessTick() + 1 == access_tick); TestAssertEquals(stats_bytes_read, static_cast<uint64>(block_size)); TestAssertEquals(stats_disk_accesses, static_cast<uint64>(1)); TestAssertEquals(request_count, read_count); char* expected = test_buffer_ + offset; if (!TestBuffer(out_buffer, expected, read_count, std::string("TestCacheBlock: all data in one non-cached block"))) return false; // Test read from the NOW cached block within the segment. offset = 23; request_count /= 3; buffer.resize(request_count); read_count = block1.Read(segment, out_buffer, request_count, offset, access_tick++, stats_bytes_read, stats_disk_accesses); TestAssertEquals(stats_bytes_read, static_cast<uint64>(block_size)); TestAssertEquals(stats_disk_accesses, static_cast<uint64>(1)); TestAssertEquals(request_count, read_count); expected = test_buffer_ + offset; if (!TestBuffer(out_buffer, expected, read_count, std::string("TestCacheBlock: all data in one cached block"))) return false; // Test a PARTIAL reads from a block (i.e., a request past the block // boundary. // create a new CacheBlock to start with an empty cache. block1 = CachedReadAccessor::CacheBlock(address1, block_size); request_count = 200; buffer.resize(request_count); uint32 expected_read_count = 133; offset = block_size - expected_read_count; // Read from a non-cached block read_count = block1.Read(segment, out_buffer, request_count, offset, access_tick++, stats_bytes_read, stats_disk_accesses); TestAssertEquals(stats_bytes_read, static_cast<uint64>(2*block_size)); TestAssertEquals(stats_disk_accesses, static_cast<uint64>(2)); TestAssertEquals(expected_read_count, read_count); expected = test_buffer_ + offset; if (!TestBuffer(out_buffer, expected, read_count, std::string("TestCacheBlock: partial data in cached block"))) return false; // Read from a cached block read_count = block1.Read(segment, out_buffer, request_count, offset, access_tick++, stats_bytes_read, stats_disk_accesses); TestAssertEquals(expected_read_count, read_count); expected = test_buffer_ + offset; if (!TestBuffer(out_buffer, expected, read_count, std::string("TestCacheBlock: partial data in cached block"))) return false; return true; }
// Test the CachedReadAccessor Pread() method. // This is the main method exposed by CachedReadAccessor. bool TestCachedReadAccessorPread() { uint32 offset = 13; uint32 segment_id = 0; uint32 block_size = file_bundle_size_ / 4; CachedReadAccessor accessor(2, block_size); // Test Read // Read request that is contained in 1 block. uint32 request_count = block_size - offset - 10; FileBundleReaderSegment segment(file_pool_, path_base_, segment_names_[segment_id], segment_names_[segment_id], segment_id); std::string buffer; buffer.reserve(block_size); buffer.resize(request_count); char* out_buffer = const_cast<char*>(buffer.data()); // Test read within a single block // uncached block accessor.Pread(segment, out_buffer, request_count, offset); char* expected = test_buffer_ + offset; if (!TestBuffer(out_buffer, expected, request_count, std::string("TestCachedReadAccessorPread: 1 non-cached block"))) return false; // same block cached read offset *= 2; request_count -= offset; buffer.resize(request_count); accessor.Pread(segment, out_buffer, request_count, offset); expected = test_buffer_ + offset; if (!TestBuffer(out_buffer, expected, request_count, std::string("TestCachedReadAccessorPread: 1 cached block"))) return false; // Test read straddling 2 blocks // uncached 2nd block offset = block_size / 3; request_count = block_size; buffer.resize(request_count); accessor.Pread(segment, out_buffer, request_count, offset); expected = test_buffer_ + offset; if (!TestBuffer(out_buffer, expected, request_count, std::string("TestCachedReadAccessorPread: 2 non-cached blocks"))) return false; // same 2 blocks cached read offset *= 2; request_count -= offset; buffer.resize(request_count); accessor.Pread(segment, out_buffer, request_count, offset); expected = test_buffer_ + offset; if (!TestBuffer(out_buffer, expected, request_count, std::string("TestCachedReadAccessorPread: 2 cached blocks"))) return false; return true; }
int WriteSectionA(const char *filename, const char *section, const CONFENTRY *entrydef, const int size, const int CharType, int maxbufsize) { int ret; int len; int nsize=0; int remaining=maxbufsize; unsigned char **buffer; unsigned char **newbuf; *buffer = (unsigned char*) malloc(maxbufsize); if (*buffer==NULL) return -1; *newbuf = (unsigned char*) malloc(maxbufsize); if (*newbuf==NULL) { free(*buffer); return -1; } if((ret=LoadConfigFileA(filename, buffer, maxbufsize))==0) { /* Convert the buffer from ASCII to UTF-16/32 or vice versa */ if (TestBuffer(*buffer)==ASCII && CharType!=ASCII) expandbuffer((char*)*buffer, ret, (wchar_t*) newbuf); else shrinkbuffer((wchar_t*)*buffer, ret/sizeof(wchar_t),(char*)newbuf); if (CharType==ASCII) { char* result1, *result2; char* begin, *buf, *nbuf; buf = (char*) *buffer; nbuf = (char*) *newbuf; result1 = FindSectionA(buf, section, &begin); if (result1!=NULL) result2 = FindSectionEndA(result1); else { free(*buffer); free(*newbuf); return -1; } /* Copy everything in front of the section */ len = begin - result1; if (remaining-len > 16) strncpy(nbuf, buf, len); remaining -= len; /* Fill buffer */ nsize = PrepareConfigBufferA(entrydef, size, result1, remaining); if (nsize>2) nsize += len; /* Copy the rest of the file */ if (result2!=NULL) { strncpy(nbuf, result2, remaining); } else { /* Write End of File */ strcpy(nbuf,"\\\\END OF FILE//"); nsize+=16; } SaveConfigFileA(filename, nbuf, nsize); } else { } } free(*buffer); free(*newbuf); return ret; }
int ProcessBuffer(unsigned char* buffer, const char *section, const CONFENTRY *entrydef, const int entrycount, int* result, unsigned char* config, int maxbufsize) { int done = FALSE; int len; if (TestBuffer(buffer)==UTF_16) { //TODO Do wide char with the ANSI wchar_t *result1, *result2; result1 = (wchar_t*)buffer; if (section!=NULL) { //TODO Find a solution to the problem of different charactersets //result1 = FindSectionW(result1, section); if (result2==NULL) return NO_SECTION; result2 = FindSectionEndW(result1); if (result2!=NULL) result2[0] = 0; } while(!done) { result1 = wcschr(result1, L'*'); if (result1!=NULL) { //TODO maybe do more checks result1+=1; result2 = wcschr(result1, L'='); if (result2!=NULL) { *result2 = 0; result2++; } else done = TRUE; result1 = ProcessKeyW(entrydef, entrycount, result, result1, result2, config); if (result1==NULL) done = TRUE; } } } else { char *result1, *result2; result1 = (char*)buffer; if (section != NULL) { result1 = FindSectionA(result1, section, NULL); if (result2==NULL) return NO_SECTION; result2 = FindSectionEndA(result1); if (result2 != NULL) result2[0] = 0; } /* Processes every key - a key starts with a * and ends with a = till it reaches the end of the buffer - or there is no data to be processed The key should be in ASCII - for highes compatibility */ while(!done) { result1 = strchr(result1, L'*'); if (result1!=NULL) { //TODO maybe do more checks if (result1[-1]=='\n') { result1+=1; result2 = strchr(result1, L'='); if (result2!=NULL) { *result2 = 0; result2++; } else done = TRUE; result1 = ProcessKeyA(entrydef, entrycount, result, own_strtolower(result1), result2, config); if (result1==NULL) done = TRUE; } else result1++; } else break; } } return 0; }