| Title: | ObjectBroker Development - BEA Systems' CORBA |
| Notice: | See note 2 for kit locations; note 4 for training |
| Moderator: | RECV::GUMBEL d |
| Created: | Thu Dec 27 1990 |
| Last Modified: | Fri Jun 06 1997 |
| Last Successful Update: | Fri Jun 06 1997 |
| Number of topics: | 2482 |
| Total number of notes: | 13057 |
v2.7-11, NT4/Win95, C++ bindings.
A project I work with is having problems with bounded strings.
I summarize the problem like this: we have problems when we
exceed a certain limit when we try to use unbouded sequences
of structures containing bounded strings.
Here's a summary of the tests I've made so far:
Test 1: unbounded sequence of unbounded strings works well up to 1600 strings
of 100. (Didn't try further).
Test 2: unbounded sequence of bounded strings works well up to 1600 strings of
10. (However, I can also create and return a sequence of strings of 100 with no
problem!).
Test 3: unbounded sequence of struct of 3 bounded strings of 10 and 1 unbounded
string. Client detects exception:
OBB_INV_MRSHEXCBUF (e), Exceeded marshalling buffer.
with 272 elements in the sequence.
Less than that it seems to work. More than 272 provokes a crash on the server.
Test 4: unbounded sequence of a struct containing 4 unbounded strings. No
problems detected.
Test 5: unbounded sequence of struct of 4 bounded strings of 10.
Client detects exception:
OBB_INV_MRSHEXCBUF (e), Exceeded marshalling buffer.
with 271 elements in the sequence.
Less than that it seems to work. More than 271 provokes a crash on the server.
Test 6: unbounded sequence of a struct with just one bounded string of 10. This
starts having problems at 1082 items. ("Exceeded marshaling buffer..."). Some
weird stuff if I set strings less than 10 (the string bound). I can for example
create a sequence of 1000 strings of 6, but not of 5!
In subsequent replies I'll give you the idl, a sample method and the calling
client.
John D.
| T.R | Title | User | Personal Name | Date | Lines |
|---|---|---|---|---|---|
| 2445.1 | the idl | LEMAN::DONALDSON | Froggisattva! Froggisattva! | Mon Mar 03 1997 06:11 | 106 |
module m1
{
typedef sequence<string> tUseqUstr;
typedef string<10> tBstr10;
typedef sequence<tBstr10> tUseqBstr10;
typedef struct tUDT1_
{
tBstr10 Bstr10_1;
tBstr10 Bstr10_2;
tBstr10 Bstr10_3;
string Ustr;
} tUDT1;
typedef sequence<tUDT1> tUseqUDT1;
typedef struct tUDT2_
{
string Ustr_1;
string Ustr_2;
string Ustr_3;
string Ustr_4;
} tUDT2;
typedef sequence<tUDT2> tUseqUDT2;
typedef struct tUDT3_
{
tBstr10 Bstr10_1;
tBstr10 Bstr10_2;
tBstr10 Bstr10_3;
tBstr10 Bstr10_4;
} tUDT3;
typedef sequence<tUDT3> tUseqUDT3;
typedef struct tUDT4_
{
tBstr10 Bstr10_1;
} tUDT4;
typedef sequence<tUDT4> tUseqUDT4;
interface i1
{
void OUseqUstr
(
in long totalUseq,
in long totalUstr,
out tUseqUstr oseq
);
void OUseqBstr10
(
in long totalUseq,
in long totalBstr,
out tUseqBstr10 oseq
);
void OUseqUDT1
(
in long totalUseq,
in long totalUstr,
in long totalBstr,
out tUseqUDT1 oseq
);
void OUseqUDT2
(
in long totalUseq,
in long totalUstr,
out tUseqUDT2 oseq
);
void OUseqUDT3
(
in long totalUseq,
in long totalBstr,
out tUseqUDT3 oseq
);
void OUseqUDT4
(
in long totalUseq,
in long totalBstr,
out tUseqUDT4 oseq
);
};
};
#pragma repository_id( "m1::tUseqUstr", "7b1ed45fb488.02.c1.50.32.68.00.00.00")
#pragma interface_id( "m1::i1", "7b1ed45fb489.02.c1.50.32.68.00.00.00")
#pragma operation_id( "m1::i1::OUseqUstr", "7b1ed45fb48a.02.c1.50.32.68.00.00.00", 1)
#pragma repository_id( "m1::tBstr10", "7b1fb93f4bb2.02.c1.50.32.68.00.00.00")
#pragma repository_id( "m1::tUseqBstr10", "7b1fb93f4bb3.02.c1.50.32.68.00.00.00")
#pragma operation_id( "m1::i1::OUseqBstr10", "7b1fb93f4bb4.02.c1.50.32.68.00.00.00", 2)
#pragma repository_id( "m1::tUDT1_", "7b21560765c1.02.c1.50.32.68.00.00.00")
#pragma repository_id( "m1::tUDT1", "7b21560765c2.02.c1.50.32.68.00.00.00")
#pragma repository_id( "m1::tUseqUDT1", "7b21560765c3.02.c1.50.32.68.00.00.00")
#pragma operation_id( "m1::i1::OUseqUDT1", "7b21560765c4.02.c1.50.32.68.00.00.00", 3)
#pragma repository_id( "m1::tUDT2_", "7b21a6e42c8b.02.c1.50.32.68.00.00.00")
#pragma repository_id( "m1::tUDT2", "7b21a6e42c8c.02.c1.50.32.68.00.00.00")
#pragma repository_id( "m1::tUseqUDT2", "7b21a6e42c8d.02.c1.50.32.68.00.00.00")
#pragma operation_id( "m1::i1::OUseqUDT2", "7b21a6e42c8e.02.c1.50.32.68.00.00.00", 4)
#pragma repository_id( "m1::tUDT3_", "7b21c3cdd19f.02.c1.50.32.68.00.00.00")
#pragma repository_id( "m1::tUDT3", "7b21c3cdd1a0.02.c1.50.32.68.00.00.00")
#pragma repository_id( "m1::tUseqUDT3", "7b21c3cdd1a1.02.c1.50.32.68.00.00.00")
#pragma operation_id( "m1::i1::OUseqUDT3", "7b21c3cdd1a2.02.c1.50.32.68.00.00.00", 5)
#pragma repository_id( "m1::tUDT4_", "7b2819b9ad65.02.c1.50.32.68.00.00.00")
#pragma repository_id( "m1::tUDT4", "7b2819b9ad66.02.c1.50.32.68.00.00.00")
#pragma repository_id( "m1::tUseqUDT4", "7b2819b9ad67.02.c1.50.32.68.00.00.00")
#pragma operation_id( "m1::i1::OUseqUDT4", "7b2819b9ad68.02.c1.50.32.68.00.00.00", 6)
| |||||
| 2445.2 | a sample method | LEMAN::DONALDSON | Froggisattva! Froggisattva! | Mon Mar 03 1997 06:20 | 92 |
/*
*
* ROUTINE NAME: i1Impl::i1Impl_OUseqUDT1
*
* FUNCTIONAL DESCRIPTION:
*
* Method routine for OUseqUDT1.
* (Implementation : i1Impl)
*
*/
void i1Impl::i1Impl_OUseqUDT1 (
CORBA::Long totalUseq,
CORBA::Long totalUstr,
CORBA::Long totalBstr,
m1::tUseqUDT1 *& oseq,
CORBA::Environment & ev)
{
/* OBB_PRESERVE_BEGIN(i1Impl::i1Impl_OUseqUDT1) */
cout << endl << "Entering i1Impl::i1Impl_OUseqUDT1" << endl;
cout << " totalUseq=" << totalUseq << endl;
cout << " totalUstr=" << totalUstr << endl;
cout << " totalBstr=" << totalBstr << endl;
// create the buffer of the sequence
m1::tUDT1 *seqBuffer = m1::tUseqUDT1::allocbuf( totalUseq);
// make strings and build them into the sequence buffer
for (short i=0; i<totalUseq; i++)
{
m1::tUDT1 *pUDT = &((seqBuffer)[i]);
m1::tBstr10 Bstr = (m1::tBstr10)malloc(totalBstr+1);
for (short j=0; j<totalBstr; j++)
{
Bstr[j] = 'a';
}
Bstr[totalBstr] = '\0';
pUDT->Bstr10_1 = Bstr;
Bstr = (m1::tBstr10)malloc(totalBstr+1);
for (j=0; j<totalBstr; j++)
{
Bstr[j] = 'b';
}
Bstr[totalBstr] = '\0';
pUDT->Bstr10_2 = Bstr;
Bstr = (m1::tBstr10)malloc(totalBstr+1);
for (j=0; j<totalBstr; j++)
{
Bstr[j] = 'c';
}
Bstr[totalBstr] = '\0';
pUDT->Bstr10_3 = Bstr;
CORBA::Char *Ustr = (CORBA::Char*)malloc(totalUstr+1);
for (j=0; j<totalUstr; j++)
{
Ustr[j] = 'd';
}
Ustr[totalUstr] = '\0';
pUDT->Ustr = Ustr;
}
// construct the sequence
oseq = new m1::tUseqUDT1( totalUseq, totalUseq, seqBuffer, CORBA_TRUE);
// print out the result locally to check its ok
cout << endl;
cout << "maximum=" << oseq->maximum() << endl;
cout << "length =" << oseq->length() << endl;
for (i=0; i<long(oseq->length()); i++)
{
m1::tUDT1 *pUDT = &((*oseq)[i]);
cout <<
"<" << pUDT->Bstr10_1 << "> " <<
"<" << pUDT->Bstr10_2 << "> " <<
"<" << pUDT->Bstr10_3 << "> " <<
"<" << pUDT->Ustr << "> " << i << endl;
};
cout << endl;
cout << "Exiting i1Impl::i1Impl_OUseqUDT1" << endl;
/* OBB_PRESERVE_END(i1Impl::i1Impl_OUseqUDT1) */
return ;
}
| |||||
| 2445.3 | the calling client | LEMAN::DONALDSON | Froggisattva! Froggisattva! | Mon Mar 03 1997 06:24 | 38 |
void TestUseqUDT1( m1::i1_ptr i1Ptr)
{
CORBA::Environment ev;
m1::tUseqUDT1 *theSeq;
short seqSize;
short uStrSize;
short bStrSize;
cout << endl << "Test: Unbounded sequence of user-defined type 1" << endl;
cout << "Size of unbounded sequence: " << flush;
cin >> seqSize;
cout << "Size of unbounded string: " << flush;
cin >> uStrSize;
cout << "Size of bounded string: " << flush;
cin >> bStrSize;
i1Ptr->OUseqUDT1( seqSize, uStrSize, bStrSize, theSeq, ev);
exitIfException( &ev, "i1Ptr->OUseqUDT1");
cout << endl;
cout << "maximum=" << theSeq->maximum() << endl;
cout << "length =" << theSeq->length() << endl;
for (short i=0; i<long(theSeq->length()); i++)
{
m1::tUDT1 *pUDT = &((*theSeq)[i]);
cout <<
"<" << pUDT->Bstr10_1 << "> " <<
"<" << pUDT->Bstr10_2 << "> " <<
"<" << pUDT->Bstr10_3 << "> " <<
"<" << pUDT->Ustr << "> " << i << endl;
};
cout << endl;
// clean up. Do we need to freebuf first?
delete theSeq;
};
| |||||
| 2445.4 | some questions and observations | LEMAN::DONALDSON | Froggisattva! Froggisattva! | Mon Mar 03 1997 06:42 | 26 |
- is the general approach ('allocbuf' + 'new') for creating sequences
recommended? Or should I prefer 'new' plus '[]'?
- is the use of malloc in the method okay? (For example, should I
create a string_ptr instead?).
- do I need the trailing zero at the end of the strings?
- should the client just 'delete' or should it freebuf (or
anything else?)?
- the other tests use exactly the same techniques to successfully
send sequences of:
unbounded strings
bounded strings
structures of unbounded strings
- sequences of structures containing 1 bounded string can be up to 1080 long.
sequences of structures containing 4 bounded strings can be up to 270 long.
After this limit they fail with 'exceeded message buffer' (see note .0).
Is the factor of 4 here significant?
If you push up the count a bit further the server just crashes after the
method exits (the sequence appears to be well-constrcuted in the sense
that I can print it out).
John D.
| |||||
| 2445.5 | REQUE::BOWER | Peter Bower, ObjectBroker | Fri Mar 07 1997 11:49 | 49 | |
> is the general approach ('allocbuf' + 'new') for creating sequences
> recommended? Or should I prefer 'new' plus '[]'?
allocbuf and then new will work. You could also do new and then a
call to set the length. CORBA does not allow you to do a [] without
first setting the length.
> is the use of malloc in the method okay? (For example, should I
> create a string_ptr instead?).
No! The C++ bindings release the memory that you return. Therefore,
the allocation and deallocation mechanisms must match. CORBA states
that strings should be allocated using CORBA::string_alloc and
released via CORBA::string_free. Therefore, change your use
of malloc to string_alloc and remove the + 1 - string_alloc allocates
the byte for the null for you. When I ran you program through
purify on nt, I saw lots of free errors due to the fact that you
use malloc and we do not use free.
> do I need the trailing zero at the end of the strings?
Yes. CORBA states that all strings are null terminated.
> should the client just 'delete' or should it freebuf (or
anything else?)?
The client 'deletes'. The out sequence is a class; it contains a buffer
but deleting the class releases all buffers and data within the
buffers.
> the other tests use exactly the same techniques to successfully
> send sequences of:
> Is the factor of 4 here significant?
Most likely the factor of 4 is not significant. OBB calculates the
length of the buffer to marshall into by walking the returned
data. It then allocates the buffer and then walks the returned
data and marshalls it. There appears to be an error in the
calculation of the length and OBB is writing over the end of
the buffer. There is extra space at the end of the buffer so
it takes a large sequence to demonstrate the problem.
I have reproduced it here.
| |||||
| 2445.6 | REQUE::BOWER | Peter Bower, ObjectBroker | Fri Mar 07 1997 13:01 | 4 | |
This is a similar problem to qar 3468. I will investigate
putting the fix into arches and will send you a workaround.
| |||||
| 2445.7 | LEMAN::DONALDSON | Froggisattva! Froggisattva! | Mon Mar 10 1997 10:19 | 6 | |
Peter, thanks for the clarification. I'll fix my test code to do as you propose. John D. | |||||