Archived

This forum has been archived. Please start a new discussion on GitHub.

ThreadPool.cpp:733: Ice::MemoryLimitException

Hi All,

I am writing a small test application to learn Ice environment. Here is the slice definition:
#ifndef _TEST_ICE
#define _TEST_ICE
#include <Ice/BuiltinSequences.ice>


module Test {	
	// services
	module Server1 {
		interface RawDataReader {
			Ice::ByteSeq getGlobalHeader();	// send global header
			Ice::ByteSeq getRawData(); // send data with local header
		};
		
		interface RawDataBuffer {
			Ice::ByteSeq getGlobalHeader();
			Ice::ByteSeq getDataFromBuffer(int index);
		};
	};

};
#endif 


I have imlemented two interfaces (they run locally).
- RawDataReader service basically reads a set of rawdata from a binary file, and sends when requested (around 6MB).
- RawDataBuffer: when a client requests rawdata by calling getDataFromBuffer(), it acts like a client for RawDataReader service: it receives the rawdata and sends it directly to the client (so again it sends a data around 6 MB).

However, when I run the program, I get this exception:
ThreadPool.cpp:733: Ice::MemoryLimitException:
protocol error: memory limit exceeded

I have increased Ice.MessageSizeMax to 100 MB, but still having the same problem.

However, if the client bypasses RawDataBuffer service, and directly requests the data from RawDataReader, it works.

I couldn't yet find any coding errors. Are there any other Ice runtime parameters that I should play with to correct this issue?

Thanks,

haris

Comments

  • It's difficult to know where things are going wrong without more info. Could you create a simple self-contained example that shows the problem?

    Also, are you sure that the property is set correctly, before you initialize the communicator?

    Cheers,

    Michi.
  • Yes, I am sure that the property is properly set (checked it in all terminals):
    $ cat /opt/Ice-3.3/default-ice-config 
    Ice.MessageSizeMax=102400 
    $ echo $ICE_CONFIG
    /opt/Ice-3.3/default-ice-config
    

    I have 3 cpp files:

    1. server1.cpp: (when requested, reads a block from data and sends it)
    #include <Ice/Ice.h>
    #include <Test.h>
    #include <complex>
    #include "rawdata.h"
    using namespace std;
    using namespace Test::Server1;
    
    typedef std::vector<Ice::Byte> ByteSeq;
    typedef std::vector<unsigned char> charvec;
    typedef std::complex<float> complexFloat;
    
    
    class RawDataReaderI: public RawDataReader {
    
    	FILE *rawfile;
    	charvec global_header;
    	ByteSeq datavec;
    	char *data;	
    	int datasize;
    	int nc;
    	int ny;
    	int nx;
    	public:
    		RawDataReaderI();
    		~RawDataReaderI();
    		virtual ByteSeq getRawData(const Ice::Current&);
    		virtual ByteSeq getGlobalHeader(const Ice::Current&);
    };
    
    // in the main:
    ....
    		ic = Ice::initialize(argc, argv);
    
    		Ice::ObjectAdapterPtr adapter_dr = ic->createObjectAdapterWithEndpoints("RawDataReaderImp",
    																			   "default -p 10000");
    		Ice::ObjectPtr object_dr = new RawDataReaderI;
    		adapter_dr->add(object_dr, ic->stringToIdentity("RawDataReader"));
    		adapter_dr->activate();
    
    		ic->waitForShutdown();
    .....
    
    

    2. server2.cpp (when requested, requests data from server1, and sends it directly to its client (no modifications on the data))
    class RawDataBufferI: public RawDataBuffer {
    	
    	Ice::CommunicatorPtr ic;
    	charvec global_header;
    	int retrieveGlobalHeader();
    	public:
    		RawDataBufferI();
    		~RawDataBufferI();
    		virtual ByteSeq getDataFromBuffer(int, const Ice::Current&);
    		virtual ByteSeq getGlobalHeader(const Ice::Current&);
    	
    };
    
    RawDataBufferI::RawDataBufferI() {
    	ic = Ice::initialize();
    }
    
    RawDataBufferI::~RawDataBufferI() {
    	if (ic)
    		ic->destroy();			
    }
    
    int RawDataBufferI::retrieveGlobalHeader() {
    	int status = 0;
    	
    	try {
    		
    		Ice::ObjectPrx base = ic->stringToProxy("RawDataReader:default -p 10000");
    		RawDataReaderPrx datareader = RawDataReaderPrx::checkedCast(base);
    		if (!datareader)
    			throw("Invalid Proxy");
    
    		global_header = datareader->getGlobalHeader();
    		
    	} catch (const Ice::Exception & e) {
    		cerr << e << endl;
    		status = 1;
    	} catch (const char * msg) {
    		cerr << msg << endl;
    		status = 1;
    	}
    	
    	return status;
    }
    
    ByteSeq RawDataBufferI::getGlobalHeader(const Ice::Current& c) {
    	int status;
    	status = retrieveGlobalHeader();
    	if (status)
    		cerr << "could not retrieve global header" << endl;
    	else {
    		cout << "got the global header from server 1" << endl;
    	}
    	return (ByteSeq)global_header;
    }
    
    
    ByteSeq RawDataBufferI::getDataFromBuffer(int coil, const Ice::Current& c) {
    	int status = 0;
    	ByteSeq data_rec;
    	try {
    		Ice::ObjectPrx base = ic->stringToProxy("RawDataReader:default -p 10000");
    		RawDataReaderPrx datareader = RawDataReaderPrx::checkedCast(base);
    		if (!datareader)
    			throw("Invalid Proxy");
    		RawFileGlobalHeader *glh = (RawFileGlobalHeader *)&global_header[0]; 
    		int nc = glh->info.nrec;
    		int nx = glh->info.xres;
    		int ny = glh->info.yres;
    		cout << nc << " " << nx << " " << ny << endl;
    		data_rec.resize(sizeof(RawFileLocalHeader) + sizeof(complexFloat) * nx * ny *nc);
    		cout << "[Server 2] requesting raw data from Server 1" << endl;
    		data_rec = datareader->getRawData();
    		cout << "[Server 2] raw data received from server1" << endl; 
    	} catch (const Ice::Exception & e) {
    		cerr << e << endl;
    		status = 1;
    	} catch (const char * msg) {
    		cerr << msg << endl;
    		status = 1;
    	}
    	return data_rec;
    }
    
    // in the main:
    ....
    		ic = Ice::initialize(argc, argv);
    
    	
    
    		Ice::ObjectAdapterPtr adapter_db = ic->createObjectAdapterWithEndpoints("RawDataBufferImp", 
    																			   "default -p 10001");
    		Ice::ObjectPtr object_db = new RawDataBufferI;
    		adapter_db->add(object_db, ic->stringToIdentity("RawDataBuffer"));
    		adapter_db->activate();
    	
    		ic->waitForShutdown();
    ....
    
    

    3. client.cpp
    int main(int argc, char**argv) {
    	int status = 0;
    	Ice::CommunicatorPtr ic;
    
    	try {
    		ic = Ice::initialize(argc, argv);
    
    			Ice::ObjectPrx base = ic->stringToProxy("RawDataBuffer:default -p 10001");
    			RawDataBufferPrx databuffer = RawDataBufferPrx::checkedCast(base);
    			if (!databuffer)
    				throw("Invalid Proxy");
    
    			RawFileGlobalHeader rgh;
    			charvec cc;
    			cc.resize(sizeof(RawFileGlobalHeader));
    			cc = (charvec) databuffer->getGlobalHeader();
    			memcpy(&rgh, &cc[0], sizeof(RawFileGlobalHeader));
    			cout << rgh.info.nrec << " " << rgh.info.xres << " " << rgh.info.yres << endl;
    
    			charvec cc2;
    			cc2.resize(sizeof(RawFileLocalHeader) + sizeof(complexFloat)*rgh.info.nrec*rgh.info.xres *rgh.info.yres);
    			cc2 = (charvec) databuffer->getDataFromBuffer(1);
    			RawFileLocalHeader rflh;
    			memcpy(&rflh, &cc2[0], sizeof(RawFileLocalHeader));
    			cout << "From local header: " << rflh.info.noiseScan << " " << rflh.info.nEchos << endl;
    		
    	} catch (const Ice::Exception & e) {
    		cerr << e << endl;
    		status = 1;
    	} catch (const char * msg) {
    		cerr << msg << endl;
    		status = 1;
    	}
    	if (ic)
    		ic->destroy();
    	return status;
    }
    

    So, when I run the executables, and when client requests getGlobalHeader() (server2), server2 gets global header from server1 and sends it directly. Global header is 1K in size. This part works OK. But, when client asks for data (~6MB), server2 gives this error when requesting data from server1:
    $ ./server2
    got the global header from server 1
    15 384 144
    [Server 2] requesting raw data from Server 1
    ThreadPool.cpp:733: Ice::MemoryLimitException:
    protocol error: memory limit exceeded

    Server1 does not give any error messages.

    If client directly requests this service from server1, it works. I could not find the reason for that. What server2 does is simply acting like a client for server1, and then serving its client. It doesn't do any modifications on the data. It gets the data and directly sends it. Can it be related to some other Ice runtime properties that I should adjust? Or am I making a simple coding error?

    Thanks in advance

    haris
  • benoit
    benoit Rennes, France
    Hi,

    There are no other properties to set, setting Ice.MessageSizeMax should be sufficient. For some reasons, it looks like the Ice.MessageSizeMax property isn't getting set properly for server2. Did you try passing the property directly to the exe or setting it programatically in the code? For example:
    ./server2 --Ice.MessageSizeMax=102400
    

    Or
    Ice::InitializationData initData;
    initData.properties = Ice::createProperties(argc, argv);
    initData.properties->setProperty("Ice.MessageSizeMax", "102400");
    ic = Ice::initialize(argc, argv, initData);
    

    Cheers,
    Benoit
  • Yes, it worked. Thank you. I was not passing argc and argv to Ice::initialize() function. Maybe that is why it could not get the proper message size before.

    Cheers,

    haris
  • benoit
    benoit Rennes, France
    Hi Haris,

    Yes, that's the reason. The Ice::initialize() method initializes a communicator with no configuration (and therefore ignores the ICE_CONFIG environment variable setting).

    Cheers,
    Benoit.