pull/2/head
Jeff Weston 2019-09-11 11:34:04 -04:00
parent 25676f4b00
commit 4244ba41d1
11 changed files with 393 additions and 325 deletions

View File

@ -928,7 +928,7 @@ void NormApp::Notify(NormController::Event event,
if (silent_client) if (silent_client)
size = NormObjectSize((UINT32)rx_buffer_size); size = NormObjectSize((UINT32)rx_buffer_size);
else else
size = object->Size(); size = object->GetSize();
if (((NormStreamObject*)object)->Accept(size.LSB())) if (((NormStreamObject*)object)->Accept(size.LSB()))
{ {
@ -993,7 +993,7 @@ void NormApp::Notify(NormController::Event event,
strncpy(fileName, rx_cache_path, PATH_MAX); strncpy(fileName, rx_cache_path, PATH_MAX);
UINT16 pathLen = strlen(rx_cache_path); UINT16 pathLen = strlen(rx_cache_path);
pathLen = MIN(pathLen, PATH_MAX); pathLen = MIN(pathLen, PATH_MAX);
UINT16 len = object->InfoLength(); UINT16 len = object->GetInfoLength();
len = MIN(len, (PATH_MAX - pathLen)); len = MIN(len, (PATH_MAX - pathLen));
strncat(fileName, object->GetInfo(), len); strncat(fileName, object->GetInfo(), len);
// Convert '/' in file info to directory delimiters // Convert '/' in file info to directory delimiters

View File

@ -262,49 +262,51 @@ void NormServerNode::HandleCommand(const struct timeval& currentTime,
{ {
is_clr = is_plr = false; is_clr = is_plr = false;
} }
if (is_clr || is_plr) double maxBackoff;
if (is_clr || is_plr || !session->Address().IsMulticast())
{ {
// Respond immediately // Respond immediately
maxBackoff = 0.0;
if (cc_timer.IsActive()) cc_timer.Deactivate(); if (cc_timer.IsActive()) cc_timer.Deactivate();
cc_timer.ResetRepeat();
OnCCTimeout(cc_timer);
} }
else if (!cc_timer.IsActive()) else
{ {
if (cc_timer.IsActive()) break;
double backoffFactor = backoff_factor; double backoffFactor = backoff_factor;
backoffFactor = MAX(backoffFactor, 4.0); backoffFactor = MAX(backoffFactor, 4.0);
double maxBackoff = grtt_estimate*backoffFactor; maxBackoff = grtt_estimate*backoffFactor;
// (TBD) don't backoff for unicast sessions
double backoffTime = (maxBackoff > 0.0) ?
ExponentialRand(maxBackoff, gsize_estimate) : 0.0;
// Bias backoff timeout based on our rate
double r;
if (slow_start)
{
r = recv_rate / send_rate;
cc_rate = 2.0 * recv_rate;
}
else
{
cc_rate = NormSession::CalculateRate(nominal_packet_size,
rtt_estimate,
LossEstimate());
r = cc_rate / send_rate;
r = MIN(r, 0.9);
r = MAX(r, 0.5);
r = (r - 0.5) / 0.4;
}
//TRACE("NormServerNode::HandleCommand(CC) node>%lu bias:%lf recv_rate:%lf send_rate:%lf "
// "grtt:%lf gsize:%lf\n",
// LocalNodeId(), r, recv_rate*(8.0/1000.0), send_rate*(8.0/1000.0),
//
backoffTime = 0.25 * r * maxBackoff + 0.75 * backoffTime;
cc_timer.SetInterval(backoffTime);
DMSG(4, "NormServerNode::HandleCommand() node>%lu begin CC back-off: %lf sec)...\n",
LocalNodeId(), backoffTime);
session->ActivateTimer(cc_timer);
} }
double backoffTime = (maxBackoff > 0.0) ?
ExponentialRand(maxBackoff, gsize_estimate) :
0.0;
// Bias backoff timeout based on our rate
double r;
if (slow_start)
{
r = recv_rate / send_rate;
cc_rate = 2.0 * recv_rate;
}
else
{
cc_rate = NormSession::CalculateRate(nominal_packet_size,
rtt_estimate,
LossEstimate());
r = cc_rate / send_rate;
r = MIN(r, 0.9);
r = MAX(r, 0.5);
r = (r - 0.5) / 0.4;
}
//DMSG(0, "NormServerNode::HandleCommand(CC) node>%lu bias:%lf recv_rate:%lf send_rate:%lf "
// "grtt:%lf gsize:%lf\n",
// LocalNodeId(), r, recv_rate*(8.0/1000.0), send_rate*(8.0/1000.0),
//
backoffTime = 0.25 * r * maxBackoff + 0.75 * backoffTime;
cc_timer.SetInterval(backoffTime);
DMSG(6, "NormServerNode::HandleCommand() node>%lu begin CC back-off: %lf sec)...\n",
LocalNodeId(), backoffTime);
session->ActivateTimer(cc_timer);
} // end if (CC_RATE == ext.GetType()) } // end if (CC_RATE == ext.GetType())
} // end while (GetNextExtension()) } // end while (GetNextExtension())
break; break;
@ -598,7 +600,7 @@ void NormServerNode::DeleteObject(NormObject* obj)
// (TBD) Notify app of object's closing/demise? // (TBD) Notify app of object's closing/demise?
obj->Close(); obj->Close();
rx_table.Remove(obj); rx_table.Remove(obj);
rx_pending_mask.Unset(obj->Id()); rx_pending_mask.Unset(obj->GetId());
delete obj; delete obj;
} // end NormServerNode::DeleteObject() } // end NormServerNode::DeleteObject()
@ -615,13 +617,13 @@ NormBlock* NormServerNode::GetFreeBlock(NormObjectId objectId, NormBlockId block
NormObject* obj; NormObject* obj;
while ((obj = iterator.GetNextObject())) while ((obj = iterator.GetNextObject()))
{ {
if (obj->Id() > objectId) if (obj->GetId() > objectId)
{ {
break; break;
} }
else else
{ {
if (obj->Id() < objectId) if (obj->GetId() < objectId)
b = obj->StealOldestBlock(false); b = obj->StealOldestBlock(false);
else else
b = obj->StealOldestBlock(true, blockId); b = obj->StealOldestBlock(true, blockId);
@ -640,13 +642,13 @@ NormBlock* NormServerNode::GetFreeBlock(NormObjectId objectId, NormBlockId block
NormObject* obj; NormObject* obj;
while ((obj = iterator.GetPrevObject())) while ((obj = iterator.GetPrevObject()))
{ {
if (obj->Id() < objectId) if (obj->GetId() < objectId)
{ {
break; break;
} }
else else
{ {
if (obj->Id() > objectId) if (obj->GetId() > objectId)
b = obj->StealNewestBlock(false); b = obj->StealNewestBlock(false);
else else
b = obj->StealNewestBlock(true, blockId); b = obj->StealNewestBlock(true, blockId);
@ -930,7 +932,7 @@ void NormServerNode::Sync(NormObjectId objectId)
{ {
NormObject* obj; NormObject* obj;
while ((obj = rx_table.Find(rx_table.RangeLo())) && while ((obj = rx_table.Find(rx_table.RangeLo())) &&
(obj->Id() < objectId)) (obj->GetId() < objectId))
{ {
DeleteObject(obj); DeleteObject(obj);
failure_count++; failure_count++;
@ -1367,28 +1369,30 @@ bool NormServerNode::OnRepairTimeout(ProtoTimer& /*theTimer*/)
void NormServerNode::UpdateRecvRate(const struct timeval& currentTime, unsigned short msgSize) void NormServerNode::UpdateRecvRate(const struct timeval& currentTime, unsigned short msgSize)
{ {
double interval;
if (prev_update_time.tv_sec || prev_update_time.tv_usec) if (prev_update_time.tv_sec || prev_update_time.tv_usec)
{ {
interval = (double)(currentTime.tv_sec - prev_update_time.tv_sec); double interval = (double)(currentTime.tv_sec - prev_update_time.tv_sec);
if (currentTime.tv_usec > prev_update_time.tv_sec) if (currentTime.tv_usec > prev_update_time.tv_sec)
interval += 1.0e-06*(double)(currentTime.tv_usec - prev_update_time.tv_usec); interval += 1.0e-06*(double)(currentTime.tv_usec - prev_update_time.tv_usec);
else else
interval -= 1.0e-06*(double)(prev_update_time.tv_usec - currentTime.tv_usec); interval -= 1.0e-06*(double)(prev_update_time.tv_usec - currentTime.tv_usec);
}
else
{
recv_rate = ((double)msgSize) / grtt_estimate;
interval = 0.0;
prev_update_time = currentTime;
}
if (interval < grtt_estimate)
{
recv_accumulator += msgSize; recv_accumulator += msgSize;
}
double rttEstimate = rtt_confirmed ? rtt_estimate : grtt_estimate;
if (interval >= rttEstimate)
{
recv_rate = ((double)(recv_accumulator)) / interval;
prev_update_time = currentTime;
recv_accumulator = 0;
}
}
else else
{ {
recv_rate = ((double)(recv_accumulator+msgSize)) / interval; if (send_rate > 0.0)
recv_rate = send_rate;
else
recv_rate = ((double)msgSize) / grtt_estimate;
prev_update_time = currentTime; prev_update_time = currentTime;
recv_accumulator = 0; recv_accumulator = 0;
} }
@ -1497,7 +1501,7 @@ bool NormServerNode::OnCCTimeout(ProtoTimer& /*theTimer*/)
rtt_estimate, ccLoss); rtt_estimate, ccLoss);
ext.SetCCRate(NormQuantizeRate(ccRate)); ext.SetCCRate(NormQuantizeRate(ccRate));
} }
//TRACE("NormServerNode::OnCCTimeout() node>%lu sending ACK rate:%lf kbps (rtt:%lf loss:%lf s:%lf recvRate:%lf) slow_start:%d\n", //DMSG(0, "NormServerNode::OnCCTimeout() node>%lu sending ACK rate:%lf kbps (rtt:%lf loss:%lf s:%lf recvRate:%lf) slow_start:%d\n",
// LocalNodeId(), NormUnquantizeRate(ext.GetCCRate()) * (8.0/1000.0), // LocalNodeId(), NormUnquantizeRate(ext.GetCCRate()) * (8.0/1000.0),
// rtt_estimate, ccLoss, nominal_packet_size, recv_rate*(8.0/1000.), slow_start); // rtt_estimate, ccLoss, nominal_packet_size, recv_rate*(8.0/1000.), slow_start);
ext.SetCCSequence(cc_sequence); ext.SetCCSequence(cc_sequence);

View File

@ -6,9 +6,9 @@
NormObject::NormObject(NormObject::Type theType, NormObject::NormObject(NormObject::Type theType,
class NormSession* theSession, class NormSession* theSession,
class NormServerNode* theServer, class NormServerNode* theServer,
const NormObjectId& objectId) const NormObjectId& transportId)
: type(theType), session(theSession), server(theServer), : type(theType), session(theSession), server(theServer),
id(objectId), segment_size(0), pending_info(false), repair_info(false), transport_id(transportId), segment_size(0), pending_info(false), repair_info(false),
current_block_id(0), next_segment_id(0), current_block_id(0), next_segment_id(0),
max_pending_block(0), max_pending_segment(0), max_pending_block(0), max_pending_segment(0),
info(NULL), info_len(0), accepted(false) info(NULL), info_len(0), accepted(false)
@ -35,8 +35,6 @@ NormNodeId NormObject::LocalNodeId() const
return session->LocalNodeId(); return session->LocalNodeId();
} }
bool NormObject::Open(const NormObjectSize& objectSize, bool NormObject::Open(const NormObjectSize& objectSize,
const char* infoPtr, const char* infoPtr,
UINT16 infoLen) UINT16 infoLen)
@ -248,7 +246,7 @@ bool NormObject::TxReset(NormBlockId firstBlock)
NormBlock* block; NormBlock* block;
while ((block = iterator.GetNextBlock())) while ((block = iterator.GetNextBlock()))
{ {
NormBlockId blockId = block->Id(); NormBlockId blockId = block->GetId();
if (blockId >= firstBlock) if (blockId >= firstBlock)
{ {
increasedRepair |= block->TxReset(GetBlockSize(blockId), increasedRepair |= block->TxReset(GetBlockSize(blockId),
@ -274,7 +272,7 @@ bool NormObject::TxResetBlocks(NormBlockId nextId, NormBlockId lastId)
} }
NormBlock* block = block_buffer.Find(nextId); NormBlock* block = block_buffer.Find(nextId);
if (block) if (block)
increasedRepair |= block->TxReset(GetBlockSize(block->Id()), nparity, autoParity, segment_size); increasedRepair |= block->TxReset(GetBlockSize(block->GetId()), nparity, autoParity, segment_size);
nextId++; nextId++;
} }
return increasedRepair; return increasedRepair;
@ -297,7 +295,7 @@ bool NormObject::ActivateRepairs()
NormBlockId lastId; NormBlockId lastId;
ASSERT(GetLastRepair(lastId)); ASSERT(GetLastRepair(lastId));
DMSG(6, "NormObject::ActivateRepairs() node>%lu obj>%hu activating blk>%lu->%lu repairs\n", DMSG(6, "NormObject::ActivateRepairs() node>%lu obj>%hu activating blk>%lu->%lu repairs\n",
LocalNodeId(), (UINT16)id, (UINT32)nextId, (UINT32)lastId); LocalNodeId(), (UINT16)transport_id, (UINT32)nextId, (UINT32)lastId);
repairsActivated = true; repairsActivated = true;
UINT16 autoParity = session->ServerAutoParity(); UINT16 autoParity = session->ServerAutoParity();
do do
@ -320,10 +318,10 @@ bool NormObject::ActivateRepairs()
{ {
repairsActivated = true; repairsActivated = true;
DMSG(6, "NormObject::ActivateRepairs() node>%lu obj>%hu activated blk>%lu segment repairs ...\n", DMSG(6, "NormObject::ActivateRepairs() node>%lu obj>%hu activated blk>%lu segment repairs ...\n",
LocalNodeId(), (UINT16)id, (UINT32)block->Id()); LocalNodeId(), (UINT16)transport_id, (UINT32)block->GetId());
// (TBD) This check can be eventually eliminated if everything else is done right // (TBD) This check can be eventually eliminated if everything else is done right
if (!pending_mask.Set(block->Id())) if (!pending_mask.Set(block->GetId()))
DMSG(0, "NormObject::ActivateRepairs() pending_mask.Set(%lu) error!\n", (UINT32)block->Id()); DMSG(0, "NormObject::ActivateRepairs() pending_mask.Set(%lu) error!\n", (UINT32)block->GetId());
} }
} }
return repairsActivated; return repairsActivated;
@ -408,13 +406,13 @@ bool NormObject::AppendRepairAdv(NormCmdRepairAdvMsg& cmd)
ASSERT(0); // can't happen ASSERT(0); // can't happen
break; break;
case NormRepairRequest::ITEMS: case NormRepairRequest::ITEMS:
req.AppendRepairItem(id, firstId, ndata, 0); req.AppendRepairItem(transport_id, firstId, GetBlockSize(firstId), 0);
if (2 == blockCount) if (2 == blockCount)
req.AppendRepairItem(id, currentId, ndata, 0); req.AppendRepairItem(transport_id, currentId, GetBlockSize(currentId), 0);
break; break;
case NormRepairRequest::RANGES: case NormRepairRequest::RANGES:
req.AppendRepairRange(id, firstId, ndata, 0, req.AppendRepairRange(transport_id, firstId, GetBlockSize(firstId), 0,
id, currentId, ndata, 0); transport_id, currentId, GetBlockSize(currentId), 0);
break; break;
case NormRepairRequest::ERASURES: case NormRepairRequest::ERASURES:
// erasure counts not used // erasure counts not used
@ -432,7 +430,7 @@ bool NormObject::AppendRepairAdv(NormCmdRepairAdvMsg& cmd)
cmd.PackRepairRequest(req); // (TBD) error check cmd.PackRepairRequest(req); // (TBD) error check
prevForm = NormRepairRequest::INVALID; prevForm = NormRepairRequest::INVALID;
} }
block->AppendRepairAdv(cmd, id, repair_info, ndata, segment_size); // (TBD) error check block->AppendRepairAdv(cmd, transport_id, repair_info, GetBlockSize(currentId), segment_size); // (TBD) error check
} }
} }
} // end while(nextId < endId) } // end while(nextId < endId)
@ -736,7 +734,7 @@ bool NormObject::AppendRepairRequest(NormNackMsg& nack,
NormBlockId lastId; NormBlockId lastId;
ASSERT(GetLastPending(lastId)); ASSERT(GetLastPending(lastId));
DMSG(6, "NormObject::AppendRepairRequest() node>%lu obj>%hu, blk>%lu->%lu (maxPending:%lu)\n", DMSG(6, "NormObject::AppendRepairRequest() node>%lu obj>%hu, blk>%lu->%lu (maxPending:%lu)\n",
LocalNodeId(), (UINT16)id, LocalNodeId(), (UINT16)transport_id,
(UINT32)nextId, (UINT32)lastId, (UINT32)max_pending_block); (UINT32)nextId, (UINT32)lastId, (UINT32)max_pending_block);
bool appendRequest = false; bool appendRequest = false;
NormBlock* block = iterating ? block_buffer.Find(nextId) : NULL; NormBlock* block = iterating ? block_buffer.Find(nextId) : NULL;
@ -783,18 +781,18 @@ bool NormObject::AppendRepairRequest(NormNackMsg& nack,
switch (nextForm) switch (nextForm)
{ {
case NormRepairRequest::ITEMS: case NormRepairRequest::ITEMS:
req.AppendRepairItem(id, prevId, GetBlockSize(prevId), 0); // (TBD) error check req.AppendRepairItem(transport_id, prevId, GetBlockSize(prevId), 0); // (TBD) error check
if (2 == consecutiveCount) if (2 == consecutiveCount)
{ {
prevId++; prevId++;
req.AppendRepairItem(id, prevId, GetBlockSize(prevId), 0); // (TBD) error check req.AppendRepairItem(transport_id, prevId, GetBlockSize(prevId), 0); // (TBD) error check
} }
break; break;
case NormRepairRequest::RANGES: case NormRepairRequest::RANGES:
{ {
NormBlockId lastId = prevId+consecutiveCount-1; NormBlockId lastId = prevId+consecutiveCount-1;
req.AppendRepairRange(id, prevId, GetBlockSize(prevId), 0, req.AppendRepairRange(transport_id, prevId, GetBlockSize(prevId), 0,
id, lastId, GetBlockSize(lastId), 0); // (TBD) error check transport_id, lastId, GetBlockSize(lastId), 0); // (TBD) error check
break; break;
} }
default: default:
@ -820,16 +818,16 @@ bool NormObject::AppendRepairRequest(NormNackMsg& nack,
nack.PackRepairRequest(req); // (TBD) error check nack.PackRepairRequest(req); // (TBD) error check
if (flush || (nextId != max_pending_block)) if (flush || (nextId != max_pending_block))
{ {
block->AppendRepairRequest(nack, numData, nparity, id, block->AppendRepairRequest(nack, numData, nparity, transport_id,
pending_info, segment_size); // (TBD) error check pending_info, segment_size); // (TBD) error check
} }
else else
{ {
if (max_pending_segment < numData) if (max_pending_segment < numData)
block->AppendRepairRequest(nack, max_pending_segment, 0, id, block->AppendRepairRequest(nack, max_pending_segment, 0, transport_id,
pending_info, segment_size); // (TBD) error check pending_info, segment_size); // (TBD) error check
else else
block->AppendRepairRequest(nack, numData, nparity, id, block->AppendRepairRequest(nack, numData, nparity, transport_id,
pending_info, segment_size); // (TBD) error check pending_info, segment_size); // (TBD) error check
} }
} }
@ -862,7 +860,7 @@ bool NormObject::AppendRepairRequest(NormNackMsg& nack,
req.SetForm(NormRepairRequest::ITEMS); req.SetForm(NormRepairRequest::ITEMS);
req.ResetFlags(); req.ResetFlags();
req.SetFlag(NormRepairRequest::INFO); req.SetFlag(NormRepairRequest::INFO);
req.AppendRepairItem(id, 0, 0, 0); // (TBD) error check req.AppendRepairItem(transport_id, 0, 0, 0); // (TBD) error check
} // end if/else (iterating) } // end if/else (iterating)
if (NormRepairRequest::INVALID != prevForm) if (NormRepairRequest::INVALID != prevForm)
nack.PackRepairRequest(req); // (TBD) error check nack.PackRepairRequest(req); // (TBD) error check
@ -885,7 +883,8 @@ void NormObject::HandleObjectMessage(const NormObjectMsg& msg,
{ {
info_len = segment_size; info_len = segment_size;
DMSG(0, "NormObject::HandleObjectMessage() node>%lu server>%lu obj>%hu " DMSG(0, "NormObject::HandleObjectMessage() node>%lu server>%lu obj>%hu "
"Warning! info too long.\n", LocalNodeId(), server->GetId(), (UINT16)id); "Warning! info too long.\n", LocalNodeId(), server->GetId(),
(UINT16)transport_id);
} }
memcpy(info, infoMsg.GetInfo(), info_len); memcpy(info, infoMsg.GetInfo(), info_len);
pending_info = false; pending_info = false;
@ -896,7 +895,7 @@ void NormObject::HandleObjectMessage(const NormObjectMsg& msg,
// (TBD) Verify info hasn't changed? // (TBD) Verify info hasn't changed?
DMSG(6, "NormObject::HandleObjectMessage() node>%lu server>%lu obj>%hu " DMSG(6, "NormObject::HandleObjectMessage() node>%lu server>%lu obj>%hu "
"received duplicate info ...\n", LocalNodeId(), "received duplicate info ...\n", LocalNodeId(),
server->GetId(), (UINT16)id); server->GetId(), (UINT16)transport_id);
} }
} }
else // NORM_MSG_DATA else // NORM_MSG_DATA
@ -909,7 +908,7 @@ void NormObject::HandleObjectMessage(const NormObjectMsg& msg,
if (!stream->StreamUpdateStatus(blockId)) if (!stream->StreamUpdateStatus(blockId))
{ {
DMSG(4, "NormObject::HandleObjectMessage() node:%lu server:%lu obj>%hu blk>%lu " DMSG(4, "NormObject::HandleObjectMessage() node:%lu server:%lu obj>%hu blk>%lu "
"broken stream ...\n", LocalNodeId(), server->GetId(), (UINT16)id, (UINT32)blockId); "broken stream ...\n", LocalNodeId(), server->GetId(), (UINT16)transport_id, (UINT32)blockId);
//ASSERT(0); //ASSERT(0);
// ??? Ignore this new packet and try to fix stream ??? // ??? Ignore this new packet and try to fix stream ???
@ -943,11 +942,11 @@ void NormObject::HandleObjectMessage(const NormObjectMsg& msg,
NormBlock* block = block_buffer.Find(blockId); NormBlock* block = block_buffer.Find(blockId);
if (!block) if (!block)
{ {
if (!(block = server->GetFreeBlock(id, blockId))) if (!(block = server->GetFreeBlock(transport_id, blockId)))
{ {
DMSG(2, "NormObject::HandleObjectMessage() node>%lu server>%lu obj>%hu " DMSG(2, "NormObject::HandleObjectMessage() node>%lu server>%lu obj>%hu "
"Warning! no free blocks ...\n", LocalNodeId(), server->GetId(), "Warning! no free blocks ...\n", LocalNodeId(), server->GetId(),
(UINT16)id); (UINT16)transport_id);
return; return;
} }
block->RxInit(blockId, numData, nparity); block->RxInit(blockId, numData, nparity);
@ -956,12 +955,12 @@ void NormObject::HandleObjectMessage(const NormObjectMsg& msg,
if (block->IsPending(segmentId)) if (block->IsPending(segmentId))
{ {
// 1) Cache segment in block buffer in case its needed for decoding // 1) Cache segment in block buffer in case its needed for decoding
char* segment = server->GetFreeSegment(id, blockId); char* segment = server->GetFreeSegment(transport_id, blockId);
if (!segment) if (!segment)
{ {
DMSG(2, "NormObject::HandleObjectMessage() node>%lu server>%lu obj>%hu " DMSG(2, "NormObject::HandleObjectMessage() node>%lu server>%lu obj>%hu "
"Warning! no free segments ...\n", LocalNodeId(), server->GetId(), "Warning! no free segments ...\n", LocalNodeId(), server->GetId(),
(UINT16)id); (UINT16)transport_id);
return; return;
} }
UINT16 segmentLength = data.GetPayloadDataLength(); UINT16 segmentLength = data.GetPayloadDataLength();
@ -969,7 +968,7 @@ void NormObject::HandleObjectMessage(const NormObjectMsg& msg,
{ {
DMSG(0, "NormObject::HandleObjectMessage() node>%lu server>%lu obj>%hu " DMSG(0, "NormObject::HandleObjectMessage() node>%lu server>%lu obj>%hu "
"Error! segment too large ...\n", LocalNodeId(), server->GetId(), "Error! segment too large ...\n", LocalNodeId(), server->GetId(),
(UINT16)id); (UINT16)transport_id);
server->PutFreeSegment(segment); server->PutFreeSegment(segment);
return; return;
} }
@ -1011,7 +1010,7 @@ void NormObject::HandleObjectMessage(const NormObjectMsg& msg,
// and write any decoded data segments to object // and write any decoded data segments to object
DMSG(8, "NormObject::HandleObjectMessage() node>%lu server>%lu obj>%hu blk>%lu " DMSG(8, "NormObject::HandleObjectMessage() node>%lu server>%lu obj>%hu blk>%lu "
"completed block ...\n", LocalNodeId(), server->GetId(), "completed block ...\n", LocalNodeId(), server->GetId(),
(UINT16)id, (UINT32)block->Id()); (UINT16)transport_id, (UINT32)block->GetId());
UINT16 erasureCount = 0; UINT16 erasureCount = 0;
UINT16 nextErasure = 0; UINT16 nextErasure = 0;
if (block->GetFirstPending(nextErasure)) if (block->GetFirstPending(nextErasure))
@ -1023,11 +1022,11 @@ void NormObject::HandleObjectMessage(const NormObjectMsg& msg,
server->SetErasureLoc(erasureCount++, nextErasure); server->SetErasureLoc(erasureCount++, nextErasure);
if (nextErasure < numData) if (nextErasure < numData)
{ {
if (!(segment = server->GetFreeSegment(id, blockId))) if (!(segment = server->GetFreeSegment(transport_id, blockId)))
{ {
DMSG(2, "NormObject::HandleObjectMessage() node>%lu server>%lu obj>%hu " DMSG(2, "NormObject::HandleObjectMessage() node>%lu server>%lu obj>%hu "
"Warning! no free segments ...\n", LocalNodeId(), server->GetId(), "Warning! no free segments ...\n", LocalNodeId(), server->GetId(),
(UINT16)id); (UINT16)transport_id);
// (TBD) Dump the block ...??? // (TBD) Dump the block ...???
return; return;
} }
@ -1076,14 +1075,14 @@ void NormObject::HandleObjectMessage(const NormObjectMsg& msg,
{ {
DMSG(6, "NormObject::HandleObjectMessage() node>%lu server>%lu obj>%hu " DMSG(6, "NormObject::HandleObjectMessage() node>%lu server>%lu obj>%hu "
"received duplicate segment ...\n", LocalNodeId(), "received duplicate segment ...\n", LocalNodeId(),
server->GetId(), (UINT16)id); server->GetId(), (UINT16)transport_id);
} }
} }
else else
{ {
DMSG(6, "NormObject::HandleObjectMessage() node>%lu server>%lu obj>%hu " DMSG(6, "NormObject::HandleObjectMessage() node>%lu server>%lu obj>%hu "
"received duplicate block message ...\n", LocalNodeId(), "received duplicate block message ...\n", LocalNodeId(),
server->GetId(), (UINT16)id); server->GetId(), (UINT16)transport_id);
} // end if/else pending_mask.Test(blockId) } // end if/else pending_mask.Test(blockId)
} // end if/else (NORM_MSG_INFO) } // end if/else (NORM_MSG_INFO)
} // end NormObject::HandleObjectMessage() } // end NormObject::HandleObjectMessage()
@ -1104,7 +1103,7 @@ NormBlock* NormObject::StealNonPendingBlock(bool excludeBlock, NormBlockId exclu
NormBlock* block; NormBlock* block;
while ((block = iterator.GetNextBlock())) while ((block = iterator.GetNextBlock()))
{ {
NormBlockId bid = block->Id(); NormBlockId bid = block->GetId();
if (block->IsTransmitPending() || if (block->IsTransmitPending() ||
pending_mask.Test(bid) || pending_mask.Test(bid) ||
repair_mask.Test(bid) || repair_mask.Test(bid) ||
@ -1134,7 +1133,7 @@ NormBlock* NormObject::StealNewestBlock(bool excludeBlock, NormBlockId excludeId
else else
{ {
NormBlock* block = block_buffer.Find(block_buffer.RangeHi()); NormBlock* block = block_buffer.Find(block_buffer.RangeHi());
if (excludeBlock && (excludeId == block->Id())) if (excludeBlock && (excludeId == block->GetId()))
{ {
return NULL; return NULL;
} }
@ -1158,7 +1157,7 @@ NormBlock* NormObject::StealOldestBlock(bool excludeBlock, NormBlockId excludeId
else else
{ {
NormBlock* block = block_buffer.Find(block_buffer.RangeLo()); NormBlock* block = block_buffer.Find(block_buffer.RangeLo());
if (excludeBlock && (excludeId == block->Id())) if (excludeBlock && (excludeId == block->GetId()))
{ {
return NULL; return NULL;
} }
@ -1195,7 +1194,7 @@ bool NormObject::NextServerMsg(NormObjectMsg* msg)
} }
if (info) msg->SetFlag(NormObjectMsg::FLAG_INFO); if (info) msg->SetFlag(NormObjectMsg::FLAG_INFO);
msg->SetFecId(129); msg->SetFecId(129);
msg->SetObjectId(id); msg->SetObjectId(transport_id);
// We currently always apply the FTI extension // We currently always apply the FTI extension
NormFtiExtension fti; NormFtiExtension fti;
@ -1222,7 +1221,7 @@ bool NormObject::NextServerMsg(NormObjectMsg* msg)
NormBlock* block = block_buffer.Find(blockId); NormBlock* block = block_buffer.Find(blockId);
if (!block) if (!block)
{ {
if (!(block = session->ServerGetFreeBlock(id, blockId))) if (!(block = session->ServerGetFreeBlock(transport_id, blockId)))
{ {
DMSG(2, "NormObject::NextServerMsg() node>%lu Warning! server resource " DMSG(2, "NormObject::NextServerMsg() node>%lu Warning! server resource "
"constrained (no free blocks).\n", LocalNodeId()); "constrained (no free blocks).\n", LocalNodeId());
@ -1232,7 +1231,7 @@ bool NormObject::NextServerMsg(NormObjectMsg* msg)
UINT16 totalBlockLen = numData + nparity; UINT16 totalBlockLen = numData + nparity;
for (UINT16 i = numData; i < totalBlockLen; i++) for (UINT16 i = numData; i < totalBlockLen; i++)
{ {
char* s = session->ServerGetFreeSegment(id, blockId); char* s = session->ServerGetFreeSegment(transport_id, blockId);
if (s) if (s)
{ {
UINT16 payloadMax = segment_size + NormDataMsg::GetStreamPayloadHeaderLength(); UINT16 payloadMax = segment_size + NormDataMsg::GetStreamPayloadHeaderLength();
@ -1378,7 +1377,7 @@ void NormStreamObject::StreamAdvance()
else else
{ {
DMSG(4, "NormStreamObject::StreamAdvance() node>%lu Pending segment repairs (blk>%lu) " DMSG(4, "NormStreamObject::StreamAdvance() node>%lu Pending segment repairs (blk>%lu) "
"delaying stream advance ...\n", LocalNodeId(), (UINT32)block->Id()); "delaying stream advance ...\n", LocalNodeId(), (UINT32)block->GetId());
} }
} }
} }
@ -1391,10 +1390,10 @@ void NormStreamObject::StreamAdvance()
bool NormObject::CalculateBlockParity(NormBlock* block) bool NormObject::CalculateBlockParity(NormBlock* block)
{ {
char buffer[NormMsg::MAX_SIZE]; char buffer[NormMsg::MAX_SIZE];
UINT16 numData = GetBlockSize(block->Id()); UINT16 numData = GetBlockSize(block->GetId());
for (UINT16 i = 0; i < numData; i++) for (UINT16 i = 0; i < numData; i++)
{ {
UINT16 payloadLength = ReadSegment(block->Id(), i, buffer); UINT16 payloadLength = ReadSegment(block->GetId(), i, buffer);
if (0 != payloadLength) if (0 != payloadLength)
{ {
UINT16 payloadMax = segment_size+NormDataMsg::GetStreamPayloadHeaderLength(); UINT16 payloadMax = segment_size+NormDataMsg::GetStreamPayloadHeaderLength();
@ -1416,7 +1415,7 @@ bool NormObject::CalculateBlockParity(NormBlock* block)
NormBlock* NormObject::ServerRecoverBlock(NormBlockId blockId) NormBlock* NormObject::ServerRecoverBlock(NormBlockId blockId)
{ {
NormBlock* block = session->ServerGetFreeBlock(id, blockId); NormBlock* block = session->ServerGetFreeBlock(transport_id, blockId);
if (block) if (block)
{ {
UINT16 numData = GetBlockSize(blockId); UINT16 numData = GetBlockSize(blockId);
@ -1426,7 +1425,7 @@ NormBlock* NormObject::ServerRecoverBlock(NormBlockId blockId)
UINT16 totalBlockLen = numData + nparity; UINT16 totalBlockLen = numData + nparity;
for (UINT16 i = numData; i < totalBlockLen; i++) for (UINT16 i = numData; i < totalBlockLen; i++)
{ {
char* s = session->ServerGetFreeSegment(id, blockId); char* s = session->ServerGetFreeSegment(transport_id, blockId);
if (s) if (s)
{ {
UINT16 payloadMax = segment_size + NormDataMsg::GetStreamPayloadHeaderLength(); UINT16 payloadMax = segment_size + NormDataMsg::GetStreamPayloadHeaderLength();
@ -1952,7 +1951,7 @@ bool NormStreamObject::WriteSegment(NormBlockId blockId,
while (block->IsPending()) while (block->IsPending())
{ {
// Notify app for stream data salvage // Notify app for stream data salvage
read_index.block = block->Id(); read_index.block = block->GetId();
block->GetFirstPending(read_index.segment); block->GetFirstPending(read_index.segment);
NormBlock* tempBlock = block; NormBlock* tempBlock = block;
UINT32 tempOffset = read_offset; UINT32 tempOffset = read_offset;
@ -1995,9 +1994,9 @@ bool NormStreamObject::WriteSegment(NormBlockId blockId,
if (broken) if (broken)
{ {
DMSG(4, "NormStreamObject::WriteSegment() node>%lu obj>%hu blk>%lu seg>%hu broken stream ...\n", DMSG(4, "NormStreamObject::WriteSegment() node>%lu obj>%hu blk>%lu seg>%hu broken stream ...\n",
LocalNodeId(), (UINT16)id, (UINT32)blockId, (UINT16)segmentId); LocalNodeId(), (UINT16)transport_id, (UINT32)blockId, (UINT16)segmentId);
NormBlock* first = stream_buffer.Find(stream_buffer.RangeLo()); NormBlock* first = stream_buffer.Find(stream_buffer.RangeLo());
read_index.block = first->Id(); read_index.block = first->GetId();
read_index.segment = 0; read_index.segment = 0;
} }
} }
@ -2029,10 +2028,10 @@ void NormStreamObject::Prune(NormBlockId blockId)
NormBlock* block; NormBlock* block;
while ((block = block_buffer.Find(block_buffer.RangeLo()))) while ((block = block_buffer.Find(block_buffer.RangeLo())))
{ {
if (block->Id() < blockId) if (block->GetId() < blockId)
{ {
resync = true; resync = true;
pending_mask.Unset(block->Id()); pending_mask.Unset(block->GetId());
block_buffer.Remove(block); block_buffer.Remove(block);
server->PutFreeBlock(block); server->PutFreeBlock(block);
} }
@ -2183,7 +2182,7 @@ unsigned long NormStreamObject::Write(const char* buffer, unsigned long len,
ASSERT(block); ASSERT(block);
if (push) if (push)
{ {
NormBlockId blockId = block->Id(); NormBlockId blockId = block->GetId();
pending_mask.Unset(blockId); pending_mask.Unset(blockId);
repair_mask.Unset(blockId); repair_mask.Unset(blockId);
NormBlock* b = FindBlock(blockId); NormBlock* b = FindBlock(blockId);
@ -2215,7 +2214,7 @@ unsigned long NormStreamObject::Write(const char* buffer, unsigned long len,
ASSERT(b != block); ASSERT(b != block);
if (push) if (push)
{ {
NormBlockId blockId = block->Id(); NormBlockId blockId = block->GetId();
pending_mask.Unset(blockId); pending_mask.Unset(blockId);
repair_mask.Unset(blockId); repair_mask.Unset(blockId);
NormBlock* c = FindBlock(blockId); NormBlock* c = FindBlock(blockId);
@ -2404,7 +2403,7 @@ NormObject* NormObjectTable::Find(const NormObjectId& objectId) const
{ {
if ((objectId < range_lo) || (objectId > range_hi)) return (NormObject*)NULL; if ((objectId < range_lo) || (objectId > range_hi)) return (NormObject*)NULL;
NormObject* theObject = table[((UINT16)objectId) & hash_mask]; NormObject* theObject = table[((UINT16)objectId) & hash_mask];
while (theObject && (objectId != theObject->Id())) theObject = theObject->next; while (theObject && (objectId != theObject->GetId())) theObject = theObject->next;
return theObject; return theObject;
} }
else else
@ -2445,7 +2444,7 @@ bool NormObjectTable::CanInsert(NormObjectId objectId) const
bool NormObjectTable::Insert(NormObject* theObject) bool NormObjectTable::Insert(NormObject* theObject)
{ {
const NormObjectId& objectId = theObject->Id(); const NormObjectId& objectId = theObject->GetId();
if (!range) if (!range)
{ {
range_lo = range_hi = objectId; range_lo = range_hi = objectId;
@ -2468,7 +2467,7 @@ bool NormObjectTable::Insert(NormObject* theObject)
UINT16 index = ((UINT16)objectId) & hash_mask; UINT16 index = ((UINT16)objectId) & hash_mask;
NormObject* prev = NULL; NormObject* prev = NULL;
NormObject* entry = table[index]; NormObject* entry = table[index];
while (entry && (entry->Id() < objectId)) while (entry && (entry->GetId() < objectId))
{ {
prev = entry; prev = entry;
entry = entry->next; entry = entry->next;
@ -2477,24 +2476,24 @@ bool NormObjectTable::Insert(NormObject* theObject)
prev->next = theObject; prev->next = theObject;
else else
table[index] = theObject; table[index] = theObject;
ASSERT((entry ? (objectId != entry->Id()) : true)); ASSERT((entry ? (objectId != entry->GetId()) : true));
theObject->next = entry; theObject->next = entry;
count++; count++;
size = size + theObject->Size(); size = size + theObject->GetSize();
return true; return true;
} // end NormObjectTable::Insert() } // end NormObjectTable::Insert()
bool NormObjectTable::Remove(const NormObject* theObject) bool NormObjectTable::Remove(const NormObject* theObject)
{ {
ASSERT(theObject); ASSERT(theObject);
const NormObjectId& objectId = theObject->Id(); const NormObjectId& objectId = theObject->GetId();
if (range) if (range)
{ {
if ((objectId < range_lo) || (objectId > range_hi)) return false; if ((objectId < range_lo) || (objectId > range_hi)) return false;
UINT16 index = ((UINT16)objectId) & hash_mask; UINT16 index = ((UINT16)objectId) & hash_mask;
NormObject* prev = NULL; NormObject* prev = NULL;
NormObject* entry = table[index]; NormObject* entry = table[index];
while (entry && (entry->Id() != objectId)) while (entry && (entry->GetId() != objectId))
{ {
prev = entry; prev = entry;
entry = entry->next; entry = entry->next;
@ -2525,10 +2524,10 @@ bool NormObjectTable::Remove(const NormObject* theObject)
if ((entry = table[i])) if ((entry = table[i]))
{ {
NormObjectId id = (UINT16)index + offset; NormObjectId id = (UINT16)index + offset;
while(entry && (entry->Id() != id)) while(entry && (entry->GetId() != id))
{ {
if ((entry->Id() > objectId) && if ((entry->GetId() > objectId) &&
(entry->Id() < nextId)) nextId = entry->Id(); (entry->GetId() < nextId)) nextId = entry->GetId();
entry = entry->next; entry = entry->next;
} }
@ -2536,7 +2535,7 @@ bool NormObjectTable::Remove(const NormObject* theObject)
} }
} while (i != endex); } while (i != endex);
if (entry) if (entry)
range_lo = entry->Id(); range_lo = entry->GetId();
else else
range_lo = nextId; range_lo = nextId;
range = range_hi - range_lo + 1; range = range_hi - range_lo + 1;
@ -2561,18 +2560,18 @@ bool NormObjectTable::Remove(const NormObject* theObject)
if ((entry = table[i])) if ((entry = table[i]))
{ {
NormObjectId id = (UINT16)index - offset; NormObjectId id = (UINT16)index - offset;
//printf("Looking for id:%lu at index:%lu\n", (UINT16)id, i); //printf("Looking for id:%lu at index:%lu\n", (UINT16)transport_id, i);
while(entry && (entry->Id() != id)) while(entry && (entry->GetId() != id))
{ {
if ((entry->Id() < objectId) && if ((entry->GetId() < objectId) &&
(entry->Id() > prevId)) prevId = entry->Id(); (entry->GetId() > prevId)) prevId = entry->GetId();
entry = entry->next; entry = entry->next;
} }
if (entry) break; if (entry) break;
} }
} while (i != endex); } while (i != endex);
if (entry) if (entry)
range_hi = entry->Id(); range_hi = entry->GetId();
else else
range_hi = prevId; range_hi = prevId;
range = range_hi - range_lo + 1; range = range_hi - range_lo + 1;
@ -2583,7 +2582,7 @@ bool NormObjectTable::Remove(const NormObject* theObject)
range = 0; range = 0;
} }
count--; count--;
size = size - theObject->Size(); size = size - theObject->GetSize();
return true; return true;
} }
else else
@ -2633,15 +2632,15 @@ NormObject* NormObjectTable::Iterator::GetNextObject()
offset++; offset++;
NormObjectId id = (UINT16)index + offset; NormObjectId id = (UINT16)index + offset;
NormObject* entry = table.table[i]; NormObject* entry = table.table[i];
while ((NULL != entry) && (entry->Id() != id)) while ((NULL != entry) && (entry->GetId() != id))
{ {
if ((entry->Id() > index) && (entry->Id() < nextId)) if ((entry->GetId() > index) && (entry->GetId() < nextId))
nextId = entry->Id(); nextId = entry->GetId();
entry = table.Next(entry); entry = table.Next(entry);
} }
if (entry) if (entry)
{ {
index = entry->Id(); index = entry->GetId();
return entry; return entry;
} }
} while (i != endex); } while (i != endex);
@ -2692,15 +2691,15 @@ NormObject* NormObjectTable::Iterator::GetPrevObject()
offset--; offset--;
NormObjectId id = (UINT16)index + offset; NormObjectId id = (UINT16)index + offset;
NormObject* entry = table.table[i]; NormObject* entry = table.table[i];
while ((NULL != entry ) && (entry->Id() != id)) while ((NULL != entry ) && (entry->GetId() != id))
{ {
if ((entry->Id() > index) && (entry->Id() < nextId)) if ((entry->GetId() > index) && (entry->GetId() < nextId))
nextId = entry->Id(); nextId = entry->GetId();
entry = table.Next(entry); entry = table.Next(entry);
} }
if (entry) if (entry)
{ {
index = entry->Id(); index = entry->GetId();
return entry; return entry;
} }
} while (i != endex); } while (i != endex);

View File

@ -32,11 +32,11 @@ class NormObject
// Object information // Object information
NormObject::Type GetType() const {return type;} NormObject::Type GetType() const {return type;}
const NormObjectId& Id() const {return id;} const NormObjectId& GetId() const {return transport_id;}
const NormObjectSize& Size() const {return object_size;} const NormObjectSize& GetSize() const {return object_size;}
bool HaveInfo() const {return (info_len > 0);} bool HaveInfo() const {return (info_len > 0);}
const char* GetInfo() const {return info;} const char* GetInfo() const {return info;}
UINT16 InfoLength() const {return info_len;} UINT16 GetInfoLength() const {return info_len;}
bool IsStream() const {return (STREAM == type);} bool IsStream() const {return (STREAM == type);}
NormNodeId LocalNodeId() const; NormNodeId LocalNodeId() const;
@ -127,7 +127,7 @@ class NormObject
NormSegmentId lastSegmentId, NormSegmentId lastSegmentId,
UINT16 numErasures) UINT16 numErasures)
{ {
NormBlockId blockId = theBlock->Id(); NormBlockId blockId = theBlock->GetId();
bool result = theBlock->TxUpdate(firstSegmentId, lastSegmentId, bool result = theBlock->TxUpdate(firstSegmentId, lastSegmentId,
GetBlockSize(blockId), nparity, GetBlockSize(blockId), nparity,
numErasures); numErasures);
@ -184,7 +184,7 @@ class NormObject
NormObject::Type type; NormObject::Type type;
class NormSession* session; class NormSession* session;
class NormServerNode* server; // NULL value indicates local (tx) object class NormServerNode* server; // NULL value indicates local (tx) object
NormObjectId id; NormObjectId transport_id;
NormObjectSize object_size; NormObjectSize object_size;
UINT16 segment_size; UINT16 segment_size;

View File

@ -104,28 +104,28 @@ NormBlock::~NormBlock()
Destroy(); Destroy();
} }
bool NormBlock::Init(UINT16 blockSize) bool NormBlock::Init(UINT16 totalSize)
{ {
if (segment_table) Destroy(); if (segment_table) Destroy();
if (!(segment_table = new char*[blockSize])) if (!(segment_table = new char*[totalSize]))
{ {
DMSG(0, "NormBlock::Init() segment_table allocation error: %s\n", strerror(errno)); DMSG(0, "NormBlock::Init() segment_table allocation error: %s\n", strerror(errno));
return false; return false;
} }
memset(segment_table, 0, blockSize*sizeof(char*)); memset(segment_table, 0, totalSize*sizeof(char*));
if (!pending_mask.Init(blockSize)) if (!pending_mask.Init(totalSize))
{ {
DMSG(0, "NormBlock::Init() pending_mask allocation error: %s\n", strerror(errno)); DMSG(0, "NormBlock::Init() pending_mask allocation error: %s\n", strerror(errno));
Destroy(); Destroy();
return false; return false;
} }
if (!repair_mask.Init(blockSize)) if (!repair_mask.Init(totalSize))
{ {
DMSG(0, "NormBlock::Init() repair_mask allocation error: %s\n", strerror(errno)); DMSG(0, "NormBlock::Init() repair_mask allocation error: %s\n", strerror(errno));
Destroy(); Destroy();
return false; return false;
} }
size = blockSize; size = totalSize;
erasure_count = 0; erasure_count = 0;
parity_count = 0; parity_count = 0;
parity_offset = 0;; parity_offset = 0;;
@ -173,16 +173,16 @@ bool NormBlock::IsEmpty() const
// Used by client side to determine if NACK should be sent // Used by client side to determine if NACK should be sent
// Note: This invalidates the block's "repair_mask" state // Note: This invalidates the block's "repair_mask" state
bool NormBlock::IsRepairPending(UINT16 ndata, UINT16 nparity) bool NormBlock::IsRepairPending(UINT16 numData, UINT16 numParity)
{ {
// Clients ask for a block of parity to fulfill their // Clients ask for a block of parity to fulfill their
// repair needs (erasure_count), but if there isn't // repair needs (erasure_count), but if there isn't
// enough parity, they ask for some data segments, too // enough parity, they ask for some data segments, too
if (erasure_count > nparity) if (erasure_count > numParity)
{ {
if (nparity) if (numParity)
{ {
UINT16 i = nparity; UINT16 i = numParity;
NormSegmentId nextId = 0; NormSegmentId nextId = 0;
GetFirstPending(nextId); GetFirstPending(nextId);
while (i--) while (i--)
@ -194,44 +194,44 @@ bool NormBlock::IsRepairPending(UINT16 ndata, UINT16 nparity)
GetNextPending(nextId); GetNextPending(nextId);
} }
} }
else if (size > ndata) else if (size > numData)
{ {
repair_mask.SetBits(ndata, size-ndata); repair_mask.SetBits(numData, size-numData);
} }
} }
else else
{ {
repair_mask.SetBits(0, ndata); repair_mask.SetBits(0, numData);
repair_mask.SetBits(ndata+erasure_count, nparity-erasure_count); repair_mask.SetBits(numData+erasure_count, numParity-erasure_count);
} }
repair_mask.XCopy(pending_mask); repair_mask.XCopy(pending_mask);
return (repair_mask.IsSet()); return (repair_mask.IsSet());
} // end NormBlock::IsRepairPending() } // end NormBlock::IsRepairPending()
// Called by server // Called by server
bool NormBlock::TxReset(UINT16 ndata, bool NormBlock::TxReset(UINT16 numData,
UINT16 nparity, UINT16 numParity,
UINT16 autoParity, UINT16 autoParity,
UINT16 segmentSize) UINT16 segmentSize)
{ {
bool increasedRepair = false; bool increasedRepair = false;
repair_mask.SetBits(0, ndata+autoParity); repair_mask.SetBits(0, numData+autoParity);
repair_mask.UnsetBits(ndata+autoParity, nparity-autoParity); repair_mask.UnsetBits(numData+autoParity, numParity-autoParity);
repair_mask.Xor(pending_mask); repair_mask.Xor(pending_mask);
if (repair_mask.IsSet()) if (repair_mask.IsSet())
{ {
increasedRepair = true; increasedRepair = true;
repair_mask.Clear(); repair_mask.Clear();
pending_mask.SetBits(0, ndata+autoParity); pending_mask.SetBits(0, numData+autoParity);
pending_mask.UnsetBits(ndata+autoParity, nparity-autoParity); pending_mask.UnsetBits(numData+autoParity, numParity-autoParity);
parity_offset = autoParity; // reset parity since we're resending this one parity_offset = autoParity; // reset parity since we're resending this one
parity_count = nparity; // no parity repair this repair cycle parity_count = numParity; // no parity repair this repair cycle
SetFlag(IN_REPAIR); SetFlag(IN_REPAIR);
if (!ParityReady(ndata)) // (TBD) only when incrementalParity == true if (!ParityReady(numData)) // (TBD) only when incrementalParity == true
{ {
// Clear _any_ existing incremental parity state // Clear _any_ existing incremental parity state
char** ptr = segment_table+ndata; char** ptr = segment_table+numData;
while (nparity--) while (numParity--)
{ {
if (*ptr) memset(*ptr, 0, segmentSize); if (*ptr) memset(*ptr, 0, segmentSize);
ptr++; ptr++;
@ -242,7 +242,7 @@ bool NormBlock::TxReset(UINT16 ndata,
return increasedRepair; return increasedRepair;
} // end NormBlock::TxReset() } // end NormBlock::TxReset()
bool NormBlock::ActivateRepairs(UINT16 nparity) bool NormBlock::ActivateRepairs(UINT16 numParity)
{ {
if (repair_mask.IsSet()) if (repair_mask.IsSet())
{ {
@ -260,14 +260,14 @@ bool NormBlock::ActivateRepairs(UINT16 nparity)
// (we directly update the "pending_mask" for blocks/segments // (we directly update the "pending_mask" for blocks/segments
// greater than our current transmit index) // greater than our current transmit index)
bool NormBlock::TxUpdate(NormSegmentId nextId, NormSegmentId lastId, bool NormBlock::TxUpdate(NormSegmentId nextId, NormSegmentId lastId,
UINT16 ndata, UINT16 nparity, UINT16 erasureCount) UINT16 numData, UINT16 numParity, UINT16 erasureCount)
{ {
bool increasedRepair = false; bool increasedRepair = false;
if (nextId < ndata) if (nextId < numData)
{ {
// Explicit data repair request // Explicit data repair request
parity_offset = parity_count = nparity; parity_offset = parity_count = numParity;
while (nextId <= lastId) while (nextId <= lastId)
{ {
if (!pending_mask.Test(nextId)) if (!pending_mask.Test(nextId))
@ -281,13 +281,13 @@ bool NormBlock::TxUpdate(NormSegmentId nextId, NormSegmentId lastId,
else else
{ {
// parity repair request // parity repair request
UINT16 parityAvailable = nparity - parity_offset; UINT16 parityAvailable = numParity - parity_offset;
if (erasureCount <= parityAvailable) if (erasureCount <= parityAvailable)
{ {
// Use fresh parity for repair // Use fresh parity for repair
if (erasureCount > parity_count) if (erasureCount > parity_count)
{ {
pending_mask.SetBits(ndata+parity_offset+parity_count, pending_mask.SetBits(numData+parity_offset+parity_count,
erasureCount - parity_count); erasureCount - parity_count);
parity_count = erasureCount; parity_count = erasureCount;
increasedRepair = true; increasedRepair = true;
@ -299,7 +299,7 @@ bool NormBlock::TxUpdate(NormSegmentId nextId, NormSegmentId lastId,
if (parity_count < parityAvailable) if (parity_count < parityAvailable)
{ {
UINT16 count = parityAvailable - parity_count; UINT16 count = parityAvailable - parity_count;
pending_mask.SetBits(ndata+parity_offset+parity_count, count); pending_mask.SetBits(numData+parity_offset+parity_count, count);
parity_count = parityAvailable; parity_count = parityAvailable;
nextId += parityAvailable; nextId += parityAvailable;
increasedRepair = true; increasedRepair = true;
@ -320,15 +320,15 @@ bool NormBlock::TxUpdate(NormSegmentId nextId, NormSegmentId lastId,
} // end NormBlock::TxUpdate() } // end NormBlock::TxUpdate()
bool NormBlock::HandleSegmentRequest(NormSegmentId nextId, NormSegmentId lastId, bool NormBlock::HandleSegmentRequest(NormSegmentId nextId, NormSegmentId lastId,
UINT16 ndata, UINT16 nparity, UINT16 erasureCount) UINT16 numData, UINT16 numParity, UINT16 erasureCount)
{ {
DMSG(6, "NormBlock::HandleSegmentRequest() blk>%lu seg>%hu:%hu erasures:%hu\n", DMSG(6, "NormBlock::HandleSegmentRequest() blk>%lu seg>%hu:%hu erasures:%hu\n",
(UINT32)id, (UINT16)nextId, (UINT16)lastId, erasureCount); (UINT32)id, (UINT16)nextId, (UINT16)lastId, erasureCount);
bool increasedRepair = false; bool increasedRepair = false;
if (nextId < ndata) if (nextId < numData)
{ {
// Explicit data repair request // Explicit data repair request
parity_count = parity_offset = nparity; parity_count = parity_offset = numParity;
while (nextId <= lastId) while (nextId <= lastId)
{ {
if (!repair_mask.Test(nextId)) if (!repair_mask.Test(nextId))
@ -342,13 +342,13 @@ bool NormBlock::HandleSegmentRequest(NormSegmentId nextId, NormSegmentId lastId,
else else
{ {
// parity repair request // parity repair request
UINT16 parityAvailable = nparity - parity_offset; UINT16 parityAvailable = numParity - parity_offset;
if (erasureCount <= parityAvailable) if (erasureCount <= parityAvailable)
{ {
// Use fresh parity for repair // Use fresh parity for repair
if (erasureCount > parity_count) if (erasureCount > parity_count)
{ {
repair_mask.SetBits(ndata+parity_offset+parity_count, repair_mask.SetBits(numData+parity_offset+parity_count,
erasureCount - parity_count); erasureCount - parity_count);
parity_count = erasureCount; parity_count = erasureCount;
increasedRepair = true; increasedRepair = true;
@ -360,7 +360,7 @@ bool NormBlock::HandleSegmentRequest(NormSegmentId nextId, NormSegmentId lastId,
if (parity_count < parityAvailable) if (parity_count < parityAvailable)
{ {
UINT16 count = parityAvailable - parity_count; UINT16 count = parityAvailable - parity_count;
repair_mask.SetBits(ndata+parity_offset+parity_count, count); repair_mask.SetBits(numData+parity_offset+parity_count, count);
parity_count = parityAvailable; parity_count = parityAvailable;
nextId += parityAvailable; nextId += parityAvailable;
increasedRepair = true; increasedRepair = true;
@ -384,7 +384,7 @@ bool NormBlock::HandleSegmentRequest(NormSegmentId nextId, NormSegmentId lastId,
bool NormBlock::AppendRepairAdv(NormCmdRepairAdvMsg& cmd, bool NormBlock::AppendRepairAdv(NormCmdRepairAdvMsg& cmd,
NormObjectId objectId, NormObjectId objectId,
bool repairInfo, bool repairInfo,
UINT16 ndata, UINT16 numData,
UINT16 segmentSize) UINT16 segmentSize)
{ {
NormRepairRequest req; NormRepairRequest req;
@ -393,18 +393,18 @@ bool NormBlock::AppendRepairAdv(NormCmdRepairAdvMsg& cmd,
NormSymbolId nextId = 0; NormSymbolId nextId = 0;
if (GetFirstRepair(nextId)) if (GetFirstRepair(nextId))
{ {
UINT16 blockSize = size; UINT16 totalSize = size;
NormRepairRequest::Form prevForm = NormRepairRequest::INVALID; NormRepairRequest::Form prevForm = NormRepairRequest::INVALID;
UINT16 segmentCount = 0; UINT16 segmentCount = 0;
UINT16 firstId = 0; UINT16 firstId = 0;
while (nextId < blockSize) while (nextId < totalSize)
{ {
UINT16 currentId = nextId; UINT16 currentId = nextId;
if (!GetNextRepair(++nextId)) nextId = blockSize; if (!GetNextRepair(++nextId)) nextId = totalSize;
if (!segmentCount) firstId = currentId; if (!segmentCount) firstId = currentId;
segmentCount++; segmentCount++;
// Check for break in consecutive series or end // Check for break in consecutive series or end
if (((nextId - currentId) > 1) || (nextId >= blockSize)) if (((nextId - currentId) > 1) || (nextId >= totalSize))
{ {
NormRepairRequest::Form form; NormRepairRequest::Form form;
switch (segmentCount) switch (segmentCount)
@ -434,13 +434,13 @@ bool NormBlock::AppendRepairAdv(NormCmdRepairAdvMsg& cmd,
ASSERT(0); // can't happen ASSERT(0); // can't happen
break; break;
case NormRepairRequest::ITEMS: case NormRepairRequest::ITEMS:
req.AppendRepairItem(objectId, id, ndata, firstId); req.AppendRepairItem(objectId, id, numData, firstId);
if (2 == segmentCount) if (2 == segmentCount)
req.AppendRepairItem(objectId, id, ndata, currentId); req.AppendRepairItem(objectId, id, numData, currentId);
break; break;
case NormRepairRequest::RANGES: case NormRepairRequest::RANGES:
req.AppendRepairRange(objectId, id, ndata, firstId, req.AppendRepairRange(objectId, id, numData, firstId,
objectId, id, ndata, currentId); objectId, id, numData, currentId);
break; break;
case NormRepairRequest::ERASURES: case NormRepairRequest::ERASURES:
// erasure counts not used // erasure counts not used
@ -448,7 +448,7 @@ bool NormBlock::AppendRepairAdv(NormCmdRepairAdvMsg& cmd,
} }
segmentCount = 0; segmentCount = 0;
} }
} // end while (nextId < blockSize) } // end while (nextId < totalSize)
if (NormRepairRequest::INVALID != prevForm) if (NormRepairRequest::INVALID != prevForm)
cmd.PackRepairRequest(req); // (TBD) error check cmd.PackRepairRequest(req); // (TBD) error check
} }
@ -457,32 +457,32 @@ bool NormBlock::AppendRepairAdv(NormCmdRepairAdvMsg& cmd,
// Called by client // Called by client
bool NormBlock::AppendRepairRequest(NormNackMsg& nack, bool NormBlock::AppendRepairRequest(NormNackMsg& nack,
UINT16 ndata, UINT16 numData,
UINT16 nparity, UINT16 numParity,
NormObjectId objectId, NormObjectId objectId,
bool pendingInfo, bool pendingInfo,
UINT16 segmentSize) UINT16 segmentSize)
{ {
NormSegmentId nextId = 0; NormSegmentId nextId = 0;
NormSegmentId endId; NormSegmentId endId;
if (erasure_count > nparity) if (erasure_count > numParity)
{ {
// Request explicit repair // Request explicit repair
GetFirstPending(nextId); GetFirstPending(nextId);
UINT16 i = nparity; UINT16 i = numParity;
// Skip nparity missing data segments // Skip numParity missing data segments
while (i--) while (i--)
{ {
nextId++; nextId++;
GetNextPending(nextId); GetNextPending(nextId);
} }
endId = ndata + nparity; endId = numData + numParity;
} }
else else
{ {
nextId = ndata; nextId = numData;
GetNextPending(nextId); GetNextPending(nextId);
endId = ndata + erasure_count; endId = numData + erasure_count;
} }
NormRepairRequest req; NormRepairRequest req;
req.SetFlag(NormRepairRequest::SEGMENT); req.SetFlag(NormRepairRequest::SEGMENT);
@ -528,13 +528,13 @@ bool NormBlock::AppendRepairRequest(NormNackMsg& nack,
ASSERT(0); ASSERT(0);
break; break;
case NormRepairRequest::ITEMS: case NormRepairRequest::ITEMS:
req.AppendRepairItem(objectId, id, ndata, firstId); // (TBD) error check req.AppendRepairItem(objectId, id, numData, firstId); // (TBD) error check
if (2 == segmentCount) if (2 == segmentCount)
req.AppendRepairItem(objectId, id, ndata, currentId); // (TBD) error check req.AppendRepairItem(objectId, id, numData, currentId); // (TBD) error check
break; break;
case NormRepairRequest::RANGES: case NormRepairRequest::RANGES:
req.AppendRepairRange(objectId, id, ndata, firstId, // (TBD) error check req.AppendRepairRange(objectId, id, numData, firstId, // (TBD) error check
objectId, id, ndata, currentId); // (TBD) error check objectId, id, numData, currentId); // (TBD) error check
break; break;
case NormRepairRequest::ERASURES: case NormRepairRequest::ERASURES:
// erasure counts not used // erasure counts not used
@ -627,7 +627,7 @@ NormBlockPool::~NormBlockPool()
Destroy(); Destroy();
} }
bool NormBlockPool::Init(UINT32 numBlocks, UINT16 blockSize) bool NormBlockPool::Init(UINT32 numBlocks, UINT16 totalSize)
{ {
if (head) Destroy(); if (head) Destroy();
for (UINT32 i = 0; i < numBlocks; i++) for (UINT32 i = 0; i < numBlocks; i++)
@ -635,7 +635,7 @@ bool NormBlockPool::Init(UINT32 numBlocks, UINT16 blockSize)
NormBlock* b = new NormBlock(); NormBlock* b = new NormBlock();
if (b) if (b)
{ {
if (!b->Init(blockSize)) if (!b->Init(totalSize))
{ {
DMSG(0, "NormBlockPool::Init() block init error\n"); DMSG(0, "NormBlockPool::Init() block init error\n");
delete b; delete b;
@ -723,7 +723,7 @@ NormBlock* NormBlockBuffer::Find(const NormBlockId& blockId) const
if ((blockId < range_lo) || (blockId > range_hi)) if ((blockId < range_lo) || (blockId > range_hi))
return (NormBlock*)NULL; return (NormBlock*)NULL;
NormBlock* theBlock = table[((UINT32)blockId) & hash_mask]; NormBlock* theBlock = table[((UINT32)blockId) & hash_mask];
while (theBlock && (blockId != theBlock->Id())) while (theBlock && (blockId != theBlock->GetId()))
theBlock = theBlock->next; theBlock = theBlock->next;
return theBlock; return theBlock;
} }
@ -766,7 +766,7 @@ bool NormBlockBuffer::CanInsert(NormBlockId blockId) const
bool NormBlockBuffer::Insert(NormBlock* theBlock) bool NormBlockBuffer::Insert(NormBlock* theBlock)
{ {
const NormBlockId& blockId = theBlock->Id(); const NormBlockId& blockId = theBlock->GetId();
if (!range) if (!range)
{ {
range_lo = range_hi = blockId; range_lo = range_hi = blockId;
@ -789,7 +789,7 @@ bool NormBlockBuffer::Insert(NormBlock* theBlock)
UINT32 index = ((UINT32)blockId) & hash_mask; UINT32 index = ((UINT32)blockId) & hash_mask;
NormBlock* prev = NULL; NormBlock* prev = NULL;
NormBlock* entry = table[index]; NormBlock* entry = table[index];
while (entry && (entry->Id() < blockId)) while (entry && (entry->GetId() < blockId))
{ {
prev = entry; prev = entry;
entry = entry->next; entry = entry->next;
@ -799,7 +799,7 @@ bool NormBlockBuffer::Insert(NormBlock* theBlock)
else else
table[index] = theBlock; table[index] = theBlock;
ASSERT((entry ? (blockId != entry->Id()) : true)); ASSERT((entry ? (blockId != entry->GetId()) : true));
theBlock->next = entry; theBlock->next = entry;
return true; return true;
@ -810,12 +810,12 @@ bool NormBlockBuffer::Remove(const NormBlock* theBlock)
ASSERT(theBlock); ASSERT(theBlock);
if (range) if (range)
{ {
const NormBlockId& blockId = theBlock->Id(); const NormBlockId& blockId = theBlock->GetId();
if ((blockId < range_lo) || (blockId > range_hi)) return false; if ((blockId < range_lo) || (blockId > range_hi)) return false;
UINT32 index = ((UINT32)blockId) & hash_mask; UINT32 index = ((UINT32)blockId) & hash_mask;
NormBlock* prev = NULL; NormBlock* prev = NULL;
NormBlock* entry = table[index]; NormBlock* entry = table[index];
while (entry && (entry->Id() != blockId)) while (entry && (entry->GetId() != blockId))
{ {
prev = entry; prev = entry;
entry = entry->next; entry = entry->next;
@ -847,10 +847,10 @@ bool NormBlockBuffer::Remove(const NormBlock* theBlock)
if ((entry = table[i])) if ((entry = table[i]))
{ {
NormBlockId id = (UINT32)index + offset; NormBlockId id = (UINT32)index + offset;
while(entry && (entry->Id() != id)) while(entry && (entry->GetId() != id))
{ {
if ((entry->Id() > blockId) && if ((entry->GetId() > blockId) &&
(entry->Id() < nextId)) nextId = entry->Id(); (entry->GetId() < nextId)) nextId = entry->GetId();
entry = entry->next; entry = entry->next;
} }
@ -858,7 +858,7 @@ bool NormBlockBuffer::Remove(const NormBlock* theBlock)
} }
} while (i != endex); } while (i != endex);
if (entry) if (entry)
range_lo = entry->Id(); range_lo = entry->GetId();
else else
range_lo = nextId; range_lo = nextId;
range = range_hi - range_lo + 1; range = range_hi - range_lo + 1;
@ -884,17 +884,17 @@ bool NormBlockBuffer::Remove(const NormBlock* theBlock)
{ {
NormBlockId id = (UINT32)index - offset; NormBlockId id = (UINT32)index - offset;
//printf("Looking for id:%lu at index:%lu\n", (UINT32)id, i); //printf("Looking for id:%lu at index:%lu\n", (UINT32)id, i);
while(entry && (entry->Id() != id)) while(entry && (entry->GetId() != id))
{ {
if ((entry->Id() < blockId) && if ((entry->GetId() < blockId) &&
(entry->Id() > prevId)) prevId = entry->Id(); (entry->GetId() > prevId)) prevId = entry->GetId();
entry = entry->next; entry = entry->next;
} }
if (entry) break; if (entry) break;
} }
} while (i != endex); } while (i != endex);
if (entry) if (entry)
range_hi = entry->Id(); range_hi = entry->GetId();
else else
range_hi = prevId; range_hi = prevId;
range = range_hi - range_lo + 1; range = range_hi - range_lo + 1;
@ -954,15 +954,15 @@ NormBlock* NormBlockBuffer::Iterator::GetNextBlock()
NormBlockId id = (UINT32)index + offset; NormBlockId id = (UINT32)index + offset;
ASSERT(i < 256); ASSERT(i < 256);
NormBlock* entry = buffer.table[i]; NormBlock* entry = buffer.table[i];
while ((NULL != entry ) && (entry->Id() != id)) while ((NULL != entry ) && (entry->GetId() != id))
{ {
if ((entry->Id() > index) && (entry->Id() < nextId)) if ((entry->GetId() > index) && (entry->GetId() < nextId))
nextId = entry->Id(); nextId = entry->GetId();
entry = NormBlockBuffer::Next(entry); entry = NormBlockBuffer::Next(entry);
} }
if (entry) if (entry)
{ {
index = entry->Id(); index = entry->GetId();
return entry; return entry;
} }
} while (i != endex); } while (i != endex);

View File

@ -56,9 +56,9 @@ class NormBlock
NormBlock(); NormBlock();
~NormBlock(); ~NormBlock();
const NormBlockId& Id() const {return id;} const NormBlockId& GetId() const {return id;}
void SetId(NormBlockId& x) {id = x;} void SetId(NormBlockId& x) {id = x;}
bool Init(UINT16 blockSize); bool Init(UINT16 totalSize);
void Destroy(); void Destroy();
void SetFlag(NormBlock::Flag flag) {flags |= flag;} void SetFlag(NormBlock::Flag flag) {flags |= flag;}
@ -134,7 +134,7 @@ class NormBlock
bool AppendRepairAdv(NormCmdRepairAdvMsg& cmd, bool AppendRepairAdv(NormCmdRepairAdvMsg& cmd,
NormObjectId objectId, NormObjectId objectId,
bool repairInfo, bool repairInfo,
UINT16 ndata, UINT16 numData,
UINT16 segmentSize); UINT16 segmentSize);
// Client routines // Client routines
@ -217,8 +217,8 @@ class NormBlock
{return (pending_mask.IsSet() || repair_mask.IsSet());} {return (pending_mask.IsSet() || repair_mask.IsSet());}
bool AppendRepairRequest(NormNackMsg& nack, bool AppendRepairRequest(NormNackMsg& nack,
UINT16 ndata, UINT16 numData,
UINT16 nparity, UINT16 numParity,
NormObjectId objectId, NormObjectId objectId,
bool pendingInfo, bool pendingInfo,
UINT16 segmentSize); UINT16 segmentSize);
@ -248,7 +248,7 @@ class NormBlockPool
public: public:
NormBlockPool(); NormBlockPool();
~NormBlockPool(); ~NormBlockPool();
bool Init(UINT32 numBlocks, UINT16 blockSize); bool Init(UINT32 numBlocks, UINT16 totalSize);
void Destroy(); void Destroy();
bool IsEmpty() const {return (NULL == head);} bool IsEmpty() const {return (NULL == head);}
NormBlock* Get() NormBlock* Get()

View File

@ -21,7 +21,7 @@ NormSession::NormSession(NormSessionMgr& sessionMgr, NormNodeId localNodeId)
ttl(DEFAULT_TTL), tx_rate(DEFAULT_TRANSMIT_RATE/8.0), ttl(DEFAULT_TTL), tx_rate(DEFAULT_TRANSMIT_RATE/8.0),
backoff_factor(DEFAULT_BACKOFF_FACTOR), is_server(false), session_id(0), backoff_factor(DEFAULT_BACKOFF_FACTOR), is_server(false), session_id(0),
ndata(DEFAULT_NDATA), nparity(DEFAULT_NPARITY), auto_parity(0), extra_parity(0), ndata(DEFAULT_NDATA), nparity(DEFAULT_NPARITY), auto_parity(0), extra_parity(0),
next_tx_object_id(0), tx_cache_count_min(1), tx_cache_count_max(256), next_tx_object_id(0), tx_cache_count_min(8), tx_cache_count_max(256),
tx_cache_size_max((UINT32)20*1024*1024), tx_cache_size_max((UINT32)20*1024*1024),
flush_count(NORM_ROBUST_FACTOR+1), flush_count(NORM_ROBUST_FACTOR+1),
posted_tx_queue_empty(false), advertise_repairs(false), posted_tx_queue_empty(false), advertise_repairs(false),
@ -72,7 +72,7 @@ NormSession::NormSession(NormSessionMgr& sessionMgr, NormNodeId localNodeId)
// (It may be used to trigger transmission of report messages // (It may be used to trigger transmission of report messages
// in the future for debugging, etc // in the future for debugging, etc
report_timer.SetListener(this, &NormSession::OnReportTimeout); report_timer.SetListener(this, &NormSession::OnReportTimeout);
report_timer.SetInterval(10.0); report_timer.SetInterval(60.0);
report_timer.SetRepeat(-1); report_timer.SetRepeat(-1);
} }
@ -233,6 +233,8 @@ bool NormSession::StartServer(unsigned long bufferSpace,
flush_count = NORM_ROBUST_FACTOR+1; // (TBD) parameterize robust_factor flush_count = NORM_ROBUST_FACTOR+1; // (TBD) parameterize robust_factor
//probe_timer.SetInterval(0.0); //probe_timer.SetInterval(0.0);
probe_pending = probe_reset = false; probe_pending = probe_reset = false;
if (cc_enable) tx_rate = segmentSize;
OnProbeTimeout(probe_timer); OnProbeTimeout(probe_timer);
ActivateTimer(probe_timer); ActivateTimer(probe_timer);
return true; return true;
@ -317,7 +319,7 @@ void NormSession::Serve()
if (obj->IsStream()) if (obj->IsStream())
posted_tx_queue_empty = true; // repair-delayed stream advance posted_tx_queue_empty = true; // repair-delayed stream advance
else else
tx_pending_mask.Unset(obj->Id()); tx_pending_mask.Unset(obj->GetId());
} }
} }
else else
@ -379,13 +381,13 @@ void NormSession::ServerQueueFlush()
if (obj->IsStream()) if (obj->IsStream())
{ {
NormStreamObject* stream = (NormStreamObject*)obj; NormStreamObject* stream = (NormStreamObject*)obj;
objectId = stream->Id(); objectId = stream->GetId();
blockId = stream->FlushBlockId(); blockId = stream->FlushBlockId();
segmentId = stream->FlushSegmentId(); segmentId = stream->FlushSegmentId();
} }
else else
{ {
objectId = obj->Id(); objectId = obj->GetId();
blockId = obj->GetFinalBlockId(); blockId = obj->GetFinalBlockId();
segmentId = obj->GetBlockSize(blockId) - 1; segmentId = obj->GetBlockSize(blockId) - 1;
} }
@ -579,7 +581,7 @@ bool NormSession::QueueTxObject(NormObject* obj, bool touchServer)
unsigned long count = tx_table.Count(); unsigned long count = tx_table.Count();
while ((count >= tx_cache_count_min) && while ((count >= tx_cache_count_min) &&
((count >= tx_cache_count_max) || ((count >= tx_cache_count_max) ||
((tx_table.Size() + obj->Size()) > tx_cache_size_max))) ((tx_table.Size() + obj->GetSize()) > tx_cache_size_max)))
{ {
// Remove oldest non-pending // Remove oldest non-pending
NormObject* oldest = tx_table.Find(tx_table.RangeLo()); NormObject* oldest = tx_table.Find(tx_table.RangeLo());
@ -605,8 +607,8 @@ bool NormSession::QueueTxObject(NormObject* obj, bool touchServer)
ASSERT(0); ASSERT(0);
return false; return false;
} }
tx_pending_mask.Set(obj->Id()); tx_pending_mask.Set(obj->GetId());
ASSERT(tx_pending_mask.Test(obj->Id())); ASSERT(tx_pending_mask.Test(obj->GetId()));
next_tx_object_id++; next_tx_object_id++;
TouchServer(); TouchServer();
//posted_tx_queue_empty = false; //posted_tx_queue_empty = false;
@ -616,7 +618,7 @@ bool NormSession::QueueTxObject(NormObject* obj, bool touchServer)
void NormSession::DeleteTxObject(NormObject* obj) void NormSession::DeleteTxObject(NormObject* obj)
{ {
NormObjectId objectId = obj->Id(); NormObjectId objectId = obj->GetId();
ASSERT(obj == tx_table.Find(objectId)); ASSERT(obj == tx_table.Find(objectId));
tx_table.Remove(obj); tx_table.Remove(obj);
obj->Close(); obj->Close();
@ -637,7 +639,7 @@ NormBlock* NormSession::ServerGetFreeBlock(NormObjectId objectId,
NormObject* obj; NormObject* obj;
while ((obj = iterator.GetNextObject())) while ((obj = iterator.GetNextObject()))
{ {
if (obj->Id() == objectId) if (obj->GetId() == objectId)
b = obj->StealNonPendingBlock(true, blockId); b = obj->StealNonPendingBlock(true, blockId);
else else
b = obj->StealNonPendingBlock(false); b = obj->StealNonPendingBlock(false);
@ -656,13 +658,13 @@ NormBlock* NormSession::ServerGetFreeBlock(NormObjectId objectId,
NormObject* obj; NormObject* obj;
while ((obj = iterator.GetPrevObject())) while ((obj = iterator.GetPrevObject()))
{ {
if (obj->Id() < objectId) if (obj->GetId() < objectId)
{ {
break; break;
} }
else else
{ {
if (obj->Id() > objectId) if (obj->GetId() > objectId)
b = obj->StealNewestBlock(false); b = obj->StealNewestBlock(false);
else else
b = obj->StealNewestBlock(true, blockId); b = obj->StealNewestBlock(true, blockId);
@ -888,34 +890,21 @@ void NormSession::HandleReceiveMessage(NormMsg& msg, bool wasUnicast)
if (trace) NormTrace(currentTime, LocalNodeId(), msg, false); if (trace) NormTrace(currentTime, LocalNodeId(), msg, false);
// Do common updates for servers we already know.
NormNodeId sourceId = msg.GetSourceId();
NormServerNode* theServer = (NormServerNode*)server_tree.FindNodeById(sourceId);
if (theServer)
{
// (TBD) combine these as needed for efficiency
// (i.e. fewer function calls per message)
if (theServer->IsOpen()) theServer->Activate();
theServer->UpdateRecvRate(currentTime, msg.GetLength());
theServer->UpdateLossEstimate(currentTime, msg.GetSequence());
theServer->SetAddress(msg.GetSource());
// for statistics only (TBD) #ifdef NORM_DEBUG
theServer->IncrementRecvTotal(msg.GetLength());
}
switch (msg.GetType()) switch (msg.GetType())
{ {
case NormMsg::INFO: case NormMsg::INFO:
//DMSG(0, "NormSession::HandleReceiveMessage(NormMsg::INFO)\n"); //DMSG(0, "NormSession::HandleReceiveMessage(NormMsg::INFO)\n");
if (IsClient()) ClientHandleObjectMessage(currentTime, (NormObjectMsg&)msg, theServer); if (IsClient()) ClientHandleObjectMessage(currentTime, (NormObjectMsg&)msg);
break; break;
case NormMsg::DATA: case NormMsg::DATA:
//DMSG(0, "NormSession::HandleReceiveMessage(NormMsg::DATA) ...\n"); //DMSG(0, "NormSession::HandleReceiveMessage(NormMsg::DATA) ...\n");
if (IsClient()) ClientHandleObjectMessage(currentTime, (NormObjectMsg&)msg, theServer); if (IsClient()) ClientHandleObjectMessage(currentTime, (NormObjectMsg&)msg);
break; break;
case NormMsg::CMD: case NormMsg::CMD:
//DMSG(0, "NormSession::HandleReceiveMessage(NormMsg::CMD) ...\n"); //DMSG(0, "NormSession::HandleReceiveMessage(NormMsg::CMD) ...\n");
if (IsClient()) ClientHandleCommand(currentTime, (NormCmdMsg&)msg, theServer); if (IsClient()) ClientHandleCommand(currentTime, (NormCmdMsg&)msg);
break; break;
case NormMsg::NACK: case NormMsg::NACK:
DMSG(4, "NormSession::HandleReceiveMessage(NormMsg::NACK) node>%lu ...\n", DMSG(4, "NormSession::HandleReceiveMessage(NormMsg::NACK) node>%lu ...\n",
@ -923,7 +912,7 @@ void NormSession::HandleReceiveMessage(NormMsg& msg, bool wasUnicast)
if (IsServer() && (((NormNackMsg&)msg).GetServerId() == LocalNodeId())) if (IsServer() && (((NormNackMsg&)msg).GetServerId() == LocalNodeId()))
{ {
ServerHandleNackMessage(currentTime, (NormNackMsg&)msg); ServerHandleNackMessage(currentTime, (NormNackMsg&)msg);
if (wasUnicast && (backoff_factor > 0.5)) if (wasUnicast && (backoff_factor > 0.5) && Address().IsMulticast())
{ {
// for suppression of unicast nack feedback // for suppression of unicast nack feedback
advertise_repairs = true; advertise_repairs = true;
@ -952,9 +941,11 @@ void NormSession::HandleReceiveMessage(NormMsg& msg, bool wasUnicast)
void NormSession::ClientHandleObjectMessage(const struct timeval& currentTime, void NormSession::ClientHandleObjectMessage(const struct timeval& currentTime,
const NormObjectMsg& msg, const NormObjectMsg& msg)
NormServerNode* theServer)
{ {
// Do common updates for servers we already know.
NormNodeId sourceId = msg.GetSourceId();
NormServerNode* theServer = (NormServerNode*)server_tree.FindNodeById(sourceId);
if (!theServer) if (!theServer)
{ {
if ((theServer = new NormServerNode(this, msg.GetSourceId()))) if ((theServer = new NormServerNode(this, msg.GetSourceId())))
@ -962,11 +953,6 @@ void NormSession::ClientHandleObjectMessage(const struct timeval& currentTime,
server_tree.AttachNode(theServer); server_tree.AttachNode(theServer);
DMSG(4, "NormSession::ClientHandleObjectMessage() node>%lu new remote server:%lu ...\n", DMSG(4, "NormSession::ClientHandleObjectMessage() node>%lu new remote server:%lu ...\n",
LocalNodeId(), msg.GetSourceId()); LocalNodeId(), msg.GetSourceId());
theServer->UpdateRecvRate(currentTime, msg.GetLength());
theServer->UpdateLossEstimate(currentTime, msg.GetSequence());
theServer->SetAddress(msg.GetSource());
// for statistics only (TBD) #ifdef NORM_DEBUG
theServer->IncrementRecvTotal(msg.GetLength());
} }
else else
{ {
@ -976,13 +962,20 @@ void NormSession::ClientHandleObjectMessage(const struct timeval& currentTime,
return; return;
} }
} }
if (theServer->IsOpen()) theServer->Activate();
theServer->UpdateLossEstimate(currentTime, msg.GetSequence());
theServer->SetAddress(msg.GetSource());
theServer->IncrementRecvTotal(msg.GetLength()); // for statistics only (TBD) #ifdef NORM_DEBUG
theServer->HandleObjectMessage(msg); theServer->HandleObjectMessage(msg);
theServer->UpdateRecvRate(currentTime, msg.GetLength());
} // end NormSession::ClientHandleObjectMessage() } // end NormSession::ClientHandleObjectMessage()
void NormSession::ClientHandleCommand(const struct timeval& currentTime, void NormSession::ClientHandleCommand(const struct timeval& currentTime,
const NormCmdMsg& cmd, const NormCmdMsg& cmd)
NormServerNode* theServer)
{ {
// Do common updates for servers we already know.
NormNodeId sourceId = cmd.GetSourceId();
NormServerNode* theServer = (NormServerNode*)server_tree.FindNodeById(sourceId);
if (!theServer) if (!theServer)
{ {
//DMSG(0, "NormSession::ClientHandleCommand() node>%lu recvd command from unknown server ...\n", //DMSG(0, "NormSession::ClientHandleCommand() node>%lu recvd command from unknown server ...\n",
@ -993,11 +986,6 @@ void NormSession::ClientHandleCommand(const struct timeval& currentTime,
server_tree.AttachNode(theServer); server_tree.AttachNode(theServer);
DMSG(4, "NormSession::ClientHandleCommand() node>%lu new remote server:%lu ...\n", DMSG(4, "NormSession::ClientHandleCommand() node>%lu new remote server:%lu ...\n",
LocalNodeId(), cmd.GetSourceId()); LocalNodeId(), cmd.GetSourceId());
theServer->UpdateRecvRate(currentTime, cmd.GetLength());
theServer->UpdateLossEstimate(currentTime, cmd.GetSequence());
theServer->SetAddress(cmd.GetSource());
// for statistics only (TBD) #ifdef NORM_DEBUG
theServer->IncrementRecvTotal(cmd.GetLength());
} }
else else
{ {
@ -1007,7 +995,12 @@ void NormSession::ClientHandleCommand(const struct timeval& currentTime,
return; return;
} }
} }
if (theServer->IsOpen()) theServer->Activate();
theServer->UpdateLossEstimate(currentTime, cmd.GetSequence());
theServer->SetAddress(cmd.GetSource());
theServer->IncrementRecvTotal(cmd.GetLength()); // for statistics only (TBD) #ifdef NORM_DEBUG
theServer->HandleCommand(currentTime, cmd); theServer->HandleCommand(currentTime, cmd);
theServer->UpdateRecvRate(currentTime, cmd.GetLength());
} // end NormSession::ClientHandleCommand() } // end NormSession::ClientHandleCommand()
@ -1046,16 +1039,16 @@ double NormSession::CalculateRtt(const struct timeval& currentTime,
void NormSession::ServerUpdateGrttEstimate(double clientRtt) void NormSession::ServerUpdateGrttEstimate(double clientRtt)
{ {
grtt_response = true; grtt_response = true;
if (clientRtt > grtt_current_peak) if ((clientRtt > grtt_current_peak) || !address.IsMulticast())
{ {
// Immediately incorporate bigger RTT's // Immediately incorporate bigger RTT's
grtt_current_peak = clientRtt; grtt_current_peak = clientRtt;
if (clientRtt > grtt_measured) if ((clientRtt > grtt_measured) || !address.IsMulticast())
{ {
grtt_decrease_delay_count = DEFAULT_GRTT_DECREASE_DELAY; grtt_decrease_delay_count = DEFAULT_GRTT_DECREASE_DELAY;
grtt_measured = 0.25 * grtt_measured + 0.75 * clientRtt; grtt_measured = 0.25 * grtt_measured + 0.75 * clientRtt;
if (grtt_measured > grtt_max) grtt_measured = grtt_max; if (grtt_measured > grtt_max) grtt_measured = grtt_max;
double pktInterval = 2.0 * ((double)(44+segment_size))/tx_rate; double pktInterval = ((double)(44+segment_size))/tx_rate;
UINT8 grttQuantizedOld = grtt_quantized; UINT8 grttQuantizedOld = grtt_quantized;
grtt_quantized = NormQuantizeRtt(MAX(pktInterval, grtt_measured)); grtt_quantized = NormQuantizeRtt(MAX(pktInterval, grtt_measured));
// Calculate grtt_advertised since quantization rounds upward // Calculate grtt_advertised since quantization rounds upward
@ -1104,6 +1097,7 @@ void NormSession::ServerHandleCCFeedback(NormNodeId nodeId,
// Adjust ccRtt if we have state on this nodeId // Adjust ccRtt if we have state on this nodeId
NormCCNode* node = (NormCCNode*)cc_node_list.FindNodeById(nodeId); NormCCNode* node = (NormCCNode*)cc_node_list.FindNodeById(nodeId);
if (node) ccRtt = node->UpdateRtt(ccRtt); if (node) ccRtt = node->UpdateRtt(ccRtt);
if (0 == (ccFlags & NormCC::START)) if (0 == (ccFlags & NormCC::START))
{ {
// slow start has ended // slow start has ended
@ -1287,7 +1281,7 @@ void NormSession::ServerHandleAckMessage(const struct timeval& currentTime, cons
break; break;
} }
if (wasUnicast && probe_proactive) if (wasUnicast && probe_proactive && Address().IsMulticast())
{ {
// for suppression of unicast feedback // for suppression of unicast feedback
advertise_repairs = true; advertise_repairs = true;
@ -1711,7 +1705,7 @@ void NormSession::ServerHandleNackMessage(const struct timeval& currentTime, Nor
else else
{ {
block->HandleSegmentRequest(nextSegmentId, lastSegmentId, block->HandleSegmentRequest(nextSegmentId, lastSegmentId,
object->GetBlockSize(block->Id()), object->GetBlockSize(block->GetId()),
nparity, numErasures); nparity, numErasures);
startTimer = true; startTimer = true;
} // end if/else (holdoff) } // end if/else (holdoff)
@ -1798,7 +1792,7 @@ bool NormSession::ServerQueueSquelch(NormObjectId objectId)
squelch->SetFecSymbolId(0); squelch->SetFecSymbolId(0);
squelch->ResetInvalidObjectList(); squelch->ResetInvalidObjectList();
while ((obj = iterator.GetNextObject())) while ((obj = iterator.GetNextObject()))
if (objectId == obj->Id()) break; if (objectId == obj->GetId()) break;
nextId = objectId + 1; nextId = objectId + 1;
} }
else else
@ -1806,13 +1800,13 @@ bool NormSession::ServerQueueSquelch(NormObjectId objectId)
obj = iterator.GetNextObject(); obj = iterator.GetNextObject();
if (obj) if (obj)
{ {
squelch->SetObjectId(obj->Id()); squelch->SetObjectId(obj->GetId());
if (obj->IsStream()) if (obj->IsStream())
squelch->SetFecBlockId(((NormStreamObject*)obj)->StreamBufferLo()); squelch->SetFecBlockId(((NormStreamObject*)obj)->StreamBufferLo());
else else
squelch->SetFecBlockId(0); squelch->SetFecBlockId(0);
squelch->SetFecSymbolId(0); squelch->SetFecSymbolId(0);
nextId = obj->Id() + 1; nextId = obj->GetId() + 1;
} }
else else
{ {
@ -1826,7 +1820,7 @@ bool NormSession::ServerQueueSquelch(NormObjectId objectId)
bool buildingList = true; bool buildingList = true;
while (buildingList && (obj = iterator.GetNextObject())) while (buildingList && (obj = iterator.GetNextObject()))
{ {
while (nextId != obj->Id()) while (nextId != obj->GetId())
{ {
if (!squelch->AppendInvalidObject(nextId, segment_size)) if (!squelch->AppendInvalidObject(nextId, segment_size))
{ {
@ -1864,7 +1858,7 @@ bool NormSession::ServerBuildRepairAdv(NormCmdRepairAdvMsg& cmd)
{ {
NormObject* currentObject = nextObject; NormObject* currentObject = nextObject;
nextObject = iterator.GetNextObject(); nextObject = iterator.GetNextObject();
NormObjectId currentId = currentObject->Id(); NormObjectId currentId = currentObject->GetId();
bool repairEntireObject = tx_repair_mask.Test(currentId); bool repairEntireObject = tx_repair_mask.Test(currentId);
if (repairEntireObject) if (repairEntireObject)
{ {
@ -1953,7 +1947,7 @@ bool NormSession::OnRepairTimeout(ProtoTimer& /*theTimer*/)
NormObject* obj; NormObject* obj;
while ((obj = iterator.GetNextObject())) while ((obj = iterator.GetNextObject()))
{ {
NormObjectId objectId = obj->Id(); NormObjectId objectId = obj->GetId();
if (tx_repair_mask.Test(objectId)) if (tx_repair_mask.Test(objectId))
{ {
DMSG(6, "NormSession::OnRepairTimeout() node>%lu tx reset obj>%hu ...\n", DMSG(6, "NormSession::OnRepairTimeout() node>%lu tx reset obj>%hu ...\n",
@ -2167,31 +2161,32 @@ bool NormSession::SendMessage(NormMsg& msg)
// Separate send/recv tracing // Separate send/recv tracing
if (trace) NormTrace(currentTime, LocalNodeId(), msg, true); if (trace) NormTrace(currentTime, LocalNodeId(), msg, true);
// Keep track of _actual_ sent rate // Keep track of _actual_ sent rate (TBD) we can do away with this now
double interval;
if (prev_update_time.tv_sec || prev_update_time.tv_usec) if (prev_update_time.tv_sec || prev_update_time.tv_usec)
{ {
interval = (double)(currentTime.tv_sec - prev_update_time.tv_sec); double interval = (double)(currentTime.tv_sec - prev_update_time.tv_sec);
if (currentTime.tv_usec > prev_update_time.tv_sec) if (currentTime.tv_usec > prev_update_time.tv_sec)
interval += 1.0e-06*(double)(currentTime.tv_usec - prev_update_time.tv_usec); interval += 1.0e-06*(double)(currentTime.tv_usec - prev_update_time.tv_usec);
else else
interval -= 1.0e-06*(double)(prev_update_time.tv_usec - currentTime.tv_usec); interval -= 1.0e-06*(double)(prev_update_time.tv_usec - currentTime.tv_usec);
sent_rate += 0.125 * (((double)msgSize)/interval - sent_rate);
prev_update_time = currentTime;
/*if (interval < grtt_advertised)
{
sent_accumulator += msgSize;
}
else
{
sent_rate = ((double)(sent_accumulator+msgSize)) / interval;
prev_update_time = currentTime;
sent_accumulator = 0;
}*/
} }
else else
{ {
sent_rate = ((double)msgSize) / grtt_advertised; sent_rate = ((double)msgSize) / grtt_advertised;
interval = -1.0; prev_update_time = currentTime;
prev_update_time = currentTime; sent_accumulator = msgSize;
}
if (interval < grtt_advertised)
{
sent_accumulator += msgSize;
}
else
{
sent_rate = ((double)(sent_accumulator+msgSize)) / interval;
prev_update_time = currentTime;
sent_accumulator = 0;
} }
// Update nominal packet size // Update nominal packet size
nominal_packet_size += 0.05 * (((double)msgSize) - nominal_packet_size); nominal_packet_size += 0.05 * (((double)msgSize) - nominal_packet_size);
@ -2224,7 +2219,7 @@ bool NormSession::OnProbeTimeout(ProtoTimer& /*theTimer*/)
probe_reset = true; probe_reset = true;
probe_timer.Deactivate(); probe_timer.Deactivate();
return false; return false;
} }
// 2) Update grtt_estimate _if_ sufficient time elapsed. // 2) Update grtt_estimate _if_ sufficient time elapsed.
// This new code allows more liberal downward adjustment of // This new code allows more liberal downward adjustment of
@ -2289,6 +2284,7 @@ bool NormSession::OnProbeTimeout(ProtoTimer& /*theTimer*/)
cmd->Init(); cmd->Init();
cmd->SetDestination(address); cmd->SetDestination(address);
cmd->SetGrtt(grtt_quantized); cmd->SetGrtt(grtt_quantized);
cmd->SetBackoffFactor((unsigned char)backoff_factor); cmd->SetBackoffFactor((unsigned char)backoff_factor);
cmd->SetGroupSize(gsize_quantized); cmd->SetGroupSize(gsize_quantized);
// SetSendTime() when message is being sent (in OnTxTimeout()) // SetSendTime() when message is being sent (in OnTxTimeout())
@ -2332,8 +2328,8 @@ bool NormSession::OnProbeTimeout(ProtoTimer& /*theTimer*/)
// Determine next probe_interval // Determine next probe_interval
const NormCCNode* clr = (const NormCCNode*)cc_node_list.Head(); const NormCCNode* clr = (const NormCCNode*)cc_node_list.Head();
probeInterval = clr ? MIN(grtt_advertised, clr->GetRtt()) : grtt_advertised; probeInterval = clr ? MIN(grtt_advertised, clr->GetRtt()) : grtt_advertised;
double nominalRate = ((double)segment_size)/((double)tx_rate); //double nominalRate = ((double)segment_size)/((double)tx_rate);
probeInterval = MAX(probeInterval, nominalRate); //probeInterval = MAX(probeInterval, nominalRate);
} }
else else
{ {
@ -2356,6 +2352,7 @@ void NormSession::AdjustRate(bool onResponse)
const NormCCNode* clr = (const NormCCNode*)cc_node_list.Head(); const NormCCNode* clr = (const NormCCNode*)cc_node_list.Head();
double ccRtt = clr ? clr->GetRtt() : grtt_measured; double ccRtt = clr ? clr->GetRtt() : grtt_measured;
double ccLoss = clr ? clr->GetLoss() : 0.0; double ccLoss = clr ? clr->GetLoss() : 0.0;
double oldRate = tx_rate;
if (onResponse) if (onResponse)
{ {
// Adjust rate based on CLR feedback and // Adjust rate based on CLR feedback and
@ -2364,19 +2361,16 @@ void NormSession::AdjustRate(bool onResponse)
// (TBD) check feedback age // (TBD) check feedback age
if (cc_slow_start) if (cc_slow_start)
{ {
double scale = tx_rate / sent_rate; tx_rate = clr->GetRate();
scale = MAX(1.0, scale); DMSG(6, "NormSession::AdjustRate(slow start) clr>%lu newRate>%lf (oldRate>%lf sentRate>%lf clrRate>%lf\n",
scale = 1.0; clr->GetId(), tx_rate*8.0/1000.0, oldRate*8.0/1000.0, sent_rate*8.0/1000.0,
//DMSG(0, "NormSession::AdjustRate() slow start clr>%lu rate>%lf tx_rate>%lf sent_rate>%lf\n", clr->GetRate()*8.0/1000.0);
// clr->Id(), clr->GetRate() * 8.0/1000.0, tx_rate * 8.0/1000.0, sent_rate * 8.0/1000.0);
tx_rate = clr->GetRate() * scale;
} }
else else
{ {
double clrRate = clr->GetRate(); double clrRate = clr->GetRate();
if (clrRate > tx_rate) if (clrRate > tx_rate)
{ {
double linRate = tx_rate + segment_size; double linRate = tx_rate + segment_size;
tx_rate = MIN(clrRate, linRate); tx_rate = MIN(clrRate, linRate);
} }
@ -2384,9 +2378,9 @@ void NormSession::AdjustRate(bool onResponse)
{ {
tx_rate = clrRate; tx_rate = clrRate;
} }
DMSG(6, "NormSession::AdjustRate(stdy state) clr>%lu newRate>%lf (rtt>%lf loss>%lf)\n",
clr->GetId(), tx_rate*8.0/1000.0, clr->GetRtt(), clr->GetLoss());
} }
//DMSG(0, "NormSession::AdjustRate() regular rate adjust clr>%lu rate>%lf (rtt>%lf loss>%lf slow_start>%d)\n",
// clr->Id(), tx_rate*8.0/1000.0, clr->GetRtt(), clr->GetLoss(), cc_slow_start);
} }
else if (clr) else if (clr)
{ {
@ -2414,7 +2408,21 @@ void NormSession::AdjustRate(bool onResponse)
struct timeval currentTime; struct timeval currentTime;
::ProtoSystemTime(currentTime); ::ProtoSystemTime(currentTime);
double theTime = (double)currentTime.tv_sec + 1.0e-06 * ((double)currentTime.tv_usec); double theTime = (double)currentTime.tv_sec + 1.0e-06 * ((double)currentTime.tv_usec);
DMSG(6, "ServerRateTracking time>%lf rate>%lf rtt>%lf loss>%lf\n", theTime, tx_rate * (8.0/1000.0), ccRtt, ccLoss);
if (tx_rate != oldRate)
{
if (tx_timer.IsActive())
{
//double ratio = tx_rate / oldRate;
double txInterval = tx_timer.GetInterval() * oldRate / tx_rate;
double timeElapsed = tx_timer.GetInterval() - tx_timer.GetTimeRemaining();
txInterval = timeElapsed < txInterval ? (txInterval - timeElapsed) : 0.0;
tx_timer.SetInterval(txInterval);
tx_timer.Reschedule();
}
}
DMSG(6, "ServerRateTracking time>%lf rate>%lf rtt>%lf loss>%lf\n\n", theTime, tx_rate*(8.0/1000.0), ccRtt, ccLoss);
} // end NormSession::AdjustRate() } // end NormSession::AdjustRate()
bool NormSession::OnReportTimeout(ProtoTimer& /*theTimer*/) bool NormSession::OnReportTimeout(ProtoTimer& /*theTimer*/)

View File

@ -162,6 +162,14 @@ class NormSession
return result; return result;
} }
double ServerGrtt() {return grtt_advertised;}
void ServerSetGrtt(double grttValue)
{
double grttMin = 2.0 * ((double)(44+segment_size))/tx_rate;
grttValue = (grttValue < grttMin) ? grttMin : grttValue;
grtt_quantized = NormQuantizeRtt(grttValue);
grtt_measured = grtt_advertised = NormUnquantizeRtt(grtt_quantized);
}
double ServerGroupSize() {return gsize_measured;} double ServerGroupSize() {return gsize_measured;}
void ServerSetGroupSize(double gsize) void ServerSetGroupSize(double gsize)
{ {
@ -267,11 +275,9 @@ class NormSession
// Client message handling routines // Client message handling routines
void ClientHandleObjectMessage(const struct timeval& currentTime, void ClientHandleObjectMessage(const struct timeval& currentTime,
const NormObjectMsg& msg, const NormObjectMsg& msg);
NormServerNode* theServer);
void ClientHandleCommand(const struct timeval& currentTime, void ClientHandleCommand(const struct timeval& currentTime,
const NormCmdMsg& msg, const NormCmdMsg& msg);
NormServerNode* theServer);
void ClientHandleNackMessage(const NormNackMsg& nack); void ClientHandleNackMessage(const NormNackMsg& nack);
void ClientHandleAckMessage(const NormAckMsg& ack); void ClientHandleAckMessage(const NormAckMsg& ack);

View File

@ -15,8 +15,10 @@ NormSimAgent::NormSimAgent(ProtoTimerMgr& timerMgr,
backoff_factor(NormSession::DEFAULT_BACKOFF_FACTOR), backoff_factor(NormSession::DEFAULT_BACKOFF_FACTOR),
segment_size(1024), ndata(32), nparity(16), auto_parity(0), extra_parity(0), segment_size(1024), ndata(32), nparity(16), auto_parity(0), extra_parity(0),
group_size(NormSession::DEFAULT_GSIZE_ESTIMATE), group_size(NormSession::DEFAULT_GSIZE_ESTIMATE),
grtt_estimate(NormSession::DEFAULT_GRTT_ESTIMATE),
tx_buffer_size(1024*1024), rx_buffer_size(1024*1024), tx_buffer_size(1024*1024), rx_buffer_size(1024*1024),
tx_object_size(0), tx_object_interval(0.0), tx_object_size(0), tx_object_interval(0.0),
tx_object_size_min(0), tx_object_size_max(0),
tx_repeat_count(0), tx_repeat_interval(0.0), tx_repeat_count(0), tx_repeat_interval(0.0),
stream(NULL), auto_stream(false), push_stream(false), stream(NULL), auto_stream(false), push_stream(false),
flush_mode(NormStreamObject::FLUSH_PASSIVE), flush_mode(NormStreamObject::FLUSH_PASSIVE),
@ -62,11 +64,13 @@ const char* const NormSimAgent::cmd_list[] =
"+auto", // server auto parity count "+auto", // server auto parity count
"+extra", // server extra parity count "+extra", // server extra parity count
"+gsize", // group size estimate "+gsize", // group size estimate
"+grtt", // grtt estimate
"+txbuffer", // tx buffer size (bytes) "+txbuffer", // tx buffer size (bytes)
"+rxbuffer", // rx buffer size (bytes) "+rxbuffer", // rx buffer size (bytes)
"+start", // open session and beging activity "+start", // open session and beging activity
"-stop", // cease activity and close session "-stop", // cease activity and close session
"+sendFile", // queue a "sim" file for transmission "+sendFile", // queue a "sim" file of <size> bytes for transmission
"+sendRandomFile", // queue random-size file size range <sizeMin>:<sizeMax>
"+sendStream", // send a simulated NORM stream "+sendStream", // send a simulated NORM stream
"+openStream", // open a stream object for messaging "+openStream", // open a stream object for messaging
"+push", // "on" means real-time push stream advancement (non-blocking) "+push", // "on" means real-time push stream advancement (non-blocking)
@ -285,6 +289,15 @@ bool NormSimAgent::ProcessCommand(const char* cmd, const char* val)
} }
if (session) session->ServerSetGroupSize(group_size); if (session) session->ServerSetGroupSize(group_size);
} }
else if (!strncmp("grtt", cmd, len))
{
if (1 != sscanf(val, "%lf", &grtt_estimate))
{
DMSG(0, "NormSimAgent::ProcessCommand(gize) invalid value!\n");
return false;
}
if (session) session->ServerSetGroupSize(grtt_estimate);
}
else if (!strncmp("txbuffer", cmd, len)) else if (!strncmp("txbuffer", cmd, len))
{ {
if (1 != sscanf(val, "%lu", &tx_buffer_size)) if (1 != sscanf(val, "%lu", &tx_buffer_size))
@ -338,6 +351,33 @@ bool NormSimAgent::ProcessCommand(const char* cmd, const char* val)
return false; return false;
} }
} }
else if (!strncmp("sendRandomFile", cmd, len))
{
if (2 != sscanf(val, "%lu:%lu", &tx_object_size_min, &tx_object_size_max))
{
DMSG(0, "NormSimAgent::ProcessCommand(sendRandomFile) invalid size!\n");
return false;
}
if (tx_object_size_min > tx_object_size_max)
{
unsigned int tempSize = tx_object_size_min;
tx_object_size_min = tx_object_size_max;
tx_object_size_max = tempSize;
}
tx_object_size = tx_object_size_max - tx_object_size_min;
tx_object_size = (unsigned long)(tx_object_size * UniformRand(1.0));
tx_object_size += tx_object_size_min;
if (session)
{
TRACE("Queued file size: %lu bytes\n", tx_object_size);
return (NULL != session->QueueTxSim(tx_object_size));
}
else
{
DMSG(0, "NormSimAgent::ProcessCommand(sendRandomFile) no session started!\n");
return false;
}
}
else if (!strncmp("sendStream", cmd, len)) else if (!strncmp("sendStream", cmd, len))
{ {
if (session) if (session)
@ -422,7 +462,7 @@ bool NormSimAgent::ProcessCommand(const char* cmd, const char* val)
} }
else else
{ {
DMSG(0, "NormSimAgent::ProcessCommand(flushStream) session not started!\n"); DMSG(0, "NormSimAgent::ProcessCommand(doFlush) session not started!\n");
return false; return false;
} }
} }
@ -532,8 +572,8 @@ bool NormSimAgent::SendMessage(unsigned int len, const char* txBuffer)
else else
{ {
// Message still pending, can't send yet // Message still pending, can't send yet
DMSG(0, "NormSimAgent::SendMessage() input overflow!\n"); DMSG(0, "NormSimAgent::SendMessage() warning: input overflow!\n");
ASSERT(0); //ASSERT(0);
return false; return false;
} }
} }
@ -564,11 +604,12 @@ void NormSimAgent::OnInputReady()
} }
} // end NormSimAgent::InputReady() } // end NormSimAgent::InputReady()
// Do an _active_ flush of the stream (for use at end-of-transmission)
bool NormSimAgent::FlushStream() bool NormSimAgent::FlushStream()
{ {
if (stream && session && session->IsServer()) if (stream && session && session->IsServer())
{ {
stream->Write(NULL, 0, flush_mode, false, false); stream->Write(NULL, 0, NormStreamObject::FLUSH_ACTIVE, false, false);
return true; return true;
} }
else else
@ -631,7 +672,7 @@ void NormSimAgent::Notify(NormController::Event event,
if (silent_client) if (silent_client)
size = NormObjectSize(rx_buffer_size); size = NormObjectSize(rx_buffer_size);
else else
size = object->Size(); size = object->GetSize();
if (!((NormStreamObject*)object)->Accept(size.LSB())) if (!((NormStreamObject*)object)->Accept(size.LSB()))
{ {
DMSG(0, "NormSimAgent::Notify(RX_OBJECT_NEW) stream object accept error!\n"); DMSG(0, "NormSimAgent::Notify(RX_OBJECT_NEW) stream object accept error!\n");
@ -822,11 +863,18 @@ bool NormSimAgent::OnIntervalTimeout(ProtoTimer& theTimer)
else else
{ {
// Queue a NORM_OBJECT_SIM as long as there are repeats // Queue a NORM_OBJECT_SIM as long as there are repeats
if (tx_repeat_count > 0) tx_repeat_count--; if (tx_repeat_count > 0) tx_repeat_count--;
if (tx_object_size_min > 0)
{
tx_object_size = tx_object_size_max - tx_object_size_min;
tx_object_size = (unsigned long)(tx_object_size * UniformRand(1.0));
tx_object_size += tx_object_size_min;
}
if (!session->QueueTxSim(tx_object_size)) if (!session->QueueTxSim(tx_object_size))
{ {
DMSG(0, "NormSimAgent::OnIntervalTimeout() Error queueing tx object.\n"); DMSG(0, "NormSimAgent::OnIntervalTimeout() Error queueing tx object.\n");
} }
TRACE("Queued file size: %lu bytes\n", tx_object_size);
} }
interval_timer.SetInterval(tx_object_interval); interval_timer.SetInterval(tx_object_interval);
return true; return true;
@ -837,7 +885,6 @@ bool NormSimAgent::OnIntervalTimeout(ProtoTimer& theTimer)
if (interval_timer.IsActive()) interval_timer.Deactivate(); if (interval_timer.IsActive()) interval_timer.Deactivate();
return false; return false;
} }
} // end NormSimAgent::OnIntervalTimeout() } // end NormSimAgent::OnIntervalTimeout()
@ -866,7 +913,8 @@ bool NormSimAgent::StartServer()
session->SetTrace(tracing); session->SetTrace(tracing);
session->SetTxLoss(tx_loss); session->SetTxLoss(tx_loss);
session->SetRxLoss(rx_loss); session->SetRxLoss(rx_loss);
session->ServerSetGroupSize(group_size); session->ServerSetGroupSize(group_size);
session->ServerSetGrtt(grtt_estimate);
// StartServer(bufferMax, segmentSize, fec_ndata, fec_nparity) // StartServer(bufferMax, segmentSize, fec_ndata, fec_nparity)
if (!session->StartServer(tx_buffer_size, segment_size, ndata, nparity)) if (!session->StartServer(tx_buffer_size, segment_size, ndata, nparity))
{ {

View File

@ -64,12 +64,15 @@ class NormSimAgent : public NormController
UINT8 auto_parity; UINT8 auto_parity;
UINT8 extra_parity; UINT8 extra_parity;
double group_size; double group_size;
double grtt_estimate;
unsigned long tx_buffer_size; // bytes unsigned long tx_buffer_size; // bytes
unsigned long rx_buffer_size; // bytes unsigned long rx_buffer_size; // bytes
// for simulated transmission (streams or files) // for simulated transmission (streams or files)
unsigned long tx_object_size; unsigned long tx_object_size;
double tx_object_interval; double tx_object_interval;
unsigned long tx_object_size_min;
unsigned long tx_object_size_max;
int tx_repeat_count; int tx_repeat_count;
double tx_repeat_interval; double tx_repeat_interval;

View File

@ -32,6 +32,6 @@
#ifndef _NORM_VERSION #ifndef _NORM_VERSION
#define _NORM_VERSION #define _NORM_VERSION
#define VERSION "1.1b5" #define VERSION "1.1b6"
#endif // _NORM_VERSION #endif // _NORM_VERSION