trouble sending very large rpc replies

James Peach jpeach at sgi.com
Tue Jan 3 02:16:57 GMT 2006


On Tue, Jan 03, 2006 at 01:14:51PM +1100, Jeremy Allison wrote:
> On Sat, Dec 24, 2005 at 02:02:36PM +1100, James Peach wrote:
> > Hi guys,
> > 
> > I'm still slowly plugging away at integrating PCP support for
> > performance metrics. When the necessary management folk get back from
> > holidays in a couple of weeks, I'll be able to post some patches and
> > test programs.
> > 
> > In the meantime, I've hit what appears to be a snag in the RPC layer.
> > When the client fetches the counter names and help text registry
> > entries, these get quite large due to the number of counters we have.
> > The help text is ~100KiB on Linux and ~500KiB on IRIX.
> > 
> > I'm currently testing on Linux and it seems that send_trans_reply thinks
> > this is too large a chunk of data to send and I get the following
> > failure:
> >         
> >         [2005/12/24 13:26:42, 5] smbd/ipc.c:send_trans_reply(89)
> >         send_trans_reply: buffer 1024 too large
> >         [2005/12/24 13:26:42, 3] smbd/error.c:error_packet(146)
> >         error packet at smbd/ipc.c(97) cmd=37 (SMBtrans) STATUS_BUFFER_OVERFLOW
> >         
> > Is this behaviour to be expected? Is there something I can do to work
> > around it?
> > 
> > The test program in question does a RegQueryValueEx starting with a
> > 16KiB buffer. It grows the buffer by 16KiB each time is gets a
> > ERROR_MORE_DATA return value.
> 
> Can you send me the test program please. I'll ensure this gets fixed.

see attached

-- 
James Peach | jpeach at sgi.com | SGI Australian Software Group
I don't speak for SGI.
-------------- next part --------------
/* 
 *  Dump performance counter data.
 *
 *  Copyright (C) 2005 Silicon Graphics, Inc. All rights reserved.
 *	James Peach <jpeach at sgi.com>
 *  
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *  
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *  
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */

#include "stdafx.h"

const char PROGNAME[] = "perfdump";

#define FORMAT_ERROR(err) format_error(__FILE__, __LINE__, err)
#define XFORMAT_ERROR(err) xformat_error(__FILE__, __LINE__, err)

void format_error(const char * file, int line, DWORD errcode)
{
	LPVOID lpMsgBuf;

	::FormatMessage(
        FORMAT_MESSAGE_ALLOCATE_BUFFER | 
        FORMAT_MESSAGE_FROM_SYSTEM,
        NULL,
        errcode,
        MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
        (LPTSTR) &lpMsgBuf,
        0, NULL );

	std::cerr << PROGNAME << ": " << file << "(" << line << "): error " << errcode
		<< ": " << ((char *)lpMsgBuf ? (char *)lpMsgBuf : "<unknown>")
		<< std::flush;
 
    LocalFree(lpMsgBuf);
}

void xformat_error(const char * file, int line, DWORD errcode)
{
	format_error(file, line, errcode);
    ExitProcess(errcode);
}

void dump_buffer(const char * prefix, const char * fname, void * buf, size_t bufsz)
{
	char namebuf[1024];
    FILE * fp;

	sprintf(namebuf, "%s-%s", prefix, fname);
	if (fp = fopen(namebuf, "wb"))
	{
		std::cout << "dumping " << bufsz << " bytes in " << namebuf << std::endl;
		fwrite(buf, bufsz, 1, fp);
		fclose(fp);
	}
	else
	{
		std::cerr << "failed to create " << namebuf << std::endl;
	}
}
bool open_reg_key(const char * server, HKEY root, const char * subkey, HKEY * rkey)
{
	LONG result = ERROR_SUCCESS;

	if (server)
	{
		HKEY tmp;

		result = RegConnectRegistry(server, root, &tmp);

		if (result != ERROR_SUCCESS)
		{
			XFORMAT_ERROR(result);
			return(false);
		}

		root = tmp;
	}

	/* Return the root key if no subkey wanted. */
	*rkey = root;

	if (subkey)
	{
		HKEY skey;

		result = RegOpenKeyEx(root, subkey, 0, KEY_READ, &skey);
		if (server)
			RegCloseKey(*rkey);

		*rkey = skey;
	}

	if (result != ERROR_SUCCESS)
		XFORMAT_ERROR(result);

	return(result == ERROR_SUCCESS);
}

bool query_reg_key(HKEY key, const char * value, void ** buf, DWORD * bufsz)
{
	LONG result;

	*bufsz = 0;

	do 
	{
		*bufsz += 16384;
		*buf = realloc(*buf, *bufsz);

		result = RegQueryValueEx(key, value, NULL, NULL,
                               (LPBYTE)*buf, bufsz);

	} while (result == ERROR_MORE_DATA);

	if (result != ERROR_SUCCESS)
		XFORMAT_ERROR(result);

	return (result == ERROR_SUCCESS);
}

void dump_perflib_names(const char * server, const char * fname)
{
	void *	buf = NULL;
	DWORD	bufsz = 0;
	HKEY 	key;

	std::cout << "fetching metric names" << std::endl;

	open_reg_key(server, HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Perflib\\009", &key);
	query_reg_key(key, "Counters", &buf, &bufsz);

	dump_buffer(server ? server+2 : "local", fname, buf, bufsz);
}

void dump_perflib_help(const char * server, const char * fname)
{
	void *	buf = NULL;
	DWORD	bufsz = 0;
	HKEY 	key;

	std::cout << "fetching metric help" << std::endl;

	open_reg_key(server, HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Perflib\\009", &key);
	query_reg_key(key, "Help", &buf, &bufsz);
	dump_buffer(server ? server+2 : "local", fname, buf, bufsz);
}

void dump_perflib_data(const char * server, const char * fname)
{
	void *	buf = NULL;
	DWORD	bufsz = 0;
	HKEY 	key;

	std::cout << "fetching metric data" << std::endl;

	open_reg_key(server, HKEY_PERFORMANCE_DATA, NULL, &key);
	query_reg_key(key, "Global", &buf, &bufsz);
	dump_buffer(server ? server+2 : "local", fname, buf, bufsz);
}

int main(int argc, char ** argv)
{
	// usage: perfdump [\\server]

	dump_perflib_names(argc > 1 ? argv[1] : NULL, "names.dat");
	dump_perflib_help(argc > 1 ? argv[1] : NULL, "help.dat");
	dump_perflib_data(argc > 1 ? argv[1] : NULL, "data.dat");

	return 0;
}


More information about the samba-technical mailing list