v1.2b9
parent
5b2d493872
commit
4bd6a9acb0
12
VERSION.TXT
12
VERSION.TXT
|
|
@ -1,5 +1,15 @@
|
||||||
NORM Version History
|
NORM Version History
|
||||||
|
|
||||||
|
Version 1.2b9
|
||||||
|
=============
|
||||||
|
- Fixed bugs with NormServerNode::retrieval_pool mgmnt
|
||||||
|
(Thanks to Charlie Davis for tracking these down!!!)
|
||||||
|
- Changed ProtoDispatcher thread stuff so threads
|
||||||
|
(e.g. the NORM API thread) are only actively
|
||||||
|
signaled and interrupted when absolutely necessary
|
||||||
|
- Added support for NORM_TX_QUEUE_VACANCY notification
|
||||||
|
(for NORM_OBJECT_STREAM only at the moment)
|
||||||
|
|
||||||
Version 1.2b8
|
Version 1.2b8
|
||||||
=============
|
=============
|
||||||
- Fixed bug introduced during "alignment" changes
|
- Fixed bug introduced during "alignment" changes
|
||||||
|
|
@ -14,7 +24,7 @@ Version 1.2b7
|
||||||
(might significantly help CC performance
|
(might significantly help CC performance
|
||||||
- Fixed NormServerNode::FreeBuffers() bug which
|
- Fixed NormServerNode::FreeBuffers() bug which
|
||||||
could result in seg fault on remote server timeout
|
could result in seg fault on remote server timeout
|
||||||
or at app shutdown\
|
or at app shutdown
|
||||||
- Fixed bug where tx_sequence count was being
|
- Fixed bug where tx_sequence count was being
|
||||||
incremented for all transmitted messages (The "fix"
|
incremented for all transmitted messages (The "fix"
|
||||||
does not yet address separate increment of messages
|
does not yet address separate increment of messages
|
||||||
|
|
|
||||||
|
|
@ -229,9 +229,9 @@ void NormInstance::Notify(NormController::Event event,
|
||||||
NormStreamObject* stream = static_cast<NormStreamObject*>(object);
|
NormStreamObject* stream = static_cast<NormStreamObject*>(object);
|
||||||
// (TBD) implement silent_client accept differently
|
// (TBD) implement silent_client accept differently
|
||||||
NormObjectSize size = stream->GetSize();
|
NormObjectSize size = stream->GetSize();
|
||||||
// We double the size to prevent unecessary data loss
|
// We double the stream buffer to prevent unecessary data loss
|
||||||
// for our threaded API
|
// for our threaded API
|
||||||
if (!stream->Accept(2*size.LSB()))
|
if (!stream->Accept(size.LSB(), true))
|
||||||
{
|
{
|
||||||
DMSG(0, "NormInstance::Notify() stream accept error\n");
|
DMSG(0, "NormInstance::Notify() stream accept error\n");
|
||||||
notify_pool.Append(n);
|
notify_pool.Append(n);
|
||||||
|
|
@ -897,7 +897,7 @@ NormObjectHandle NormStreamOpen(NormSessionHandle sessionHandle,
|
||||||
if (session)
|
if (session)
|
||||||
{
|
{
|
||||||
NormObject* obj =
|
NormObject* obj =
|
||||||
static_cast<NormObject*>(session->QueueTxStream(bufferSize));
|
static_cast<NormObject*>(session->QueueTxStream(bufferSize, true));
|
||||||
if (obj) objectHandle = (NormObjectHandle)obj;
|
if (obj) objectHandle = (NormObjectHandle)obj;
|
||||||
}
|
}
|
||||||
instance->dispatcher.ResumeThread();
|
instance->dispatcher.ResumeThread();
|
||||||
|
|
|
||||||
|
|
@ -204,6 +204,7 @@ bool NormServerNode::AllocateBuffers(UINT16 segmentSize,
|
||||||
Close();
|
Close();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
memset(retrieval_pool, 0, numData*sizeof(char*));
|
||||||
for (UINT16 i = 0; i < numData; i++)
|
for (UINT16 i = 0; i < numData; i++)
|
||||||
{
|
{
|
||||||
char* s = new char[segmentSize+NormDataMsg::GetStreamPayloadHeaderLength()];
|
char* s = new char[segmentSize+NormDataMsg::GetStreamPayloadHeaderLength()];
|
||||||
|
|
@ -323,9 +324,10 @@ void NormServerNode::HandleCommand(const struct timeval& currentTime,
|
||||||
if (obj && (NormObject::STREAM == obj->GetType()))
|
if (obj && (NormObject::STREAM == obj->GetType()))
|
||||||
{
|
{
|
||||||
NormBlockId blockId = squelch.GetFecBlockId();
|
NormBlockId blockId = squelch.GetFecBlockId();
|
||||||
((NormStreamObject*)obj)->Prune(blockId);
|
static_cast<NormStreamObject*>(obj)->Prune(blockId);
|
||||||
}
|
}
|
||||||
// 3) (TBD) Discard any invalidated objects
|
// 3) (TBD) Go ahead and discard any invalidated objects
|
||||||
|
// (although they will eventually get discarded anyway)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1210,11 +1210,15 @@ void NormObject::HandleObjectMessage(const NormObjectMsg& msg,
|
||||||
#endif // SIMULATE
|
#endif // SIMULATE
|
||||||
// Zeroize the missing segment payload in prep for decoding
|
// Zeroize the missing segment payload in prep for decoding
|
||||||
memset(segment, 0, payloadMax+1);
|
memset(segment, 0, payloadMax+1);
|
||||||
|
server->SetRetrievalLoc(retrievalCount++, nextSegment);
|
||||||
block->SetSegment(nextSegment, segment);
|
block->SetSegment(nextSegment, segment);
|
||||||
}
|
}
|
||||||
else if (!block->GetSegment(nextSegment))
|
else if (!block->GetSegment(nextSegment))
|
||||||
{
|
{
|
||||||
if (!(segment = RetrieveSegment(blockId, nextSegment)))
|
// "tempRetrieval" is set to "true" if the retrieved segment
|
||||||
|
// comes from the "server" temp retrieval pool
|
||||||
|
bool tempRetrieval = false;
|
||||||
|
if (!(segment = RetrieveSegment(blockId, nextSegment, tempRetrieval)))
|
||||||
{
|
{
|
||||||
ASSERT(IsStream());
|
ASSERT(IsStream());
|
||||||
block->SetPending(nextSegment);
|
block->SetPending(nextSegment);
|
||||||
|
|
@ -1227,7 +1231,8 @@ void NormObject::HandleObjectMessage(const NormObjectMsg& msg,
|
||||||
block->DetachSegment(server->GetRetrievalLoc(i));
|
block->DetachSegment(server->GetRetrievalLoc(i));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
server->SetRetrievalLoc(retrievalCount++, nextSegment);
|
if (tempRetrieval)
|
||||||
|
server->SetRetrievalLoc(retrievalCount++, nextSegment);
|
||||||
block->SetSegment(nextSegment, segment);
|
block->SetSegment(nextSegment, segment);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1618,7 +1623,7 @@ void NormStreamObject::StreamAdvance()
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
DMSG(0, "NormStreamObject::StreamAdvance() node>%lu Pending segment repairs (blk>%lu) "
|
DMSG(0, "NormStreamObject::StreamAdvance() warning: node>%lu Pending segment repairs (blk>%lu) "
|
||||||
"delaying stream advance ...\n", LocalNodeId(), (UINT32)block->GetId());
|
"delaying stream advance ...\n", LocalNodeId(), (UINT32)block->GetId());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1904,7 +1909,8 @@ UINT16 NormFileObject::ReadSegment(NormBlockId blockId,
|
||||||
} // end NormFileObject::ReadSegment()
|
} // end NormFileObject::ReadSegment()
|
||||||
|
|
||||||
char* NormFileObject::RetrieveSegment(NormBlockId blockId,
|
char* NormFileObject::RetrieveSegment(NormBlockId blockId,
|
||||||
NormSegmentId segmentId)
|
NormSegmentId segmentId,
|
||||||
|
bool& tempRetrieval)
|
||||||
{
|
{
|
||||||
if (server)
|
if (server)
|
||||||
{
|
{
|
||||||
|
|
@ -1915,6 +1921,7 @@ char* NormFileObject::RetrieveSegment(NormBlockId blockId,
|
||||||
// zeroize remainder for proper decodes
|
// zeroize remainder for proper decodes
|
||||||
if (len < segment_size)
|
if (len < segment_size)
|
||||||
memset(segment+len, 0, segment_size-len);
|
memset(segment+len, 0, segment_size-len);
|
||||||
|
tempRetrieval = true;
|
||||||
return segment;
|
return segment;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
@ -2112,14 +2119,15 @@ UINT16 NormDataObject::ReadSegment(NormBlockId blockId,
|
||||||
return len;
|
return len;
|
||||||
} // end NormDataObject::ReadSegment()
|
} // end NormDataObject::ReadSegment()
|
||||||
|
|
||||||
char* NormDataObject::RetrieveSegment(NormBlockId blockId,
|
char* NormDataObject::RetrieveSegment(NormBlockId blockId,
|
||||||
NormSegmentId segmentId)
|
NormSegmentId segmentId,
|
||||||
|
bool& tempRetrieval)
|
||||||
{
|
{
|
||||||
if (NULL == data_ptr)
|
if (NULL == data_ptr)
|
||||||
{
|
{
|
||||||
DMSG(0, "NormDataObject::RetrieveSegment() error: NULL data_ptr\n");
|
DMSG(0, "NormDataObject::RetrieveSegment() error: NULL data_ptr\n");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
// Determine segment length from blockId::segmentId
|
// Determine segment length from blockId::segmentId
|
||||||
UINT16 len;
|
UINT16 len;
|
||||||
if (blockId == final_block_id)
|
if (blockId == final_block_id)
|
||||||
|
|
@ -2133,13 +2141,29 @@ char* NormDataObject::RetrieveSegment(NormBlockId blockId,
|
||||||
{
|
{
|
||||||
len = segment_size;
|
len = segment_size;
|
||||||
}
|
}
|
||||||
if (len < segment_size)
|
// Determine segment offset from blockId::segmentId
|
||||||
|
NormObjectSize segmentOffset;
|
||||||
|
NormObjectSize segmentSize = NormObjectSize(segment_size);
|
||||||
|
if ((UINT32)blockId < large_block_count)
|
||||||
|
{
|
||||||
|
segmentOffset = large_block_length*(UINT32)blockId + segmentSize*segmentId;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
segmentOffset = large_block_length*large_block_count; // (TBD) pre-calc this
|
||||||
|
UINT32 smallBlockIndex = (UINT32)blockId - large_block_count;
|
||||||
|
segmentOffset = segmentOffset + small_block_length*smallBlockIndex +
|
||||||
|
segmentSize*segmentId;
|
||||||
|
}
|
||||||
|
ASSERT(0 == segmentOffset.MSB());
|
||||||
|
if ((len < segment_size) || (data_max < (segmentOffset.LSB() + len)))
|
||||||
{
|
{
|
||||||
if (server)
|
if (server)
|
||||||
{
|
{
|
||||||
char* segment = server->GetRetrievalSegment();
|
char* segment = server->GetRetrievalSegment();
|
||||||
len = ReadSegment(blockId, segmentId, segment);
|
len = ReadSegment(blockId, segmentId, segment);
|
||||||
memset(segment+len, 0, segment_size-len);
|
memset(segment+len, 0, segment_size-len);
|
||||||
|
tempRetrieval = true;
|
||||||
return segment;
|
return segment;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
@ -2150,22 +2174,7 @@ char* NormDataObject::RetrieveSegment(NormBlockId blockId,
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Determine segment offset from blockId::segmentId
|
tempRetrieval = false;
|
||||||
NormObjectSize segmentOffset;
|
|
||||||
NormObjectSize segmentSize = NormObjectSize(segment_size);
|
|
||||||
if ((UINT32)blockId < large_block_count)
|
|
||||||
{
|
|
||||||
segmentOffset = large_block_length*(UINT32)blockId + segmentSize*segmentId;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
segmentOffset = large_block_length*large_block_count; // (TBD) pre-calc this
|
|
||||||
UINT32 smallBlockIndex = (UINT32)blockId - large_block_count;
|
|
||||||
segmentOffset = segmentOffset + small_block_length*smallBlockIndex +
|
|
||||||
segmentSize*segmentId;
|
|
||||||
}
|
|
||||||
ASSERT(0 == segmentOffset.MSB());
|
|
||||||
ASSERT(data_max >= (segmentOffset.LSB() + len));
|
|
||||||
return (data_ptr + segmentOffset.LSB());
|
return (data_ptr + segmentOffset.LSB());
|
||||||
}
|
}
|
||||||
} // end NormDataObject::RetrieveSegment()
|
} // end NormDataObject::RetrieveSegment()
|
||||||
|
|
@ -2192,6 +2201,7 @@ NormStreamObject::~NormStreamObject()
|
||||||
}
|
}
|
||||||
|
|
||||||
bool NormStreamObject::Open(UINT32 bufferSize,
|
bool NormStreamObject::Open(UINT32 bufferSize,
|
||||||
|
bool doubleBuffer,
|
||||||
const char* infoPtr,
|
const char* infoPtr,
|
||||||
UINT16 infoLen)
|
UINT16 infoLen)
|
||||||
{
|
{
|
||||||
|
|
@ -2216,9 +2226,9 @@ bool NormStreamObject::Open(UINT32 bufferSize,
|
||||||
|
|
||||||
UINT32 blockSize = segmentSize * numData;
|
UINT32 blockSize = segmentSize * numData;
|
||||||
UINT32 numBlocks = bufferSize / blockSize;
|
UINT32 numBlocks = bufferSize / blockSize;
|
||||||
|
|
||||||
// Buffering requires at least 2 blocks
|
// Buffering requires at least 2 blocks
|
||||||
numBlocks = MAX(2, numBlocks);
|
numBlocks = MAX(2, numBlocks);
|
||||||
|
if (doubleBuffer) numBlocks *= 2;
|
||||||
UINT32 numSegments = numBlocks * numData;
|
UINT32 numSegments = numBlocks * numData;
|
||||||
|
|
||||||
if (!block_pool.Init(numBlocks, numData))
|
if (!block_pool.Init(numBlocks, numData))
|
||||||
|
|
@ -2246,7 +2256,9 @@ bool NormStreamObject::Open(UINT32 bufferSize,
|
||||||
read_init = true;
|
read_init = true;
|
||||||
read_index.block = read_index.segment = 0;
|
read_index.block = read_index.segment = 0;
|
||||||
write_index.block = write_index.segment = 0;
|
write_index.block = write_index.segment = 0;
|
||||||
write_offset = read_offset = 0;
|
tx_offset = write_offset = read_offset = 0;
|
||||||
|
write_vacancy = true;
|
||||||
|
posted_tx_queue_vacancy = false;
|
||||||
|
|
||||||
if (!server)
|
if (!server)
|
||||||
{
|
{
|
||||||
|
|
@ -2271,9 +2283,9 @@ bool NormStreamObject::Open(UINT32 bufferSize,
|
||||||
return true;
|
return true;
|
||||||
} // end NormStreamObject::Open()
|
} // end NormStreamObject::Open()
|
||||||
|
|
||||||
bool NormStreamObject::Accept(UINT32 bufferSize)
|
bool NormStreamObject::Accept(UINT32 bufferSize, bool doubleBuffer)
|
||||||
{
|
{
|
||||||
if (Open(bufferSize))
|
if (Open(bufferSize, doubleBuffer))
|
||||||
{
|
{
|
||||||
NormObject::Accept();
|
NormObject::Accept();
|
||||||
return true;
|
return true;
|
||||||
|
|
@ -2287,7 +2299,7 @@ bool NormStreamObject::Accept(UINT32 bufferSize)
|
||||||
void NormStreamObject::Close()
|
void NormStreamObject::Close()
|
||||||
{
|
{
|
||||||
NormObject::Close();
|
NormObject::Close();
|
||||||
write_offset = read_offset = 0;
|
tx_offset = write_offset = read_offset = 0;
|
||||||
NormBlock* b;
|
NormBlock* b;
|
||||||
while ((b = stream_buffer.Find(stream_buffer.RangeLo())))
|
while ((b = stream_buffer.Find(stream_buffer.RangeLo())))
|
||||||
{
|
{
|
||||||
|
|
@ -2418,8 +2430,9 @@ bool NormStreamObject::StreamUpdateStatus(NormBlockId blockId)
|
||||||
} // end NormStreamObject::StreamUpdateStatus()
|
} // end NormStreamObject::StreamUpdateStatus()
|
||||||
|
|
||||||
|
|
||||||
char* NormStreamObject::RetrieveSegment(NormBlockId blockId,
|
char* NormStreamObject::RetrieveSegment(NormBlockId blockId,
|
||||||
NormSegmentId segmentId)
|
NormSegmentId segmentId,
|
||||||
|
bool& tempRetrieval)
|
||||||
{
|
{
|
||||||
NormBlock* block = stream_buffer.Find(blockId);
|
NormBlock* block = stream_buffer.Find(blockId);
|
||||||
if (!block)
|
if (!block)
|
||||||
|
|
@ -2430,10 +2443,10 @@ char* NormStreamObject::RetrieveSegment(NormBlockId blockId,
|
||||||
char* segment = block->GetSegment(segmentId);
|
char* segment = block->GetSegment(segmentId);
|
||||||
if (NULL == segment)
|
if (NULL == segment)
|
||||||
DMSG(0, "NormStreamObject::RetrieveSegment() segment unavailable\n");
|
DMSG(0, "NormStreamObject::RetrieveSegment() segment unavailable\n");
|
||||||
|
tempRetrieval = false;
|
||||||
return segment;
|
return segment;
|
||||||
} // end NormStreamObject::RetrieveSegment()
|
} // end NormStreamObject::RetrieveSegment()
|
||||||
|
|
||||||
|
|
||||||
UINT16 NormStreamObject::ReadSegment(NormBlockId blockId,
|
UINT16 NormStreamObject::ReadSegment(NormBlockId blockId,
|
||||||
NormSegmentId segmentId,
|
NormSegmentId segmentId,
|
||||||
char* buffer,
|
char* buffer,
|
||||||
|
|
@ -2454,8 +2467,33 @@ UINT16 NormStreamObject::ReadSegment(NormBlockId blockId,
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
block->UnsetPending(segmentId);
|
block->UnsetPending(segmentId);
|
||||||
|
|
||||||
char* segment = block->GetSegment(segmentId);
|
char* segment = block->GetSegment(segmentId);
|
||||||
ASSERT(segment != NULL);
|
ASSERT(segment != NULL);
|
||||||
|
|
||||||
|
// Update tx_offset if ((segmentOffset - tx_offset) > 0)
|
||||||
|
UINT32 segmentOffset = NormDataMsg::ReadStreamPayloadOffset(segment);
|
||||||
|
INT32 offsetDelta = segmentOffset - tx_offset;
|
||||||
|
if (offsetDelta > 0) tx_offset = segmentOffset;
|
||||||
|
|
||||||
|
// Only advertise vacancy if stream_buffer.RangeLo() is non-pending _and_
|
||||||
|
// (write_offset - tx_offset) > streamBufferSize
|
||||||
|
if (!write_vacancy)
|
||||||
|
{
|
||||||
|
offsetDelta = write_offset - tx_offset;
|
||||||
|
ASSERT(offsetDelta >= 0);
|
||||||
|
if ((UINT32)offsetDelta < object_size.LSB())
|
||||||
|
{
|
||||||
|
NormBlock* b = stream_buffer.Find(stream_buffer.RangeLo());
|
||||||
|
if (b && !b->IsPending()) write_vacancy = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (write_vacancy && !posted_tx_queue_vacancy)
|
||||||
|
{
|
||||||
|
posted_tx_queue_vacancy = true;
|
||||||
|
session.Notify(NormController::TX_QUEUE_VACANCY, NULL, this);
|
||||||
|
}
|
||||||
|
|
||||||
UINT16 segmentLength = NormDataMsg::ReadStreamPayloadLength(segment);
|
UINT16 segmentLength = NormDataMsg::ReadStreamPayloadLength(segment);
|
||||||
ASSERT(segmentLength <= segment_size);
|
ASSERT(segmentLength <= segment_size);
|
||||||
UINT16 payloadMax = segment_size + NormDataMsg::GetStreamPayloadHeaderLength();
|
UINT16 payloadMax = segment_size + NormDataMsg::GetStreamPayloadHeaderLength();
|
||||||
|
|
@ -2824,6 +2862,14 @@ UINT32 NormStreamObject::Write(const char* buffer, UINT32 len, bool eom)
|
||||||
UINT32 nBytes = 0;
|
UINT32 nBytes = 0;
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
|
INT32 deltaOffset = write_offset - tx_offset;
|
||||||
|
ASSERT(deltaOffset >= 0);
|
||||||
|
if (deltaOffset >= (INT32)object_size.LSB())
|
||||||
|
{
|
||||||
|
write_vacancy = false;
|
||||||
|
DMSG(8, "NormStreamObject::Write() stream buffer full (1)\n", len, eom);
|
||||||
|
break; // (TBD) skip break if push_mode is enabled???
|
||||||
|
}
|
||||||
NormBlock* block = stream_buffer.Find(write_index.block);
|
NormBlock* block = stream_buffer.Find(write_index.block);
|
||||||
if (!block)
|
if (!block)
|
||||||
{
|
{
|
||||||
|
|
@ -2831,28 +2877,32 @@ UINT32 NormStreamObject::Write(const char* buffer, UINT32 len, bool eom)
|
||||||
{
|
{
|
||||||
block = stream_buffer.Find(stream_buffer.RangeLo());
|
block = stream_buffer.Find(stream_buffer.RangeLo());
|
||||||
ASSERT(block);
|
ASSERT(block);
|
||||||
if (push_mode)
|
if (block->IsPending())
|
||||||
{
|
{
|
||||||
NormBlockId blockId = block->GetId();
|
write_vacancy = false;
|
||||||
pending_mask.Unset(blockId);
|
if (push_mode)
|
||||||
repair_mask.Unset(blockId);
|
|
||||||
NormBlock* b = FindBlock(blockId);
|
|
||||||
if (b)
|
|
||||||
{
|
{
|
||||||
block_buffer.Remove(b);
|
NormBlockId blockId = block->GetId();
|
||||||
session.ServerPutFreeBlock(b);
|
pending_mask.Unset(blockId);
|
||||||
}
|
repair_mask.Unset(blockId);
|
||||||
if (!pending_mask.IsSet())
|
NormBlock* b = FindBlock(blockId);
|
||||||
{
|
if (b)
|
||||||
pending_mask.Set(write_index.block);
|
{
|
||||||
stream_next_id = write_index.block + 1;
|
block_buffer.Remove(b);
|
||||||
|
session.ServerPutFreeBlock(b);
|
||||||
|
}
|
||||||
|
if (!pending_mask.IsSet())
|
||||||
|
{
|
||||||
|
pending_mask.Set(write_index.block);
|
||||||
|
stream_next_id = write_index.block + 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
else
|
||||||
else if (block->IsPending())
|
{
|
||||||
{
|
DMSG(4, "NormStreamObject::Write() stream buffer full (2) len:%d eom:%d\n", len, eom);
|
||||||
DMSG(0, "NormStreamObject::Write() stream buffer full (1) len:%d eom:%d\n", len, eom);
|
break;
|
||||||
break;
|
}
|
||||||
}
|
}
|
||||||
stream_buffer.Remove(block);
|
stream_buffer.Remove(block);
|
||||||
block->EmptyToPool(segment_pool);
|
block->EmptyToPool(segment_pool);
|
||||||
}
|
}
|
||||||
|
|
@ -2869,27 +2919,31 @@ UINT32 NormStreamObject::Write(const char* buffer, UINT32 len, bool eom)
|
||||||
{
|
{
|
||||||
NormBlock* b = stream_buffer.Find(stream_buffer.RangeLo());
|
NormBlock* b = stream_buffer.Find(stream_buffer.RangeLo());
|
||||||
ASSERT(b != block);
|
ASSERT(b != block);
|
||||||
if (push_mode)
|
if (b->IsPending())
|
||||||
{
|
{
|
||||||
NormBlockId blockId = b->GetId();
|
write_vacancy = false;
|
||||||
pending_mask.Unset(blockId);
|
if (push_mode)
|
||||||
repair_mask.Unset(blockId);
|
|
||||||
NormBlock* c = FindBlock(blockId);
|
|
||||||
if (c)
|
|
||||||
{
|
{
|
||||||
block_buffer.Remove(c);
|
NormBlockId blockId = b->GetId();
|
||||||
session.ServerPutFreeBlock(c);
|
pending_mask.Unset(blockId);
|
||||||
}
|
repair_mask.Unset(blockId);
|
||||||
if (!pending_mask.IsSet())
|
NormBlock* c = FindBlock(blockId);
|
||||||
|
if (c)
|
||||||
|
{
|
||||||
|
block_buffer.Remove(c);
|
||||||
|
session.ServerPutFreeBlock(c);
|
||||||
|
}
|
||||||
|
if (!pending_mask.IsSet())
|
||||||
|
{
|
||||||
|
pending_mask.Set(write_index.block);
|
||||||
|
stream_next_id = write_index.block + 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
pending_mask.Set(write_index.block);
|
DMSG(4, "NormStreamObject::Write() stream buffer full (3)\n");
|
||||||
stream_next_id = write_index.block + 1;
|
break;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
else if (b->IsPending())
|
|
||||||
{
|
|
||||||
DMSG(0, "NormStreamObject::Write() stream buffer full (2)\n");
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
stream_buffer.Remove(b);
|
stream_buffer.Remove(b);
|
||||||
b->EmptyToPool(segment_pool);
|
b->EmptyToPool(segment_pool);
|
||||||
|
|
@ -2969,6 +3023,8 @@ UINT32 NormStreamObject::Write(const char* buffer, UINT32 len, bool eom)
|
||||||
if (0 != nBytes)
|
if (0 != nBytes)
|
||||||
session.TouchServer();
|
session.TouchServer();
|
||||||
}
|
}
|
||||||
|
if ((0 != nBytes) && posted_tx_queue_vacancy)
|
||||||
|
posted_tx_queue_vacancy = false;
|
||||||
return nBytes;
|
return nBytes;
|
||||||
} // end NormStreamObject::Write()
|
} // end NormStreamObject::Write()
|
||||||
|
|
||||||
|
|
@ -3025,8 +3081,10 @@ UINT16 NormSimObject::ReadSegment(NormBlockId blockId,
|
||||||
} // end NormSimObject::ReadSegment()
|
} // end NormSimObject::ReadSegment()
|
||||||
|
|
||||||
char* NormSimObject::RetrieveSegment(NormBlockId blockId,
|
char* NormSimObject::RetrieveSegment(NormBlockId blockId,
|
||||||
NormSegmentId segmentId)
|
NormSegmentId segmentId,
|
||||||
|
bool& tempRetrieval)
|
||||||
{
|
{
|
||||||
|
tempRetrieval = true;
|
||||||
return server ? server->GetRetrievalSegment() : NULL;
|
return server ? server->GetRetrievalSegment() : NULL;
|
||||||
} // end NormSimObject::RetrieveSegment()
|
} // end NormSimObject::RetrieveSegment()
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -94,7 +94,8 @@ class NormObject
|
||||||
bool* msgStart = NULL) = 0;
|
bool* msgStart = NULL) = 0;
|
||||||
|
|
||||||
virtual char* RetrieveSegment(NormBlockId blockId,
|
virtual char* RetrieveSegment(NormBlockId blockId,
|
||||||
NormSegmentId segmentId) = 0;
|
NormSegmentId segmentId,
|
||||||
|
bool& tempRetrieval) = 0;
|
||||||
|
|
||||||
NackingMode GetNackingMode() const {return nacking_mode;}
|
NackingMode GetNackingMode() const {return nacking_mode;}
|
||||||
void SetNackingMode(NackingMode nackingMode)
|
void SetNackingMode(NackingMode nackingMode)
|
||||||
|
|
@ -303,7 +304,8 @@ class NormFileObject : public NormObject
|
||||||
char* buffer,
|
char* buffer,
|
||||||
bool* msgStart = NULL);
|
bool* msgStart = NULL);
|
||||||
virtual char* RetrieveSegment(NormBlockId blockId,
|
virtual char* RetrieveSegment(NormBlockId blockId,
|
||||||
NormSegmentId segmentId);
|
NormSegmentId segmentId,
|
||||||
|
bool& tempRetrieval);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
char path[PATH_MAX];
|
char path[PATH_MAX];
|
||||||
|
|
@ -348,7 +350,8 @@ class NormDataObject : public NormObject
|
||||||
bool* msgStart = NULL);
|
bool* msgStart = NULL);
|
||||||
|
|
||||||
virtual char* RetrieveSegment(NormBlockId blockId,
|
virtual char* RetrieveSegment(NormBlockId blockId,
|
||||||
NormSegmentId segmentId);
|
NormSegmentId segmentId,
|
||||||
|
bool& tempRetrieval);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
NormObjectSize large_block_length;
|
NormObjectSize large_block_length;
|
||||||
|
|
@ -369,10 +372,11 @@ class NormStreamObject : public NormObject
|
||||||
~NormStreamObject();
|
~NormStreamObject();
|
||||||
|
|
||||||
bool Open(UINT32 bufferSize,
|
bool Open(UINT32 bufferSize,
|
||||||
|
bool doubleBuffer = false,
|
||||||
const char* infoPtr = NULL,
|
const char* infoPtr = NULL,
|
||||||
UINT16 infoLen = 0);
|
UINT16 infoLen = 0);
|
||||||
void Close();
|
void Close();
|
||||||
bool Accept(UINT32 bufferSize);
|
bool Accept(UINT32 bufferSize, bool doubleBuffer = false);
|
||||||
|
|
||||||
enum FlushMode
|
enum FlushMode
|
||||||
{
|
{
|
||||||
|
|
@ -415,7 +419,8 @@ class NormStreamObject : public NormObject
|
||||||
bool* msgStart = NULL);
|
bool* msgStart = NULL);
|
||||||
|
|
||||||
virtual char* RetrieveSegment(NormBlockId blockId,
|
virtual char* RetrieveSegment(NormBlockId blockId,
|
||||||
NormSegmentId segmentId);
|
NormSegmentId segmentId,
|
||||||
|
bool& tempRetrieval);
|
||||||
|
|
||||||
|
|
||||||
// For receive stream, we can rewind to earliest buffered offset
|
// For receive stream, we can rewind to earliest buffered offset
|
||||||
|
|
@ -465,6 +470,9 @@ class NormStreamObject : public NormObject
|
||||||
NormBlockBuffer stream_buffer;
|
NormBlockBuffer stream_buffer;
|
||||||
Index write_index;
|
Index write_index;
|
||||||
UINT32 write_offset;
|
UINT32 write_offset;
|
||||||
|
UINT32 tx_offset;
|
||||||
|
bool write_vacancy;
|
||||||
|
bool posted_tx_queue_vacancy;
|
||||||
bool read_init;
|
bool read_init;
|
||||||
Index read_index;
|
Index read_index;
|
||||||
UINT32 read_offset;
|
UINT32 read_offset;
|
||||||
|
|
@ -505,7 +513,8 @@ class NormSimObject : public NormObject
|
||||||
bool* msgStart = NULL);
|
bool* msgStart = NULL);
|
||||||
|
|
||||||
virtual char* RetrieveSegment(NormBlockId blockId,
|
virtual char* RetrieveSegment(NormBlockId blockId,
|
||||||
NormSegmentId segmentId);
|
NormSegmentId segmentId,
|
||||||
|
bool& tempRetrieval);
|
||||||
}; // end class NormSimObject
|
}; // end class NormSimObject
|
||||||
#endif // SIMULATE
|
#endif // SIMULATE
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -537,6 +537,11 @@ void NormSession::Serve()
|
||||||
else
|
else
|
||||||
tx_pending_mask.Unset(obj->GetId());
|
tx_pending_mask.Unset(obj->GetId());
|
||||||
}
|
}
|
||||||
|
else if (obj->IsStream())
|
||||||
|
{
|
||||||
|
// Is there room write to the stream
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
@ -890,6 +895,7 @@ NormDataObject* NormSession::QueueTxData(const char* dataPtr,
|
||||||
|
|
||||||
|
|
||||||
NormStreamObject* NormSession::QueueTxStream(UINT32 bufferSize,
|
NormStreamObject* NormSession::QueueTxStream(UINT32 bufferSize,
|
||||||
|
bool doubleBuffer,
|
||||||
const char* infoPtr,
|
const char* infoPtr,
|
||||||
UINT16 infoLen)
|
UINT16 infoLen)
|
||||||
{
|
{
|
||||||
|
|
@ -905,7 +911,7 @@ NormStreamObject* NormSession::QueueTxStream(UINT32 bufferSize,
|
||||||
strerror(errno));
|
strerror(errno));
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
if (!stream->Open(bufferSize, infoPtr, infoLen))
|
if (!stream->Open(bufferSize, doubleBuffer, infoPtr, infoLen))
|
||||||
{
|
{
|
||||||
DMSG(0, "NormSession::QueueTxStream() stream open error\n");
|
DMSG(0, "NormSession::QueueTxStream() stream open error\n");
|
||||||
delete stream;
|
delete stream;
|
||||||
|
|
|
||||||
|
|
@ -162,6 +162,7 @@ class NormSession
|
||||||
const char* interfaceName = NULL);
|
const char* interfaceName = NULL);
|
||||||
void StopServer();
|
void StopServer();
|
||||||
NormStreamObject* QueueTxStream(UINT32 bufferSize,
|
NormStreamObject* QueueTxStream(UINT32 bufferSize,
|
||||||
|
bool doubleBuffer = false,
|
||||||
const char* infoPtr = NULL,
|
const char* infoPtr = NULL,
|
||||||
UINT16 infoLen = 0);
|
UINT16 infoLen = 0);
|
||||||
NormFileObject* QueueTxFile(const char* path,
|
NormFileObject* QueueTxFile(const char* path,
|
||||||
|
|
|
||||||
|
|
@ -35,22 +35,25 @@ int main(int argc, char* argv[])
|
||||||
|
|
||||||
//NormSetMessageTrace(session, true);
|
//NormSetMessageTrace(session, true);
|
||||||
|
|
||||||
NormSetTxLoss(session, 1.0); // 10% packet loss
|
//NormSetTxLoss(session, 1.0); // 10% packet loss
|
||||||
|
|
||||||
NormSetGrttEstimate(session, 0.5);//0.001); // 1 msec initial grtt
|
NormSetGrttEstimate(session, 0.001); // 1 msec initial grtt
|
||||||
|
|
||||||
NormSetTransmitRate(session, 1.0e+06); // in bits/second
|
NormSetTransmitRate(session, 90.0e+06); // in bits/second
|
||||||
|
|
||||||
NormSetDefaultRepairBoundary(session, NORM_BOUNDARY_BLOCK);
|
NormSetDefaultRepairBoundary(session, NORM_BOUNDARY_BLOCK);
|
||||||
|
|
||||||
// Uncomment to receive own traffic
|
// Uncomment to receive your own traffic
|
||||||
NormSetLoopback(session, true);
|
//NormSetLoopback(session, true);
|
||||||
|
|
||||||
// Uncomment this line to participate as a receiver
|
// Uncomment this line to participate as a receiver
|
||||||
//NormStartReceiver(session, 1024*1024);
|
//NormStartReceiver(session, 1024*1024);
|
||||||
|
|
||||||
|
// Uncomment to enable TCP-friendly congestion control
|
||||||
|
//NormSetCongestionControl(session, true);
|
||||||
|
|
||||||
// Uncomment the following line to start sender
|
// Uncomment the following line to start sender
|
||||||
NormStartSender(session, 1024*1024, 1024, 64, 0);
|
NormStartSender(session, 4096*1024, 1400, 64, 0);
|
||||||
|
|
||||||
NormAddAckingNode(session, NormGetLocalNodeId(session));
|
NormAddAckingNode(session, NormGetLocalNodeId(session));
|
||||||
|
|
||||||
|
|
@ -59,7 +62,7 @@ int main(int argc, char* argv[])
|
||||||
const char* fileName = "ferrari.jpg";
|
const char* fileName = "ferrari.jpg";
|
||||||
|
|
||||||
// Uncomment this line to send a stream instead of the file
|
// Uncomment this line to send a stream instead of the file
|
||||||
stream = NormStreamOpen(session, 1024*1024);
|
stream = NormStreamOpen(session, 4096*1024);
|
||||||
|
|
||||||
|
|
||||||
// NORM_FLUSH_PASSIVE automatically flushes full writes to
|
// NORM_FLUSH_PASSIVE automatically flushes full writes to
|
||||||
|
|
@ -86,27 +89,39 @@ int main(int argc, char* argv[])
|
||||||
switch (theEvent.type)
|
switch (theEvent.type)
|
||||||
{
|
{
|
||||||
case NORM_TX_QUEUE_EMPTY:
|
case NORM_TX_QUEUE_EMPTY:
|
||||||
|
//TRACE("NORM_TX_QUEUE_EMPTY ...\n");
|
||||||
|
case NORM_TX_QUEUE_VACANCY:
|
||||||
|
//TRACE("NORM_TX_QUEUE_VACANCY ...\n");
|
||||||
|
|
||||||
if (NORM_OBJECT_INVALID != stream)
|
if (NORM_OBJECT_INVALID != stream)
|
||||||
{
|
{
|
||||||
if (0 == txLen)
|
// We loop here to keep stream buffer full ....
|
||||||
|
bool keepWriting = true;
|
||||||
|
while (keepWriting)
|
||||||
{
|
{
|
||||||
// Write a message to the "txBuffer"
|
if (0 == txLen)
|
||||||
memset(txBuffer, 'a', 1037);
|
{
|
||||||
sprintf(txBuffer+1037, "normTest says hello %d ...\n", sendCount);
|
// Write a message to the "txBuffer"
|
||||||
txLen = strlen(txBuffer);
|
memset(txBuffer, 'a', 1037);
|
||||||
}
|
sprintf(txBuffer+1037, "normTest says hello %d ...\n", sendCount);
|
||||||
txIndex += NormStreamWrite(stream, txBuffer+txIndex, (txLen - txIndex));
|
txLen = strlen(txBuffer);
|
||||||
if (txIndex == txLen)
|
}
|
||||||
{
|
unsigned int want = txLen - txIndex;
|
||||||
// Instead of "NormStreamSetFlushMode(stream, NORM_FLUSH_PASSIVE)" above
|
unsigned int put = NormStreamWrite(stream, txBuffer+txIndex, want);
|
||||||
// and "NormStreamMarkEom()" here, I could have used
|
if (put != want) keepWriting = false;
|
||||||
// "NormStreamFlush(stream, true)" here to perform explicit flushing
|
txIndex += put;
|
||||||
// and EOM marking in one fell swoop. That would be a better approach
|
if (txIndex == txLen)
|
||||||
// for apps where big stream messages need to be written with
|
{
|
||||||
// multiple calls to "NormStreamWrite()"
|
// Instead of "NormStreamSetFlushMode(stream, NORM_FLUSH_PASSIVE)" above
|
||||||
NormStreamMarkEom(stream);
|
// and "NormStreamMarkEom()" here, I could have used
|
||||||
txLen = txIndex = 0;
|
// "NormStreamFlush(stream, true)" here to perform explicit flushing
|
||||||
sendCount++;
|
// and EOM marking in one fell swoop. That would be a better approach
|
||||||
|
// for apps where big stream messages need to be written with
|
||||||
|
// multiple calls to "NormStreamWrite()"
|
||||||
|
NormStreamMarkEom(stream);
|
||||||
|
txLen = txIndex = 0;
|
||||||
|
sendCount++;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
|
||||||
|
|
@ -32,6 +32,6 @@
|
||||||
|
|
||||||
#ifndef _NORM_VERSION
|
#ifndef _NORM_VERSION
|
||||||
#define _NORM_VERSION
|
#define _NORM_VERSION
|
||||||
#define VERSION "1.2b8"
|
#define VERSION "1.2b9"
|
||||||
#endif // _NORM_VERSION
|
#endif // _NORM_VERSION
|
||||||
|
|
||||||
|
|
|
||||||
BIN
win32/Norm.opt
BIN
win32/Norm.opt
Binary file not shown.
Loading…
Reference in New Issue