454 lines
13 KiB
C++
454 lines
13 KiB
C++
#include "normMessage.h"
|
|
|
|
#include "debug.h"
|
|
|
|
NormRepairRequest::NormRepairRequest()
|
|
: form(INVALID), flags(0), length(0), buffer(NULL), buffer_len(0)
|
|
{
|
|
}
|
|
|
|
bool NormRepairRequest::AppendRepairItem(const NormObjectId& objectId,
|
|
const NormBlockId& blockId,
|
|
UINT16 symbolId)
|
|
{
|
|
if (buffer_len >= (CONTENT_OFFSET+length+RepairItemLength()))
|
|
{
|
|
UINT16 temp16 = htons((UINT16)objectId);
|
|
memcpy(buffer+CONTENT_OFFSET+length, &temp16, 2);
|
|
UINT32 temp32 =htonl((UINT32)blockId);
|
|
memcpy(buffer+length+CONTENT_OFFSET+2, &temp32, 4);
|
|
symbolId = htons(symbolId);
|
|
memcpy(buffer+length+CONTENT_OFFSET+6, &symbolId, 2);
|
|
length += RepairItemLength();
|
|
return true;
|
|
}
|
|
else
|
|
{
|
|
return false;
|
|
}
|
|
} // end NormRepairRequest::AppendRepairItem()
|
|
|
|
bool NormRepairRequest::AppendRepairRange(const NormObjectId& startObjectId,
|
|
const NormBlockId& startBlockId,
|
|
UINT16 startSymbolId,
|
|
const NormObjectId& endObjectId,
|
|
const NormBlockId& endBlockId,
|
|
UINT16 endSymbolId)
|
|
{
|
|
if (buffer_len >= (CONTENT_OFFSET+length+RepairRangeLength()))
|
|
{
|
|
// range start
|
|
UINT16 temp16;
|
|
temp16 = htons((UINT16)startObjectId);
|
|
memcpy(buffer+CONTENT_OFFSET+length, &temp16, 2);
|
|
UINT32 temp32 =htonl((UINT32)startBlockId);
|
|
memcpy(buffer+length+CONTENT_OFFSET+2, &temp32, 4);
|
|
startSymbolId = htons(startSymbolId);
|
|
memcpy(buffer+length+CONTENT_OFFSET+6, &startSymbolId, 2);
|
|
// range end
|
|
temp16 = htons((UINT16)endObjectId);
|
|
memcpy(buffer+CONTENT_OFFSET+length+8, &temp16, 2);
|
|
temp32 =htonl((UINT32)endBlockId);
|
|
memcpy(buffer+length+CONTENT_OFFSET+10, &temp32, 4);
|
|
endSymbolId = htons(endSymbolId);
|
|
memcpy(buffer+length+CONTENT_OFFSET+14, &endSymbolId, 2);
|
|
length += RepairRangeLength();
|
|
return true;
|
|
}
|
|
else
|
|
{
|
|
return false;
|
|
}
|
|
} // end NormRepairRequest::AppendErasureCount()
|
|
|
|
bool NormRepairRequest::AppendErasureCount(const NormObjectId& objectId,
|
|
const NormBlockId& blockId,
|
|
UINT16 erasureCount)
|
|
{
|
|
if (buffer_len >= (CONTENT_OFFSET+length+ErasureItemLength()))
|
|
{
|
|
UINT16 temp16 = htons((UINT16)objectId);
|
|
memcpy(buffer+CONTENT_OFFSET+length, &temp16, 2);
|
|
UINT32 temp32 =htonl((UINT32)blockId);
|
|
memcpy(buffer+length+CONTENT_OFFSET+2, &temp32, 4);
|
|
erasureCount = htons(erasureCount);
|
|
memcpy(buffer+length+CONTENT_OFFSET+6, &erasureCount, 2);
|
|
length += ErasureItemLength();
|
|
return true;
|
|
}
|
|
else
|
|
{
|
|
return false;
|
|
}
|
|
} // end NormRepairRequest::AppendErasureCount()
|
|
|
|
|
|
UINT16 NormRepairRequest::Pack()
|
|
{
|
|
if (length)
|
|
{
|
|
buffer[FORM_OFFSET] = form;
|
|
buffer[FLAGS_OFFSET] = (char)flags;
|
|
UINT16 temp16 = htons(length);
|
|
memcpy(buffer+LENGTH_OFFSET, &temp16, 2);
|
|
return (CONTENT_OFFSET + length);
|
|
}
|
|
else
|
|
{
|
|
return 0;
|
|
}
|
|
} // end NormRepairRequest::Pack()
|
|
|
|
|
|
UINT16 NormRepairRequest::Unpack()
|
|
{
|
|
// Make sure there's at least a header
|
|
if (buffer_len >= CONTENT_OFFSET)
|
|
{
|
|
form = (Form)buffer[FORM_OFFSET];
|
|
flags = (int)buffer[FLAGS_OFFSET];
|
|
memcpy(&length, buffer+LENGTH_OFFSET, 2);
|
|
length = ntohs(length);
|
|
if (length > (buffer_len - CONTENT_OFFSET))
|
|
{
|
|
// Badly formed message
|
|
return 0;
|
|
}
|
|
else
|
|
{
|
|
return (CONTENT_OFFSET+length);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
return 0;
|
|
}
|
|
} // end NormRepairRequest::Unpack()
|
|
|
|
bool NormRepairRequest::RetrieveRepairItem(UINT16 offset,
|
|
NormObjectId* objectId,
|
|
NormBlockId* blockId,
|
|
UINT16* symbolId) const
|
|
{
|
|
if (length >= (offset + RepairItemLength()))
|
|
{
|
|
UINT16 temp16;
|
|
memcpy(&temp16, buffer+CONTENT_OFFSET+offset, 2);
|
|
*objectId = ntohs(temp16);
|
|
UINT32 temp32;
|
|
memcpy(&temp32, buffer+CONTENT_OFFSET+offset+2, 4);
|
|
*blockId = ntohl(temp32);
|
|
memcpy(symbolId, buffer+CONTENT_OFFSET+offset+6, 2);
|
|
*symbolId = ntohs(*symbolId);
|
|
return true;
|
|
}
|
|
else
|
|
{
|
|
return false;
|
|
}
|
|
} // end NormRepairRequest::RetrieveRepairItem()
|
|
|
|
NormRepairRequest::Iterator::Iterator(NormRepairRequest& theRequest)
|
|
: request(theRequest), offset(0)
|
|
{
|
|
}
|
|
|
|
// For erasure requests, symbolId is loaded with erasureCount
|
|
bool NormRepairRequest::Iterator::NextRepairItem(NormObjectId* objectId,
|
|
NormBlockId* blockId,
|
|
UINT16* symbolId)
|
|
{
|
|
if (request.RetrieveRepairItem(offset, objectId, blockId, symbolId))
|
|
{
|
|
offset += NormRepairRequest::RepairItemLength();
|
|
return true;
|
|
}
|
|
else
|
|
{
|
|
return false;
|
|
}
|
|
} // end NormRepairRequest::Iterator::NextRepairItem()
|
|
|
|
|
|
NormMessageQueue::NormMessageQueue()
|
|
: head(NULL), tail(NULL)
|
|
{
|
|
}
|
|
|
|
NormMessageQueue::~NormMessageQueue()
|
|
{
|
|
Destroy();
|
|
}
|
|
|
|
void NormMessageQueue::Destroy()
|
|
{
|
|
NormMessage* next;
|
|
while ((next = head))
|
|
{
|
|
head = next->next;
|
|
delete next;
|
|
}
|
|
} // end NormMessageQueue::Destroy()
|
|
|
|
|
|
void NormMessageQueue::Prepend(NormMessage* msg)
|
|
{
|
|
if ((msg->next = head))
|
|
head->prev = msg;
|
|
else
|
|
tail = msg;
|
|
msg->prev = NULL;
|
|
head = msg;
|
|
} // end NormMessageQueue::Prepend()
|
|
|
|
void NormMessageQueue::Append(NormMessage* msg)
|
|
{
|
|
if ((msg->prev = tail))
|
|
tail->next = msg;
|
|
else
|
|
head = msg;
|
|
msg->next = NULL;
|
|
tail = msg;
|
|
} // end NormMessageQueue::Append()
|
|
|
|
void NormMessageQueue::Remove(NormMessage* msg)
|
|
{
|
|
if (msg->prev)
|
|
msg->prev->next = msg->next;
|
|
else
|
|
head = msg->next;
|
|
if (msg->next)
|
|
msg->next->prev = msg->prev;
|
|
else
|
|
tail = msg->prev;
|
|
} // end NormMessageQueue::Remove()
|
|
|
|
NormMessage* NormMessageQueue::RemoveHead()
|
|
{
|
|
if (head)
|
|
{
|
|
NormMessage* msg = head;
|
|
if ((head = msg->next))
|
|
msg->next->prev = NULL;
|
|
else
|
|
tail = NULL;
|
|
return msg;
|
|
}
|
|
else
|
|
{
|
|
return NULL;
|
|
}
|
|
} // end NormMessageQueue::RemoveHead()
|
|
|
|
NormMessage* NormMessageQueue::RemoveTail()
|
|
{
|
|
if (tail)
|
|
{
|
|
NormMessage* msg = tail;
|
|
if ((tail = msg->prev))
|
|
msg->prev->next = NULL;
|
|
else
|
|
head = NULL;
|
|
return msg;
|
|
}
|
|
else
|
|
{
|
|
return NULL;
|
|
}
|
|
} // end NormMessageQueue::RemoveTail()
|
|
|
|
bool NormObjectSize::operator<(const NormObjectSize& size) const
|
|
{
|
|
UINT16 diff = msb - size.msb;
|
|
if (0 == diff)
|
|
return (lsb < size.lsb);
|
|
else if ((diff > 0x8000) ||
|
|
((0x8000 == diff) && (msb > size.msb)))
|
|
return true;
|
|
else
|
|
return false;
|
|
} // end NormObjectSize::operator<(NormObjectSize size)
|
|
|
|
bool NormObjectSize::operator>(const NormObjectSize& size) const
|
|
{
|
|
UINT16 diff = size.msb - msb;
|
|
if (0 == diff)
|
|
return (lsb > size.lsb);
|
|
else if ((diff > 0x8000) ||
|
|
((0x8000 == diff) && (size.msb > msb)))
|
|
return true;
|
|
else
|
|
return false;
|
|
} // end NormObjectSize::operator>(NormObjectSize id)
|
|
|
|
NormObjectSize NormObjectSize::operator+(const NormObjectSize& size) const
|
|
{
|
|
NormObjectSize total;
|
|
total.msb = msb + size.msb;
|
|
total.lsb = lsb + size.lsb;
|
|
if ((total.lsb < lsb) || (total.lsb < size.lsb)) total.msb++;
|
|
return total;
|
|
} // end NormObjectSize::operator+(NormObjectSize id)
|
|
|
|
NormObjectSize NormObjectSize::operator-(const NormObjectSize& b) const
|
|
{
|
|
NormObjectSize result;
|
|
result.lsb = lsb - b.lsb;
|
|
result.msb = msb - b.msb;
|
|
if (lsb < b.lsb) result.msb--;
|
|
return result;
|
|
} // end NormObjectSize::operator-(NormObjectSize id)
|
|
|
|
NormObjectSize NormObjectSize::operator*(const NormObjectSize& b) const
|
|
{
|
|
UINT32 ll = (lsb & 0x0000ffff) * (b.lsb & 0x0000ffff);
|
|
UINT32 lm = (lsb & 0x0000ffff) * ((b.lsb >> 16) & 0x0000ffff);
|
|
UINT32 ml = ((lsb >> 16) & 0x0000ffff) * (b.lsb & 0x0000ffff);
|
|
UINT32 lu = (lsb & 0x0000ffff) * (UINT32)b.msb;
|
|
UINT32 mm = ((lsb >> 16) & 0x0000ffff) *
|
|
((b.lsb >> 16) & 0x0000ffff);
|
|
NormObjectSize result;
|
|
result.lsb = ll + (lm << 16) + (ml << 16);
|
|
result.msb = lu + mm + ((lm >> 16) & 0x0000ffff) +
|
|
((ml >> 16) & 0x0000ffff);
|
|
return result;
|
|
} // end NormObjectSize::operator*(NormObjectSize size)
|
|
|
|
NormObjectSize NormObjectSize::operator/(const NormObjectSize& b) const
|
|
{
|
|
// Zero dividend is special case
|
|
if ((0 == lsb) && (0 == msb)) return NormObjectSize(0, 0);
|
|
// Zero divisor is special case
|
|
if ((0 == b.lsb) && (0 == b.msb)) return NormObjectSize(0xffff, 0xffffffff);
|
|
// Dividend equals divisor is special case
|
|
if (*this == b) return NormObjectSize(0,1);
|
|
// Divisor > dividend is special case
|
|
if ((b.lsb > lsb) && (b.msb > msb)) return NormObjectSize(0,1);
|
|
// divisor
|
|
UINT32 divisor[2];
|
|
divisor[0] = (UINT32)b.msb;
|
|
divisor[1] = b.lsb;
|
|
// dividend
|
|
UINT32 dividend[2];
|
|
dividend[0] = msb;
|
|
dividend[1] = (UINT32)lsb;
|
|
// remainder
|
|
UINT32 remainder[2];
|
|
remainder[0] = remainder[1] = 0;
|
|
unsigned int numBits = 64;
|
|
UINT32 d[2];
|
|
while (((divisor[1] > remainder[1]) && (divisor[0] == remainder[0])) ||
|
|
(divisor[0] > remainder[0]))
|
|
{
|
|
remainder[0] <<= 1;
|
|
remainder[0] |= (remainder[1] >> 31) & 0x00000001;
|
|
remainder[1] <<= 1;
|
|
remainder[1] |= (dividend[0] >> 31) & 0x00000001;
|
|
d[0] = dividend[0];
|
|
d[1] = dividend[1];
|
|
dividend[0] <<= 1;
|
|
dividend[0] |= (dividend[1] >> 31) & 0x00000001;
|
|
dividend[1] <<= 1;
|
|
numBits--;
|
|
}
|
|
|
|
// Note: above loop goes one step too far
|
|
// so we incr numBits, use old dividend (d)
|
|
numBits++;
|
|
UINT32 quotient[2];
|
|
quotient[0] = quotient[1] = 0;
|
|
bool extra = false;
|
|
for (unsigned int i = 0; i < numBits; i++)
|
|
{
|
|
UINT32 t[2];
|
|
t[0] = remainder[0] - divisor[0];
|
|
t[1] = remainder[1] - divisor[1];
|
|
if (remainder[1] < divisor[1]) t[0]--;
|
|
UINT32 q = ((t[0] >> 31) & 0x00000001) ^ 0x00000001;
|
|
d[0] <<= 1;
|
|
d[0] |= (d[1] >> 31) & 0x00000001;
|
|
d[1] <<= 1;
|
|
quotient[0] <<= 1;
|
|
quotient[1] = (quotient[1] << 1) | q;
|
|
if (q)
|
|
{
|
|
remainder[0] = t[0];
|
|
remainder[1] = t[1];
|
|
}
|
|
if (remainder[0] || remainder[1])
|
|
extra = true;
|
|
else
|
|
extra = false;
|
|
remainder[0] <<= 1;
|
|
remainder[0] |= (remainder[1] >> 31) & 0x00000001;
|
|
remainder[1] <<= 1;
|
|
remainder[1] |= (d[0] >> 31) & 0x00000001;
|
|
}
|
|
NormObjectSize result((UINT16)quotient[0], quotient[1]);
|
|
// If there was _any_ remainder, round up
|
|
if (extra) result++;
|
|
return result;
|
|
} // end NormObjectSize::operator/(NormObjectSize b)
|
|
|
|
|
|
bool NormObjectId::operator<(const NormObjectId& id) const
|
|
{
|
|
UINT16 diff = value - id.value;
|
|
if ((diff > 0x8000) ||
|
|
((0x8000 == diff) && (value > id.value)))
|
|
return true;
|
|
else
|
|
return false;
|
|
} // end NormObjectId::operator<(NormObjectId id)
|
|
|
|
bool NormObjectId::operator>(const NormObjectId& id) const
|
|
{
|
|
UINT16 diff = id.value - value;;
|
|
if ((diff > 0x8000) ||
|
|
((0x8000 == diff) && (id.value > value)))
|
|
return true;
|
|
else
|
|
return false;
|
|
} // end NormObjectId::operator>(NormObjectId id)
|
|
|
|
int NormObjectId::operator-(const NormObjectId& id) const
|
|
{
|
|
UINT16 diff = value - id.value;
|
|
if ((diff > 0x8000) ||
|
|
((0x8000 == diff) && (value > id.value)))
|
|
return ((INT16)(value - id.value));
|
|
else
|
|
return (-(INT16)(id.value - value));
|
|
} // end NormObjectId::operator-(NormObjectId id) const
|
|
|
|
|
|
bool NormBlockId::operator<(const NormBlockId& id) const
|
|
{
|
|
UINT32 diff = value - id.value;
|
|
if ((diff > 0x80000000) ||
|
|
((0x80000000 == diff) && (value > id.value)))
|
|
return true;
|
|
else
|
|
return false;
|
|
} // end NormBlockId::operator<(NormBlockId id)
|
|
|
|
bool NormBlockId::operator>(const NormBlockId& id) const
|
|
{
|
|
UINT32 diff = id.value - value;;
|
|
if ((diff > 0x80000000) ||
|
|
((0x80000000 == diff) && (id.value > value)))
|
|
return true;
|
|
else
|
|
return false;
|
|
} // end NormBlockId::operator>(NormBlockId id)
|
|
|
|
long NormBlockId::operator-(const NormBlockId& id) const
|
|
{
|
|
UINT32 diff = value - id.value;
|
|
if ((diff > 0x80000000) ||
|
|
((0x80000000 == diff) && (value > id.value)))
|
|
return ((INT32)(value - id.value));
|
|
else
|
|
return (-(INT32)(id.value - value));
|
|
} // end NormBlockId::operator-(NormBlockId id) const
|