From d35c42a0c9b898fe08b2a6beb7b1dead7a09f029 Mon Sep 17 00:00:00 2001 From: Michael Lotz Date: Tue, 9 Aug 2005 14:27:35 +0000 Subject: [PATCH] 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 --- headers/private/app/Message3.h | 212 +++++++++-------------------- headers/private/app/MessageBody3.h | 8 +- src/kits/app/Message3.cpp | 18 +-- src/kits/app/MessageBody3.cpp | 68 +++++++-- src/kits/app/MessageField3.cpp | 27 ++-- 5 files changed, 138 insertions(+), 195 deletions(-) diff --git a/headers/private/app/Message3.h b/headers/private/app/Message3.h index 9a09b23c2c..1a6eb476f0 100644 --- a/headers/private/app/Message3.h +++ b/headers/private/app/Message3.h @@ -68,7 +68,7 @@ enum B_ID_SPECIFIER, B_SPECIFIERS_END = 128 - // app-defined specifiers start at B_SPECIFIERS_END+1 + // app-defined specifiers start at B_SPECIFIERS_END + 1 }; namespace BPrivate { @@ -279,174 +279,88 @@ virtual ~BMessage(); float FindFloat(const char *, int32 n = 0) const; double FindDouble(const char *, int32 n = 0) const; - class Private; + class Private; private: - class Header; + class Header; -friend class BMessageQueue; -friend class BMessenger; -friend class BApplication; -friend class Header; -friend class Private; +friend class BMessageQueue; +friend class BMessenger; +friend class BApplication; +friend class Header; +friend class Private; -friend inline void _set_message_target_(BMessage *, int32, bool); -friend inline void _set_message_reply_(BMessage *, BMessenger); -friend inline int32 _get_message_target_(BMessage *); -friend inline bool _use_preferred_target_(BMessage *); +friend inline void _set_message_target_(BMessage *, int32, bool); +friend inline void _set_message_reply_(BMessage *, BMessenger); +friend inline int32 _get_message_target_(BMessage *); +friend inline bool _use_preferred_target_(BMessage *); - // deprecated - BMessage(BMessage *a_message); + // deprecated + BMessage(BMessage *a_message); -virtual void _ReservedMessage1(); -virtual void _ReservedMessage2(); -virtual void _ReservedMessage3(); +virtual void _ReservedMessage1(); +virtual void _ReservedMessage2(); +virtual void _ReservedMessage3(); - void init_data(); - status_t flatten_target_info(BDataIO *stream, - ssize_t size, - uchar flags) const; - status_t real_flatten(char *result, ssize_t size) const; - status_t real_flatten(BDataIO *stream, ssize_t *size) const; - char *stack_flatten(char *stack_ptr, - ssize_t stack_size, - bool incl_reply, + void init_data(); + status_t real_flatten(char *result, ssize_t size) const; + 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; - status_t _UnflattenKMessage(const char *buffer); + status_t _UnflattenKMessage(const char *buffer); - ssize_t calc_size(uchar flags) 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; + ssize_t calc_hdr_size() const; - status_t _send_(port_id port, - int32 token, - bool preferred, - bigtime_t timeout, - bool reply_required, - BMessenger &reply_to) const; - status_t send_message(port_id port, - team_id port_owner, - int32 token, - 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); + status_t _send_(port_id port, int32 token, + bool preferred, bigtime_t timeout, + bool reply_required, + BMessenger &reply_to) const; + status_t send_message(port_id port, team_id port_owner, + int32 token, bool preferred, + BMessage *reply, + bigtime_t send_timeout, + bigtime_t reply_timeout) const; -static void _StaticInit(); -static void _StaticCleanup(); -static void _StaticCacheCleanup(); +static status_t _SendFlattenedMessage(void *data, int32 size, + port_id port, int32 token, bool preferred, + bigtime_t timeout); - enum { sNumReplyPorts = 3 }; -static port_id sReplyPorts[sNumReplyPorts]; -static long sReplyPortInUse[sNumReplyPorts]; -static int32 sGetCachedReplyPort(); +static void _StaticInit(); +static void _StaticCleanup(); +static void _StaticCacheCleanup(); -static BBlockCache *sMsgCache; + enum { sNumReplyPorts = 3 }; +static port_id sReplyPorts[sNumReplyPorts]; +static long sReplyPortInUse[sNumReplyPorts]; +static int32 sGetCachedReplyPort(); - struct dyn_array { - int32 fLogicalBytes; - int32 fPhysicalBytes; - int32 fChunkSize; - int32 fCount; - int32 fEntryHdrSize; - }; +static BBlockCache *sMsgCache; - struct entry_hdr : public dyn_array { - entry_hdr *fNext; - uint32 fType; - uchar fNameLength; - char fName[1]; - }; + BMessage *fUnused1; + int32 fTarget; + BMessage *fOriginal; + uint32 fUnused2; + int32 fCurSpecifier; + uint32 fReserved[4]; - struct var_chunk { - 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; + BPrivate::BMessageBody *fBody; struct reply_to_info { - port_id port; - int32 target; - team_id team; - bool preferred; - } fReplyTo; + port_id port; + int32 target; + team_id team; + bool preferred; + } fReplyTo; - bool fPreferred; - bool fReplyRequired; - bool fReplyDone; - bool fIsReply; - bool fWasDelivered; - bool fReadOnly; - bool fHasSpecifiers; + bool fPreferred; + bool fReplyRequired; + bool fReplyDone; + bool fIsReply; + bool fWasDelivered; + bool fReadOnly; + bool fHasSpecifiers; }; //------------------------------------------------------------------------------ diff --git a/headers/private/app/MessageBody3.h b/headers/private/app/MessageBody3.h index c66aee4683..c5e61d08d3 100644 --- a/headers/private/app/MessageBody3.h +++ b/headers/private/app/MessageBody3.h @@ -69,9 +69,10 @@ public: void PrintToStream() const; // flat buffer management -inline uint8 *FlatBuffer() const { return (uint8 *)fFlatBuffer.Buffer(); }; +inline uint8 *FlatBuffer() const { return fFlatBuffer; }; uint8 *FlatInsert(int32 offset, ssize_t oldLength, ssize_t newLength); + void FlatResize(int32 newSize); // hash table support void HashInsert(BMessageField *field); @@ -91,7 +92,10 @@ private: BMessageField **fFieldTable; int32 fFieldTableSize; - BMallocIO fFlatBuffer; + uint8 *fFlatBuffer; + int32 fFlatLength; + int32 fFlatAllocated; + int32 fBlockSize; }; } // namespace BPrivate diff --git a/src/kits/app/Message3.cpp b/src/kits/app/Message3.cpp index 8ca3e09f7e..37841ddc6a 100644 --- a/src/kits/app/Message3.cpp +++ b/src/kits/app/Message3.cpp @@ -465,14 +465,9 @@ BMessage::operator=(const BMessage &msg) { what = msg.what; - link = msg.link; fTarget = msg.fTarget; fOriginal = msg.fOriginal; - fChangeCount = msg.fChangeCount; fCurSpecifier = msg.fCurSpecifier; - fPtrOffset = msg.fPtrOffset; - - fEntries = msg.fEntries; fReplyTo.port = msg.fReplyTo.port; fReplyTo.target = msg.fReplyTo.target; @@ -497,14 +492,9 @@ BMessage::init_data() { what = 0; - link = NULL; fTarget = B_NULL_TOKEN; fOriginal = NULL; - fChangeCount = 0; fCurSpecifier = -1; - fPtrOffset = 0; - - fEntries = NULL; fReplyTo.port = -1; fReplyTo.target = B_NULL_TOKEN; @@ -593,7 +583,7 @@ BMessage::IsReply() const void BMessage::PrintToStream() const { - printf("\nBMessage: what = "); + printf("BMessage: what = "); printf("%c%c%c%c", (uint8)(what >> 24), (uint8)(what >> 16), (uint8)(what >> 8), (uint8)what); printf(" (0x%lX or %ld)\n", what, what); @@ -794,7 +784,7 @@ BMessage::SendReply(BMessage *the_reply, BMessage *reply_to_reply, ssize_t 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, 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; if (calcd_size > stack_size) { stack_ptr = new char[calcd_size]; @@ -1657,7 +1647,7 @@ BMessage::_UnflattenKMessage(const char *buffer) ssize_t -BMessage::calc_hdr_size(uchar flags) const +BMessage::calc_hdr_size() const { ssize_t size = min_hdr_size(); diff --git a/src/kits/app/MessageBody3.cpp b/src/kits/app/MessageBody3.cpp index a36fe8e576..3d4d23f7d4 100644 --- a/src/kits/app/MessageBody3.cpp +++ b/src/kits/app/MessageBody3.cpp @@ -9,6 +9,7 @@ /* BMessageBody handles data storage and retrieval for BMessage. */ #include +#include #include #include #include "MessageBody3.h" @@ -17,6 +18,18 @@ 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() { InitCommon(); @@ -42,9 +55,8 @@ BMessageBody::operator=(const BMessageBody &other) { if (this != &other) { MakeEmpty(); - // the flat buffer has no last entry flag included - BMemoryIO memoryIO(other.FlatBuffer(), other.FlattenedSize() - 1); - Unflatten(&memoryIO, other.FlattenedSize() - 1); + BMemoryIO memoryIO(other.fFlatBuffer, other.fFlatLength); + Unflatten(&memoryIO, other.fFlatLength); } return *this; @@ -54,6 +66,13 @@ BMessageBody::operator=(const BMessageBody &other) status_t 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; fFieldTable = new BMessageField *[fFieldTableSize]; HashClear(); @@ -203,14 +222,14 @@ ssize_t BMessageBody::FlattenedSize() const { // one more for the last entry flag - return fFlatBuffer.BufferLength() + 1; + return fFlatLength + 1; } status_t BMessageBody::Flatten(BDataIO *stream) const { - stream->Write(fFlatBuffer.Buffer(), fFlatBuffer.BufferLength()); + stream->Write(fFlatBuffer, fFlatLength); uint8 lastField = MSG_LAST_ENTRY; status_t error = stream->Write(&lastField, sizeof(lastField)); @@ -230,14 +249,14 @@ BMessageBody::Unflatten(BDataIO *stream, int32 length) if (length <= 0) return B_OK; - fFlatBuffer.SetSize(length); - status_t error = stream->Read((void *)fFlatBuffer.Buffer(), length); + FlatResize(length); + status_t error = stream->Read(fFlatBuffer, length); if (error < B_OK) return B_ERROR; int32 offset = 0; - uint8 *location = (uint8 *)fFlatBuffer.Buffer(); + uint8 *location = fFlatBuffer; while (offset < error && *location & MSG_FLAG_VALID) { BMessageField *field = new BMessageField(this); int32 fieldLength = field->Unflatten(offset); @@ -257,7 +276,7 @@ BMessageBody::Unflatten(BDataIO *stream, int32 length) } // set the buffer to the actual size - fFlatBuffer.SetSize(offset); + FlatResize(offset); return B_OK; } @@ -324,8 +343,7 @@ BMessageBody::AddData(const char *name, type_code type, status_t &error) return foundField; // add a new field if it's not yet present - BMessageField *newField = new BMessageField(this, - fFlatBuffer.BufferLength(), name, type); + BMessageField *newField = new BMessageField(this, fFlatLength, name, type); fFieldList.AddItem(newField); HashInsert(newField); @@ -430,7 +448,12 @@ BMessageBody::MakeEmpty() } fFieldList.MakeEmpty(); - fFlatBuffer.SetSize(0); + + free(fFlatBuffer); + fFlatBuffer = NULL; + fFlatLength = 0; + fFlatAllocated = 0; + HashClear(); 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 * 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; ssize_t change = newLength - oldLength; - ssize_t bufferLength = fFlatBuffer.BufferLength(); + ssize_t bufferLength = fFlatLength; if (change > 0) { - fFlatBuffer.SetSize(bufferLength + change); + FlatResize(bufferLength + change); // usual case for adds if (offset == bufferLength) @@ -526,7 +564,7 @@ BMessageBody::FlatInsert(int32 offset, ssize_t oldLength, ssize_t newLength) } if (change < 0) - fFlatBuffer.SetSize(bufferLength + change); + FlatResize(bufferLength + change); for (int32 index = fFieldList.CountItems() - 1; index >= 0; index--) { BMessageField *field = (BMessageField *)fFieldList.ItemAt(index); diff --git a/src/kits/app/MessageField3.cpp b/src/kits/app/MessageField3.cpp index ec022bd978..209ec0ec6a 100644 --- a/src/kits/app/MessageField3.cpp +++ b/src/kits/app/MessageField3.cpp @@ -71,9 +71,6 @@ BMessageField::Unflatten(int32 _offset) fDataOffset = sizeof(FieldHeader) + header->nameLength; fFixedSize = header->flags & MSG_FLAG_FIXED_SIZE; - if (header->nameLength == 0) - return 0; - if (fFixedSize) { if (header->count > 0) fItemSize = header->dataSize / header->count; @@ -100,14 +97,14 @@ BMessageField::Unflatten(int32 _offset) void 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; - char *buffer = (char *)fParent->FlatInsert(fOffset + sizeof(FieldHeader), header->nameLength, newLength); - strncpy(buffer, newName, newLength); - buffer[newLength] = 0; + strncpy(buffer, newName, newLength - 1); + buffer[newLength - 1] = 0; - header->nameLength = newLength; + Header()->nameLength = newLength; fDataOffset = sizeof(FieldHeader) + newLength; } @@ -235,9 +232,9 @@ BMessageField::RemoveItem(int32 index) FieldHeader *header = Header(); if (fFixedSize) { - fParent->FlatInsert(DATA_OFFSET + (index * fItemSize), fItemSize, 0); - header->dataSize -= fItemSize; header->count--; + header->dataSize -= fItemSize; + fParent->FlatInsert(DATA_OFFSET + (index * fItemSize), fItemSize, 0); return; } @@ -246,9 +243,9 @@ BMessageField::RemoveItem(int32 index) for (int32 i = index; i < header->count; i++) ((ItemInfo *)fItemInfos.ItemAt(i))->offset -= info->paddedLength; - fParent->FlatInsert(DATA_OFFSET + info->offset, info->paddedLength, 0); - header->dataSize -= info->paddedLength; header->count--; + header->dataSize -= info->paddedLength; + fParent->FlatInsert(DATA_OFFSET + info->offset, info->paddedLength, 0); delete info; } @@ -276,8 +273,8 @@ void BMessageField::RemoveSelf() { // remove ourself from the flat buffer - FieldHeader *header = Header(); - fParent->FlatInsert(fOffset, fDataOffset + header->dataSize, 0); + int32 dataSize = Header()->dataSize; + fParent->FlatInsert(fOffset, fDataOffset + dataSize, 0); fOffset = 0; }