Ok, hopefully fixed all problems with Message3 now. Flat buffers are so fragile...

Also cleaned up Message3.h revert it if you think its a binary compatibility issue.

git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@13920 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Michael Lotz
2005-08-09 14:27:35 +00:00
parent 629192bcaa
commit d35c42a0c9
5 changed files with 138 additions and 195 deletions
+63 -149
View File
@@ -68,7 +68,7 @@ enum
B_ID_SPECIFIER, B_ID_SPECIFIER,
B_SPECIFIERS_END = 128 B_SPECIFIERS_END = 128
// app-defined specifiers start at B_SPECIFIERS_END+1 // app-defined specifiers start at B_SPECIFIERS_END + 1
}; };
namespace BPrivate { namespace BPrivate {
@@ -279,174 +279,88 @@ virtual ~BMessage();
float FindFloat(const char *, int32 n = 0) const; float FindFloat(const char *, int32 n = 0) const;
double FindDouble(const char *, int32 n = 0) const; double FindDouble(const char *, int32 n = 0) const;
class Private; class Private;
private: private:
class Header; class Header;
friend class BMessageQueue; friend class BMessageQueue;
friend class BMessenger; friend class BMessenger;
friend class BApplication; friend class BApplication;
friend class Header; friend class Header;
friend class Private; friend class Private;
friend inline void _set_message_target_(BMessage *, int32, bool); friend inline void _set_message_target_(BMessage *, int32, bool);
friend inline void _set_message_reply_(BMessage *, BMessenger); friend inline void _set_message_reply_(BMessage *, BMessenger);
friend inline int32 _get_message_target_(BMessage *); friend inline int32 _get_message_target_(BMessage *);
friend inline bool _use_preferred_target_(BMessage *); friend inline bool _use_preferred_target_(BMessage *);
// deprecated // deprecated
BMessage(BMessage *a_message); BMessage(BMessage *a_message);
virtual void _ReservedMessage1(); virtual void _ReservedMessage1();
virtual void _ReservedMessage2(); virtual void _ReservedMessage2();
virtual void _ReservedMessage3(); virtual void _ReservedMessage3();
void init_data(); void init_data();
status_t flatten_target_info(BDataIO *stream, status_t real_flatten(char *result, ssize_t size) const;
ssize_t size, status_t real_flatten(BDataIO *stream, ssize_t *size) const;
uchar flags) const; char *stack_flatten(char *stack_ptr,
status_t real_flatten(char *result, ssize_t size) const; ssize_t stack_size, bool incl_reply,
status_t real_flatten(BDataIO *stream, ssize_t *size) const;
char *stack_flatten(char *stack_ptr,
ssize_t stack_size,
bool incl_reply,
ssize_t *size = NULL) const; ssize_t *size = NULL) const;
status_t _UnflattenKMessage(const char *buffer); status_t _UnflattenKMessage(const char *buffer);
ssize_t calc_size(uchar flags) const; ssize_t calc_hdr_size() const;
ssize_t calc_hdr_size(uchar flags) const;
status_t nfind_data( const char *name,
type_code type,
int32 index,
const void **data,
ssize_t *data_size) const;
status_t copy_data( const char *name,
type_code type,
int32 index,
void *data,
ssize_t data_size) const;
status_t _send_(port_id port, status_t _send_(port_id port, int32 token,
int32 token, bool preferred, bigtime_t timeout,
bool preferred, bool reply_required,
bigtime_t timeout, BMessenger &reply_to) const;
bool reply_required, status_t send_message(port_id port, team_id port_owner,
BMessenger &reply_to) const; int32 token, bool preferred,
status_t send_message(port_id port, BMessage *reply,
team_id port_owner, bigtime_t send_timeout,
int32 token, bigtime_t reply_timeout) const;
bool preferred,
BMessage *reply,
bigtime_t send_timeout,
bigtime_t reply_timeout) const;
static status_t _SendFlattenedMessage(void *data, int32 size,
port_id port, int32 token, bool preferred,
bigtime_t timeout);
static void _StaticInit(); static status_t _SendFlattenedMessage(void *data, int32 size,
static void _StaticCleanup(); port_id port, int32 token, bool preferred,
static void _StaticCacheCleanup(); bigtime_t timeout);
enum { sNumReplyPorts = 3 }; static void _StaticInit();
static port_id sReplyPorts[sNumReplyPorts]; static void _StaticCleanup();
static long sReplyPortInUse[sNumReplyPorts]; static void _StaticCacheCleanup();
static int32 sGetCachedReplyPort();
static BBlockCache *sMsgCache; enum { sNumReplyPorts = 3 };
static port_id sReplyPorts[sNumReplyPorts];
static long sReplyPortInUse[sNumReplyPorts];
static int32 sGetCachedReplyPort();
struct dyn_array { static BBlockCache *sMsgCache;
int32 fLogicalBytes;
int32 fPhysicalBytes;
int32 fChunkSize;
int32 fCount;
int32 fEntryHdrSize;
};
struct entry_hdr : public dyn_array { BMessage *fUnused1;
entry_hdr *fNext; int32 fTarget;
uint32 fType; BMessage *fOriginal;
uchar fNameLength; uint32 fUnused2;
char fName[1]; int32 fCurSpecifier;
}; uint32 fReserved[4];
struct var_chunk { BPrivate::BMessageBody *fBody;
int32 fDataSize;
char fData[1];
};
entry_hdr *entry_find(const char *name, uint32 type,status_t *result=NULL) const;
void entry_remove(entry_hdr *entry);
void *da_create(int32 header_size, int32 chunk_size,
bool fixed, int32 nchunks);
status_t da_add_data(dyn_array **da, const void *data, int32 size);
void *da_find_data(dyn_array *da, int32 index,
int32 *size = NULL) const;
status_t da_delete_data(dyn_array **pda, int32 index);
status_t da_replace_data(dyn_array **pda, int32 index,
const void *data, int32 dsize);
int32 da_calc_size(int32 hdr_size, int32 chunksize,
bool is_fixed, int32 nchunks) const;
void *da_grow(dyn_array **pda, int32 increase);
void da_dump(dyn_array *da);
int32 da_chunk_hdr_size() const
{ return sizeof(int32); }
int32 da_chunk_size(var_chunk *v) const
{ return (v->fDataSize + da_chunk_hdr_size() + 7) & ~7; }
var_chunk *da_first_chunk(dyn_array *da) const
{ return (var_chunk *) da_start_of_data(da); }
var_chunk *da_next_chunk(var_chunk *v) const
{ return (var_chunk *) (((char*) v) + da_chunk_size(v)); }
var_chunk *da_chunk_ptr(void *data) const
{ return (var_chunk*) (((char *) data) - da_chunk_hdr_size()); }
int32 da_pad_8(int32 val) const
{ return (val + 7) & ~7; }
int32 da_total_size(dyn_array *da) const
{ return (int32)sizeof(dyn_array) + da->fEntryHdrSize +
da->fPhysicalBytes; }
int32 da_total_logical_size(dyn_array *da) const
{ return (int32)sizeof(dyn_array) + da->fEntryHdrSize +
da->fLogicalBytes; }
char *da_start_of_data(dyn_array *da) const
{ return ((char *) da) + (sizeof(dyn_array) +
da->fEntryHdrSize); }
bool da_is_mini_data(dyn_array *da) const
{ return ((da->fLogicalBytes <= (int32) UCHAR_MAX) &&
(da->fCount <= (int32) UCHAR_MAX));}
void da_swap_var_sized(dyn_array *da);
void da_swap_fixed_sized(dyn_array *da);
BMessage *link;
int32 fTarget;
BMessage *fOriginal;
uint32 fChangeCount;
int32 fCurSpecifier;
uint32 fPtrOffset;
// ejaesler: Stealing one for my whacky BMessageBody l33tness
uint32 _reserved[2];
BPrivate::BMessageBody* fBody;
BMessage::entry_hdr *fEntries;
struct reply_to_info { struct reply_to_info {
port_id port; port_id port;
int32 target; int32 target;
team_id team; team_id team;
bool preferred; bool preferred;
} fReplyTo; } fReplyTo;
bool fPreferred; bool fPreferred;
bool fReplyRequired; bool fReplyRequired;
bool fReplyDone; bool fReplyDone;
bool fIsReply; bool fIsReply;
bool fWasDelivered; bool fWasDelivered;
bool fReadOnly; bool fReadOnly;
bool fHasSpecifiers; bool fHasSpecifiers;
}; };
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
+6 -2
View File
@@ -69,9 +69,10 @@ public:
void PrintToStream() const; void PrintToStream() const;
// flat buffer management // flat buffer management
inline uint8 *FlatBuffer() const { return (uint8 *)fFlatBuffer.Buffer(); }; inline uint8 *FlatBuffer() const { return fFlatBuffer; };
uint8 *FlatInsert(int32 offset, ssize_t oldLength, uint8 *FlatInsert(int32 offset, ssize_t oldLength,
ssize_t newLength); ssize_t newLength);
void FlatResize(int32 newSize);
// hash table support // hash table support
void HashInsert(BMessageField *field); void HashInsert(BMessageField *field);
@@ -91,7 +92,10 @@ private:
BMessageField **fFieldTable; BMessageField **fFieldTable;
int32 fFieldTableSize; int32 fFieldTableSize;
BMallocIO fFlatBuffer; uint8 *fFlatBuffer;
int32 fFlatLength;
int32 fFlatAllocated;
int32 fBlockSize;
}; };
} // namespace BPrivate } // namespace BPrivate
+4 -14
View File
@@ -465,14 +465,9 @@ BMessage::operator=(const BMessage &msg)
{ {
what = msg.what; what = msg.what;
link = msg.link;
fTarget = msg.fTarget; fTarget = msg.fTarget;
fOriginal = msg.fOriginal; fOriginal = msg.fOriginal;
fChangeCount = msg.fChangeCount;
fCurSpecifier = msg.fCurSpecifier; fCurSpecifier = msg.fCurSpecifier;
fPtrOffset = msg.fPtrOffset;
fEntries = msg.fEntries;
fReplyTo.port = msg.fReplyTo.port; fReplyTo.port = msg.fReplyTo.port;
fReplyTo.target = msg.fReplyTo.target; fReplyTo.target = msg.fReplyTo.target;
@@ -497,14 +492,9 @@ BMessage::init_data()
{ {
what = 0; what = 0;
link = NULL;
fTarget = B_NULL_TOKEN; fTarget = B_NULL_TOKEN;
fOriginal = NULL; fOriginal = NULL;
fChangeCount = 0;
fCurSpecifier = -1; fCurSpecifier = -1;
fPtrOffset = 0;
fEntries = NULL;
fReplyTo.port = -1; fReplyTo.port = -1;
fReplyTo.target = B_NULL_TOKEN; fReplyTo.target = B_NULL_TOKEN;
@@ -593,7 +583,7 @@ BMessage::IsReply() const
void void
BMessage::PrintToStream() const BMessage::PrintToStream() const
{ {
printf("\nBMessage: what = "); printf("BMessage: what = ");
printf("%c%c%c%c", (uint8)(what >> 24), (uint8)(what >> 16), printf("%c%c%c%c", (uint8)(what >> 24), (uint8)(what >> 16),
(uint8)(what >> 8), (uint8)what); (uint8)(what >> 8), (uint8)what);
printf(" (0x%lX or %ld)\n", what, what); printf(" (0x%lX or %ld)\n", what, what);
@@ -794,7 +784,7 @@ BMessage::SendReply(BMessage *the_reply, BMessage *reply_to_reply,
ssize_t ssize_t
BMessage::FlattenedSize() const BMessage::FlattenedSize() const
{ {
return calc_hdr_size(0) + fBody->FlattenedSize(); return calc_hdr_size() + fBody->FlattenedSize();
} }
@@ -1627,7 +1617,7 @@ char *
BMessage::stack_flatten(char *stack_ptr, ssize_t stack_size, BMessage::stack_flatten(char *stack_ptr, ssize_t stack_size,
bool /*incl_reply*/, ssize_t *size) const bool /*incl_reply*/, ssize_t *size) const
{ {
const ssize_t calcd_size = calc_hdr_size(0) + fBody->FlattenedSize(); const ssize_t calcd_size = calc_hdr_size() + fBody->FlattenedSize();
char *new_ptr = NULL; char *new_ptr = NULL;
if (calcd_size > stack_size) { if (calcd_size > stack_size) {
stack_ptr = new char[calcd_size]; stack_ptr = new char[calcd_size];
@@ -1657,7 +1647,7 @@ BMessage::_UnflattenKMessage(const char *buffer)
ssize_t ssize_t
BMessage::calc_hdr_size(uchar flags) const BMessage::calc_hdr_size() const
{ {
ssize_t size = min_hdr_size(); ssize_t size = min_hdr_size();
+53 -15
View File
@@ -9,6 +9,7 @@
/* BMessageBody handles data storage and retrieval for BMessage. */ /* BMessageBody handles data storage and retrieval for BMessage. */
#include <stdio.h> #include <stdio.h>
#include <malloc.h>
#include <DataIO.h> #include <DataIO.h>
#include <TypeConstants.h> #include <TypeConstants.h>
#include "MessageBody3.h" #include "MessageBody3.h"
@@ -17,6 +18,18 @@
namespace BPrivate { namespace BPrivate {
void
dump_raw(uint8 *data, int32 length)
{
int32 index = 0;
while (index < length) {
for (int32 line = 0; line < 40 && index < length; line++, index++)
printf("%02x ", data[index]);
printf("\n");
}
}
BMessageBody::BMessageBody() BMessageBody::BMessageBody()
{ {
InitCommon(); InitCommon();
@@ -42,9 +55,8 @@ BMessageBody::operator=(const BMessageBody &other)
{ {
if (this != &other) { if (this != &other) {
MakeEmpty(); MakeEmpty();
// the flat buffer has no last entry flag included BMemoryIO memoryIO(other.fFlatBuffer, other.fFlatLength);
BMemoryIO memoryIO(other.FlatBuffer(), other.FlattenedSize() - 1); Unflatten(&memoryIO, other.fFlatLength);
Unflatten(&memoryIO, other.FlattenedSize() - 1);
} }
return *this; return *this;
@@ -54,6 +66,13 @@ BMessageBody::operator=(const BMessageBody &other)
status_t status_t
BMessageBody::InitCommon() BMessageBody::InitCommon()
{ {
// use an avarage field size for each block
fBlockSize = sizeof(FieldHeader) + 50;
fFlatBuffer = (uint8 *)malloc(fBlockSize);
fFlatAllocated = fBlockSize;
fFlatLength = 0;
// init hash table
fFieldTableSize = 100; fFieldTableSize = 100;
fFieldTable = new BMessageField *[fFieldTableSize]; fFieldTable = new BMessageField *[fFieldTableSize];
HashClear(); HashClear();
@@ -203,14 +222,14 @@ ssize_t
BMessageBody::FlattenedSize() const BMessageBody::FlattenedSize() const
{ {
// one more for the last entry flag // one more for the last entry flag
return fFlatBuffer.BufferLength() + 1; return fFlatLength + 1;
} }
status_t status_t
BMessageBody::Flatten(BDataIO *stream) const BMessageBody::Flatten(BDataIO *stream) const
{ {
stream->Write(fFlatBuffer.Buffer(), fFlatBuffer.BufferLength()); stream->Write(fFlatBuffer, fFlatLength);
uint8 lastField = MSG_LAST_ENTRY; uint8 lastField = MSG_LAST_ENTRY;
status_t error = stream->Write(&lastField, sizeof(lastField)); status_t error = stream->Write(&lastField, sizeof(lastField));
@@ -230,14 +249,14 @@ BMessageBody::Unflatten(BDataIO *stream, int32 length)
if (length <= 0) if (length <= 0)
return B_OK; return B_OK;
fFlatBuffer.SetSize(length); FlatResize(length);
status_t error = stream->Read((void *)fFlatBuffer.Buffer(), length); status_t error = stream->Read(fFlatBuffer, length);
if (error < B_OK) if (error < B_OK)
return B_ERROR; return B_ERROR;
int32 offset = 0; int32 offset = 0;
uint8 *location = (uint8 *)fFlatBuffer.Buffer(); uint8 *location = fFlatBuffer;
while (offset < error && *location & MSG_FLAG_VALID) { while (offset < error && *location & MSG_FLAG_VALID) {
BMessageField *field = new BMessageField(this); BMessageField *field = new BMessageField(this);
int32 fieldLength = field->Unflatten(offset); int32 fieldLength = field->Unflatten(offset);
@@ -257,7 +276,7 @@ BMessageBody::Unflatten(BDataIO *stream, int32 length)
} }
// set the buffer to the actual size // set the buffer to the actual size
fFlatBuffer.SetSize(offset); FlatResize(offset);
return B_OK; return B_OK;
} }
@@ -324,8 +343,7 @@ BMessageBody::AddData(const char *name, type_code type, status_t &error)
return foundField; return foundField;
// add a new field if it's not yet present // add a new field if it's not yet present
BMessageField *newField = new BMessageField(this, BMessageField *newField = new BMessageField(this, fFlatLength, name, type);
fFlatBuffer.BufferLength(), name, type);
fFieldList.AddItem(newField); fFieldList.AddItem(newField);
HashInsert(newField); HashInsert(newField);
@@ -430,7 +448,12 @@ BMessageBody::MakeEmpty()
} }
fFieldList.MakeEmpty(); fFieldList.MakeEmpty();
fFlatBuffer.SetSize(0);
free(fFlatBuffer);
fFlatBuffer = NULL;
fFlatLength = 0;
fFlatAllocated = 0;
HashClear(); HashClear();
return B_OK; return B_OK;
} }
@@ -502,6 +525,21 @@ BMessageBody::FindData(const char *name, type_code type, status_t &error) const
} }
void
BMessageBody::FlatResize(int32 newSize)
{
int32 newLength = (newSize + fBlockSize - 1) / fBlockSize * fBlockSize;
if (newLength != fFlatAllocated) {
fFlatBuffer = (uint8 *)realloc(fFlatBuffer, newLength);
if (newLength > fFlatAllocated)
memset(fFlatBuffer + fFlatAllocated, 0, newLength - fFlatAllocated);
fFlatAllocated = newLength;
}
fFlatLength = newSize;
}
uint8 * uint8 *
BMessageBody::FlatInsert(int32 offset, ssize_t oldLength, ssize_t newLength) BMessageBody::FlatInsert(int32 offset, ssize_t oldLength, ssize_t newLength)
{ {
@@ -509,10 +547,10 @@ BMessageBody::FlatInsert(int32 offset, ssize_t oldLength, ssize_t newLength)
return FlatBuffer() + offset; return FlatBuffer() + offset;
ssize_t change = newLength - oldLength; ssize_t change = newLength - oldLength;
ssize_t bufferLength = fFlatBuffer.BufferLength(); ssize_t bufferLength = fFlatLength;
if (change > 0) { if (change > 0) {
fFlatBuffer.SetSize(bufferLength + change); FlatResize(bufferLength + change);
// usual case for adds // usual case for adds
if (offset == bufferLength) if (offset == bufferLength)
@@ -526,7 +564,7 @@ BMessageBody::FlatInsert(int32 offset, ssize_t oldLength, ssize_t newLength)
} }
if (change < 0) if (change < 0)
fFlatBuffer.SetSize(bufferLength + change); FlatResize(bufferLength + change);
for (int32 index = fFieldList.CountItems() - 1; index >= 0; index--) { for (int32 index = fFieldList.CountItems() - 1; index >= 0; index--) {
BMessageField *field = (BMessageField *)fFieldList.ItemAt(index); BMessageField *field = (BMessageField *)fFieldList.ItemAt(index);
+12 -15
View File
@@ -71,9 +71,6 @@ BMessageField::Unflatten(int32 _offset)
fDataOffset = sizeof(FieldHeader) + header->nameLength; fDataOffset = sizeof(FieldHeader) + header->nameLength;
fFixedSize = header->flags & MSG_FLAG_FIXED_SIZE; fFixedSize = header->flags & MSG_FLAG_FIXED_SIZE;
if (header->nameLength == 0)
return 0;
if (fFixedSize) { if (fFixedSize) {
if (header->count > 0) if (header->count > 0)
fItemSize = header->dataSize / header->count; fItemSize = header->dataSize / header->count;
@@ -100,14 +97,14 @@ BMessageField::Unflatten(int32 _offset)
void void
BMessageField::SetName(const char *newName) BMessageField::SetName(const char *newName)
{ {
FieldHeader *header = Header(); int32 newLength = min_c(strlen(newName), B_FIELD_NAME_LENGTH - 1) + 1;
char *buffer = (char *)fParent->FlatInsert(fOffset + sizeof(FieldHeader),
Header()->nameLength, newLength);
int32 newLength = min_c(strlen(newName), 254) + 1; strncpy(buffer, newName, newLength - 1);
char *buffer = (char *)fParent->FlatInsert(fOffset + sizeof(FieldHeader), header->nameLength, newLength); buffer[newLength - 1] = 0;
strncpy(buffer, newName, newLength);
buffer[newLength] = 0;
header->nameLength = newLength; Header()->nameLength = newLength;
fDataOffset = sizeof(FieldHeader) + newLength; fDataOffset = sizeof(FieldHeader) + newLength;
} }
@@ -235,9 +232,9 @@ BMessageField::RemoveItem(int32 index)
FieldHeader *header = Header(); FieldHeader *header = Header();
if (fFixedSize) { if (fFixedSize) {
fParent->FlatInsert(DATA_OFFSET + (index * fItemSize), fItemSize, 0);
header->dataSize -= fItemSize;
header->count--; header->count--;
header->dataSize -= fItemSize;
fParent->FlatInsert(DATA_OFFSET + (index * fItemSize), fItemSize, 0);
return; return;
} }
@@ -246,9 +243,9 @@ BMessageField::RemoveItem(int32 index)
for (int32 i = index; i < header->count; i++) for (int32 i = index; i < header->count; i++)
((ItemInfo *)fItemInfos.ItemAt(i))->offset -= info->paddedLength; ((ItemInfo *)fItemInfos.ItemAt(i))->offset -= info->paddedLength;
fParent->FlatInsert(DATA_OFFSET + info->offset, info->paddedLength, 0);
header->dataSize -= info->paddedLength;
header->count--; header->count--;
header->dataSize -= info->paddedLength;
fParent->FlatInsert(DATA_OFFSET + info->offset, info->paddedLength, 0);
delete info; delete info;
} }
@@ -276,8 +273,8 @@ void
BMessageField::RemoveSelf() BMessageField::RemoveSelf()
{ {
// remove ourself from the flat buffer // remove ourself from the flat buffer
FieldHeader *header = Header(); int32 dataSize = Header()->dataSize;
fParent->FlatInsert(fOffset, fDataOffset + header->dataSize, 0); fParent->FlatInsert(fOffset, fDataOffset + dataSize, 0);
fOffset = 0; fOffset = 0;
} }