xref: /plan9/sys/src/cmd/venti/srv/dat.h (revision 1206f3fc1b0aab3e32fa15899d31a9b5bfa82d9f)
1368c31abSDavid du Colombier typedef struct Config		Config;
2368c31abSDavid du Colombier typedef struct AMap		AMap;
3368c31abSDavid du Colombier typedef struct AMapN		AMapN;
4368c31abSDavid du Colombier typedef struct Arena		Arena;
5368c31abSDavid du Colombier typedef struct AState	AState;
6f9e1cf08SDavid du Colombier typedef struct ArenaCIG	ArenaCIG;
7368c31abSDavid du Colombier typedef struct ArenaHead	ArenaHead;
8368c31abSDavid du Colombier typedef struct ArenaPart	ArenaPart;
9368c31abSDavid du Colombier typedef struct ArenaTail	ArenaTail;
10368c31abSDavid du Colombier typedef struct ATailStats	ATailStats;
11368c31abSDavid du Colombier typedef struct CIBlock		CIBlock;
12368c31abSDavid du Colombier typedef struct Clump		Clump;
13368c31abSDavid du Colombier typedef struct ClumpInfo	ClumpInfo;
14368c31abSDavid du Colombier typedef struct Graph Graph;
15368c31abSDavid du Colombier typedef struct IAddr		IAddr;
16368c31abSDavid du Colombier typedef struct IBucket		IBucket;
17368c31abSDavid du Colombier typedef struct IEStream		IEStream;
18368c31abSDavid du Colombier typedef struct IEntry		IEntry;
19368c31abSDavid du Colombier typedef struct IFile		IFile;
20368c31abSDavid du Colombier typedef struct ISect		ISect;
21368c31abSDavid du Colombier typedef struct Index		Index;
22368c31abSDavid du Colombier typedef struct Lump		Lump;
23368c31abSDavid du Colombier typedef struct DBlock		DBlock;
24368c31abSDavid du Colombier typedef struct Part		Part;
25368c31abSDavid du Colombier typedef struct Statbin Statbin;
26368c31abSDavid du Colombier typedef struct Statdesc	Statdesc;
27368c31abSDavid du Colombier typedef struct Stats		Stats;
28368c31abSDavid du Colombier typedef struct ZBlock		ZBlock;
29368c31abSDavid du Colombier typedef struct Round	Round;
30368c31abSDavid du Colombier typedef struct Bloom	Bloom;
31368c31abSDavid du Colombier 
32f9e1cf08SDavid du Colombier #pragma incomplete IEStream
33f9e1cf08SDavid du Colombier 
34368c31abSDavid du Colombier #define	TWID32	((u32int)~(u32int)0)
35368c31abSDavid du Colombier #define	TWID64	((u64int)~(u64int)0)
36368c31abSDavid du Colombier #define	TWID8	((u8int)~(u8int)0)
37368c31abSDavid du Colombier 
38368c31abSDavid du Colombier enum
39368c31abSDavid du Colombier {
40368c31abSDavid du Colombier 	ABlockLog		= 9,		/* log2(512), the quantum for reading arenas */
41368c31abSDavid du Colombier 	ANameSize		= 64,
42368c31abSDavid du Colombier 	MaxDiskBlock		= 64*1024,	/* max. allowed size for a disk block */
43368c31abSDavid du Colombier 	MaxIoSize		= 64*1024,	/* max. allowed size for a disk io operation */
44368c31abSDavid du Colombier 	PartBlank		= 256*1024,	/* untouched section at beginning of partition */
45368c31abSDavid du Colombier 	HeadSize		= 512,		/* size of a header after PartBlank */
46368c31abSDavid du Colombier 	MinArenaSize		= 1*1024*1024,	/* smallest reasonable arena size */
47368c31abSDavid du Colombier 	IndexBase		= 1024*1024,	/* initial address to use in an index */
48368c31abSDavid du Colombier 	MaxIo			= 64*1024,	/* max size of a single read or write operation */
49368c31abSDavid du Colombier 	ICacheBits		= 16,		/* default bits for indexing icache */
5068860d28SDavid du Colombier 	MaxAMap			= 31*1024,	/* max. allowed arenas in an address mapping; must be < 32*1024 */
51*1206f3fcSDavid du Colombier 	Unspecified		= TWID32,
52368c31abSDavid du Colombier 
53368c31abSDavid du Colombier 	/*
54368c31abSDavid du Colombier 	 * return codes from syncarena
55368c31abSDavid du Colombier 	 */
56368c31abSDavid du Colombier 	SyncDataErr	= 1 << 0,		/* problem reading the clump data */
57368c31abSDavid du Colombier 	SyncCIErr	= 1 << 1,		/* found erroneous clump directory entries */
58368c31abSDavid du Colombier 	SyncCIZero	= 1 << 2,		/* found unwritten clump directory entries */
59368c31abSDavid du Colombier 	SyncFixErr	= 1 << 3,		/* error writing fixed data */
60368c31abSDavid du Colombier 	SyncHeader	= 1 << 4,		/* altered header fields */
61368c31abSDavid du Colombier 
62368c31abSDavid du Colombier 	/*
63368c31abSDavid du Colombier 	 * error severity
64368c31abSDavid du Colombier 	 */
65368c31abSDavid du Colombier 	EOk			= 0,		/* error expected in normal operation */
66368c31abSDavid du Colombier 	EStrange,				/* strange error that should be logged */
67368c31abSDavid du Colombier 	ECorrupt,				/* corrupted data found in arenas */
68368c31abSDavid du Colombier 	EICorrupt,				/* corrupted data found in index */
69368c31abSDavid du Colombier 	EAdmin,					/* should be brought to administrators' attention */
70368c31abSDavid du Colombier 	ECrash,					/* really bad internal error */
71368c31abSDavid du Colombier 	EBug,					/* a limitation which should be fixed */
72368c31abSDavid du Colombier 	EInconsist,				/* inconsistencies between index and arena */
73368c31abSDavid du Colombier 	EMax,
74368c31abSDavid du Colombier 
75368c31abSDavid du Colombier 	/*
76368c31abSDavid du Colombier 	 * internal disk formats for the venti archival storage system
77368c31abSDavid du Colombier 	 */
78368c31abSDavid du Colombier 	/*
79368c31abSDavid du Colombier 	 * magic numbers on disk
80368c31abSDavid du Colombier 	 */
81368c31abSDavid du Colombier 	_ClumpMagic		= 0xd15cb10cU,	/* clump header, deprecated */
82368c31abSDavid du Colombier 	ClumpFreeMagic		= 0,		/* free clump; terminates active clump log */
83368c31abSDavid du Colombier 
84368c31abSDavid du Colombier 	ArenaPartMagic		= 0xa9e4a5e7U,	/* arena partition header */
85368c31abSDavid du Colombier 	ArenaMagic		= 0xf2a14eadU,	/* arena trailer */
86368c31abSDavid du Colombier 	ArenaHeadMagic		= 0xd15c4eadU,	/* arena header */
87368c31abSDavid du Colombier 
88368c31abSDavid du Colombier 	BloomMagic		= 0xb1004eadU,	/* bloom filter header */
89368c31abSDavid du Colombier 	BloomMaxHash	= 32,
90368c31abSDavid du Colombier 
91368c31abSDavid du Colombier 	ISectMagic		= 0xd15c5ec7U,	/* index header */
92368c31abSDavid du Colombier 
93368c31abSDavid du Colombier 	ArenaPartVersion	= 3,
94368c31abSDavid du Colombier 	ArenaVersion4		= 4,
95368c31abSDavid du Colombier 	ArenaVersion5		= 5,
96368c31abSDavid du Colombier 	BloomVersion		= 1,
97368c31abSDavid du Colombier 	IndexVersion		= 1,
98368c31abSDavid du Colombier 	ISectVersion1		= 1,
99368c31abSDavid du Colombier 	ISectVersion2		= 2,
100368c31abSDavid du Colombier 
101368c31abSDavid du Colombier 	/*
102368c31abSDavid du Colombier 	 * encodings of clumps on disk
103368c31abSDavid du Colombier 	 */
104368c31abSDavid du Colombier 	ClumpEErr		= 0,		/* can't happen */
105368c31abSDavid du Colombier 	ClumpENone,				/* plain */
106368c31abSDavid du Colombier 	ClumpECompress,				/* compressed */
107368c31abSDavid du Colombier 	ClumpEMax,
108368c31abSDavid du Colombier 
109368c31abSDavid du Colombier 	/*
110368c31abSDavid du Colombier 	 * sizes in bytes on disk
111368c31abSDavid du Colombier 	 */
112368c31abSDavid du Colombier 	U8Size			= 1,
113368c31abSDavid du Colombier 	U16Size			= 2,
114368c31abSDavid du Colombier 	U32Size			= 4,
115368c31abSDavid du Colombier 	U64Size			= 8,
116368c31abSDavid du Colombier 
117368c31abSDavid du Colombier 	ArenaPartSize		= 4 * U32Size,
118368c31abSDavid du Colombier 	ArenaSize4		= 2 * U64Size + 6 * U32Size + ANameSize + U8Size,
119368c31abSDavid du Colombier 	ArenaSize5			= ArenaSize4 + U32Size,
120368c31abSDavid du Colombier 	ArenaSize5a		= ArenaSize5 + 2 * U8Size + 2 * U32Size + 2 * U64Size,
121368c31abSDavid du Colombier 	ArenaHeadSize4		= U64Size + 3 * U32Size + ANameSize,
122368c31abSDavid du Colombier 	ArenaHeadSize5		= ArenaHeadSize4 + U32Size,
123368c31abSDavid du Colombier 	BloomHeadSize	= 4 * U32Size,
124368c31abSDavid du Colombier 	ISectSize1		= 7 * U32Size + 2 * ANameSize,
125368c31abSDavid du Colombier 	ISectSize2		= ISectSize1 + U32Size,
126368c31abSDavid du Colombier 	ClumpInfoSize		= U8Size + 2 * U16Size + VtScoreSize,
127368c31abSDavid du Colombier 	ClumpSize		= ClumpInfoSize + U8Size + 3 * U32Size,
128368c31abSDavid du Colombier 	MaxBloomSize		= 1<<(32-3),	/* 2^32 bits */
129368c31abSDavid du Colombier 	MaxBloomHash	= 32,		/* bits per score */
130368c31abSDavid du Colombier 	/*
131368c31abSDavid du Colombier 	 * BUG - The various block copies that manipulate entry buckets
132368c31abSDavid du Colombier 	 * would be faster if we bumped IBucketSize up to 8 and IEntrySize up to 40,
133368c31abSDavid du Colombier 	 * so that everything is word-aligned.  Buildindex is actually cpu-bound
134368c31abSDavid du Colombier 	 * by the (byte at a time) copying in qsort.
135368c31abSDavid du Colombier 	 */
136368c31abSDavid du Colombier 	IBucketSize		= U32Size + U16Size,
137368c31abSDavid du Colombier 	IEntrySize		= U64Size + U32Size + 2*U16Size + 2*U8Size + VtScoreSize,
138368c31abSDavid du Colombier 	IEntryTypeOff		= VtScoreSize + U32Size + U16Size + U64Size + U16Size,
139368c31abSDavid du Colombier 	IEntryAddrOff		= VtScoreSize + U32Size + U16Size,
140368c31abSDavid du Colombier 
141368c31abSDavid du Colombier 	MaxClumpBlocks		=  (VtMaxLumpSize + ClumpSize + (1 << ABlockLog) - 1) >> ABlockLog,
142368c31abSDavid du Colombier 
143368c31abSDavid du Colombier 	IcacheFrac		= 1000000,	/* denominator */
144368c31abSDavid du Colombier 
145368c31abSDavid du Colombier 	SleepForever		= 1000000000,	/* magic value for sleep time */
146368c31abSDavid du Colombier 	/*
147368c31abSDavid du Colombier 	 * dirty flags - order controls disk write order
148368c31abSDavid du Colombier 	 */
149368c31abSDavid du Colombier 	DirtyArena		= 1,
150368c31abSDavid du Colombier 	DirtyArenaCib,
151368c31abSDavid du Colombier 	DirtyArenaTrailer,
152368c31abSDavid du Colombier 	DirtyMax,
153368c31abSDavid du Colombier 
154f9e1cf08SDavid du Colombier 	ArenaCIGSize = 10*1024,	// about 0.5 MB worth of IEntry.
155f9e1cf08SDavid du Colombier 
156368c31abSDavid du Colombier 	VentiZZZZZZZZ
157368c31abSDavid du Colombier };
158368c31abSDavid du Colombier 
159368c31abSDavid du Colombier extern char TraceDisk[];
160368c31abSDavid du Colombier extern char TraceLump[];
161368c31abSDavid du Colombier extern char TraceBlock[];
162368c31abSDavid du Colombier extern char TraceProc[];
163368c31abSDavid du Colombier extern char TraceWork[];
164368c31abSDavid du Colombier extern char TraceQuiet[];
165368c31abSDavid du Colombier extern char TraceRpc[];
166368c31abSDavid du Colombier 
167368c31abSDavid du Colombier /*
168368c31abSDavid du Colombier  * results of parsing and initializing a config file
169368c31abSDavid du Colombier  */
170368c31abSDavid du Colombier struct Config
171368c31abSDavid du Colombier {
172368c31abSDavid du Colombier 	char		*index;			/* name of the index to initialize */
173368c31abSDavid du Colombier 	int		naparts;		/* arena partitions initialized */
174368c31abSDavid du Colombier 	ArenaPart	**aparts;
175368c31abSDavid du Colombier 	int		nsects;			/* index sections initialized */
176368c31abSDavid du Colombier 	ISect		**sects;
177368c31abSDavid du Colombier 	Bloom	*bloom;		/* bloom filter */
178368c31abSDavid du Colombier 	u32int	bcmem;
179368c31abSDavid du Colombier 	u32int	mem;
180368c31abSDavid du Colombier 	u32int	icmem;
181368c31abSDavid du Colombier 	int		queuewrites;
182368c31abSDavid du Colombier 	char*	haddr;
183368c31abSDavid du Colombier 	char*	vaddr;
184368c31abSDavid du Colombier 	char*	webroot;
185368c31abSDavid du Colombier };
186368c31abSDavid du Colombier 
187368c31abSDavid du Colombier /*
188368c31abSDavid du Colombier  * a Part is the low level interface to files or disks.
189368c31abSDavid du Colombier  * there are two main types of partitions
190368c31abSDavid du Colombier  *	arena paritions, which some number of arenas, each in a sub-partition.
191368c31abSDavid du Colombier  *	index partition, which only have one subpartition.
192368c31abSDavid du Colombier  */
193368c31abSDavid du Colombier struct Part
194368c31abSDavid du Colombier {
195368c31abSDavid du Colombier 	int		fd;			/* rock for accessing the disk */
196368c31abSDavid du Colombier 	int		mode;
197368c31abSDavid du Colombier 	u64int		offset;
198368c31abSDavid du Colombier 	u64int		size;			/* size of the partiton */
199368c31abSDavid du Colombier 	u32int		blocksize;		/* block size for reads and writes */
200368c31abSDavid du Colombier 	u32int		fsblocksize;	/* minimum file system block size */
201368c31abSDavid du Colombier 	char		*name;
202368c31abSDavid du Colombier 	char		*filename;
203368c31abSDavid du Colombier 	Channel		*writechan;		/* chan[dcache.nblock](DBlock*) */
204368c31abSDavid du Colombier };
205368c31abSDavid du Colombier 
206368c31abSDavid du Colombier /*
207368c31abSDavid du Colombier  * a cached block from the partition
208368c31abSDavid du Colombier  * yuck -- most of this is internal structure for the cache
209368c31abSDavid du Colombier  * all other routines should only use data
210368c31abSDavid du Colombier  */
211368c31abSDavid du Colombier struct DBlock
212368c31abSDavid du Colombier {
213368c31abSDavid du Colombier 	u8int	*data;
214368c31abSDavid du Colombier 
215368c31abSDavid du Colombier 	Part	*part;			/* partition in which cached */
216368c31abSDavid du Colombier 	u64int	addr;			/* base address on the partition */
217368c31abSDavid du Colombier 	u32int	size;			/* amount of data available, not amount allocated; should go away */
218368c31abSDavid du Colombier 	u32int	mode;
219368c31abSDavid du Colombier 	u32int	dirty;
220368c31abSDavid du Colombier 	u32int	dirtying;
221368c31abSDavid du Colombier 	DBlock	*next;			/* doubly linked hash chains */
222368c31abSDavid du Colombier 	DBlock	*prev;
223368c31abSDavid du Colombier 	u32int	heap;			/* index in heap table */
224368c31abSDavid du Colombier 	u32int	used;			/* last reference times */
225368c31abSDavid du Colombier 	u32int	used2;
226368c31abSDavid du Colombier 	u32int	ref;			/* reference count */
227368c31abSDavid du Colombier 	RWLock	lock;			/* for access to data only */
228368c31abSDavid du Colombier 	Channel	*writedonechan;
229368c31abSDavid du Colombier 	void*	chanbuf[1];		/* buffer for the chan! */
230368c31abSDavid du Colombier };
231368c31abSDavid du Colombier 
232368c31abSDavid du Colombier /*
233368c31abSDavid du Colombier  * a cached block from the partition
234368c31abSDavid du Colombier  * yuck -- most of this is internal structure for the cache
235368c31abSDavid du Colombier  * all other routines should only use data
236368c31abSDavid du Colombier  * double yuck -- this is mostly the same as a DBlock
237368c31abSDavid du Colombier  */
238368c31abSDavid du Colombier struct Lump
239368c31abSDavid du Colombier {
240368c31abSDavid du Colombier 	Packet	*data;
241368c31abSDavid du Colombier 
242368c31abSDavid du Colombier 	Part	*part;			/* partition in which cached */
243368c31abSDavid du Colombier 	u8int	score[VtScoreSize];	/* score of packet */
244368c31abSDavid du Colombier 	u8int	type;			/* type of packet */
245368c31abSDavid du Colombier 	u32int	size;			/* amount of data allocated to hold packet */
246368c31abSDavid du Colombier 	Lump	*next;			/* doubly linked hash chains */
247368c31abSDavid du Colombier 	Lump	*prev;
248368c31abSDavid du Colombier 	u32int	heap;			/* index in heap table */
249368c31abSDavid du Colombier 	u32int	used;			/* last reference times */
250368c31abSDavid du Colombier 	u32int	used2;
251368c31abSDavid du Colombier 	u32int	ref;			/* reference count */
252368c31abSDavid du Colombier 	QLock	lock;			/* for access to data only */
253368c31abSDavid du Colombier };
254368c31abSDavid du Colombier 
255368c31abSDavid du Colombier /*
256368c31abSDavid du Colombier  * mapping between names and address ranges
257368c31abSDavid du Colombier  */
258368c31abSDavid du Colombier struct AMap
259368c31abSDavid du Colombier {
260368c31abSDavid du Colombier 	u64int		start;
261368c31abSDavid du Colombier 	u64int		stop;
262368c31abSDavid du Colombier 	char		name[ANameSize];
263368c31abSDavid du Colombier };
264368c31abSDavid du Colombier 
265368c31abSDavid du Colombier /*
266368c31abSDavid du Colombier  * an AMap along with a length
267368c31abSDavid du Colombier  */
268368c31abSDavid du Colombier struct AMapN
269368c31abSDavid du Colombier {
270368c31abSDavid du Colombier 	int		n;
271368c31abSDavid du Colombier 	AMap		*map;
272368c31abSDavid du Colombier };
273368c31abSDavid du Colombier 
274368c31abSDavid du Colombier /*
275368c31abSDavid du Colombier  * an ArenaPart is a partition made up of Arenas
276368c31abSDavid du Colombier  * it exists because most os's don't support many partitions,
277368c31abSDavid du Colombier  * and we want to have many different Arenas
278368c31abSDavid du Colombier  */
279368c31abSDavid du Colombier struct ArenaPart
280368c31abSDavid du Colombier {
281368c31abSDavid du Colombier 	Part		*part;
282368c31abSDavid du Colombier 	u64int		size;			/* size of underlying partition, rounded down to blocks */
283368c31abSDavid du Colombier 	Arena		**arenas;
284368c31abSDavid du Colombier 	u32int		tabbase;		/* base address of arena table on disk */
285368c31abSDavid du Colombier 	u32int		tabsize;		/* max. bytes in arena table */
286368c31abSDavid du Colombier 
287368c31abSDavid du Colombier 	/*
288368c31abSDavid du Colombier 	 * fields stored on disk
289368c31abSDavid du Colombier 	 */
290368c31abSDavid du Colombier 	u32int		version;
291368c31abSDavid du Colombier 	u32int		blocksize;		/* "optimal" block size for reads and writes */
292368c31abSDavid du Colombier 	u32int		arenabase;		/* base address of first arena */
293368c31abSDavid du Colombier 
294368c31abSDavid du Colombier 	/*
295368c31abSDavid du Colombier 	 * stored in the arena mapping table on disk
296368c31abSDavid du Colombier 	 */
297368c31abSDavid du Colombier 	AMap		*map;
298368c31abSDavid du Colombier 	int		narenas;
299368c31abSDavid du Colombier };
300368c31abSDavid du Colombier 
301368c31abSDavid du Colombier /*
302368c31abSDavid du Colombier  * info about one block in the clump info cache
303368c31abSDavid du Colombier  */
304368c31abSDavid du Colombier struct CIBlock
305368c31abSDavid du Colombier {
306368c31abSDavid du Colombier 	u32int		block;			/* blocks in the directory */
307368c31abSDavid du Colombier 	int		offset;			/* offsets of one clump in the data */
308368c31abSDavid du Colombier 	DBlock		*data;
309368c31abSDavid du Colombier };
310368c31abSDavid du Colombier 
311368c31abSDavid du Colombier /*
312368c31abSDavid du Colombier  * Statistics kept in the tail.
313368c31abSDavid du Colombier  */
314368c31abSDavid du Colombier struct ATailStats
315368c31abSDavid du Colombier {
316368c31abSDavid du Colombier 	u32int		clumps;		/* number of clumps */
317368c31abSDavid du Colombier 	u32int		cclumps;		/* number of compressed clumps */
318368c31abSDavid du Colombier 	u64int		used;
319368c31abSDavid du Colombier 	u64int		uncsize;
320368c31abSDavid du Colombier 	u8int		sealed;
321368c31abSDavid du Colombier };
322368c31abSDavid du Colombier 
323368c31abSDavid du Colombier /*
324368c31abSDavid du Colombier  * Arena state - represents a point in the data log
325368c31abSDavid du Colombier  */
326368c31abSDavid du Colombier struct AState
327368c31abSDavid du Colombier {
328368c31abSDavid du Colombier 	Arena		*arena;
329368c31abSDavid du Colombier 	u64int		aa;			/* index address */
330368c31abSDavid du Colombier 	ATailStats		stats;
331368c31abSDavid du Colombier };
332368c31abSDavid du Colombier 
333368c31abSDavid du Colombier /*
334368c31abSDavid du Colombier  * an Arena is a log of Clumps, preceeded by an ArenaHeader,
335368c31abSDavid du Colombier  * and followed by a Arena, each in one disk block.
336368c31abSDavid du Colombier  * struct on disk is not always up to date, but should be self-consistent.
337368c31abSDavid du Colombier  * to sync after reboot, follow clumps starting at used until ClumpFreeMagic if found.
338368c31abSDavid du Colombier  * <struct name="Arena" type="Arena *">
339368c31abSDavid du Colombier  *	<field name="name" val="s->name" type="AName"/>
340368c31abSDavid du Colombier  *	<field name="version" val="s->version" type="U32int"/>
341368c31abSDavid du Colombier  *	<field name="partition" val="s->part->name" type="AName"/>
342368c31abSDavid du Colombier  *	<field name="blocksize" val="s->blocksize" type="U32int"/>
343368c31abSDavid du Colombier  *	<field name="start" val="s->base" type="U64int"/>
344368c31abSDavid du Colombier  *	<field name="stop" val="s->base+2*s->blocksize" type="U64int"/>
345368c31abSDavid du Colombier  *	<field name="created" val="s->ctime" type="U32int"/>
346368c31abSDavid du Colombier  *	<field name="modified" val="s->wtime" type="U32int"/>
347368c31abSDavid du Colombier  *	<field name="sealed" val="s->sealed" type="Sealed"/>
348368c31abSDavid du Colombier  *	<field name="score" val="s->score" type="Score"/>
349368c31abSDavid du Colombier  *	<field name="clumps" val="s->clumps" type="U32int"/>
350368c31abSDavid du Colombier  *	<field name="compressedclumps" val="s->cclumps" type="U32int"/>
351368c31abSDavid du Colombier  *	<field name="data" val="s->uncsize" type="U64int"/>
352368c31abSDavid du Colombier  *	<field name="compresseddata" val="s->used - s->clumps * ClumpSize" type="U64int"/>
353368c31abSDavid du Colombier  *	<field name="storage" val="s->used + s->clumps * ClumpInfoSize" type="U64int"/>
354368c31abSDavid du Colombier  * </struct>
355368c31abSDavid du Colombier  */
356368c31abSDavid du Colombier struct Arena
357368c31abSDavid du Colombier {
358368c31abSDavid du Colombier 	QLock		lock;			/* lock for arena fields, writing to disk */
359368c31abSDavid du Colombier 	Part		*part;			/* partition in which arena lives */
360368c31abSDavid du Colombier 	int		blocksize;		/* size of block to read or write */
361368c31abSDavid du Colombier 	u64int		base;			/* base address on disk */
362368c31abSDavid du Colombier 	u64int		size;			/* total space in the arena */
363368c31abSDavid du Colombier 	u8int		score[VtScoreSize];	/* score of the entire sealed & summed arena */
364368c31abSDavid du Colombier 
365368c31abSDavid du Colombier 	int		clumpmax;		/* ClumpInfos per block */
366368c31abSDavid du Colombier 	AState		mem;
367368c31abSDavid du Colombier 	int		inqueue;
368368c31abSDavid du Colombier 
369368c31abSDavid du Colombier 	/*
370368c31abSDavid du Colombier 	 * fields stored on disk
371368c31abSDavid du Colombier 	 */
372368c31abSDavid du Colombier 	u32int		version;
373368c31abSDavid du Colombier 	char		name[ANameSize];	/* text label */
374368c31abSDavid du Colombier 	ATailStats		memstats;
375368c31abSDavid du Colombier 	ATailStats		diskstats;
376368c31abSDavid du Colombier 	u32int		ctime;			/* first time a block was written */
377368c31abSDavid du Colombier 	u32int		wtime;			/* last time a block was written */
378368c31abSDavid du Colombier 	u32int		clumpmagic;
379f9e1cf08SDavid du Colombier 
380f9e1cf08SDavid du Colombier 	ArenaCIG	*cig;
381f9e1cf08SDavid du Colombier 	int	ncig;
382f9e1cf08SDavid du Colombier };
383f9e1cf08SDavid du Colombier 
384f9e1cf08SDavid du Colombier struct ArenaCIG
385f9e1cf08SDavid du Colombier {
386f9e1cf08SDavid du Colombier 	u64int	offset;  // from arena base
387368c31abSDavid du Colombier };
388368c31abSDavid du Colombier 
389368c31abSDavid du Colombier /*
390368c31abSDavid du Colombier  * redundant storage of some fields at the beginning of each arena
391368c31abSDavid du Colombier  */
392368c31abSDavid du Colombier struct ArenaHead
393368c31abSDavid du Colombier {
394368c31abSDavid du Colombier 	u32int		version;
395368c31abSDavid du Colombier 	char		name[ANameSize];
396368c31abSDavid du Colombier 	u32int		blocksize;
397368c31abSDavid du Colombier 	u64int		size;
398368c31abSDavid du Colombier 	u32int		clumpmagic;
399368c31abSDavid du Colombier };
400368c31abSDavid du Colombier 
401368c31abSDavid du Colombier /*
402368c31abSDavid du Colombier  * most interesting meta information for a clump.
403368c31abSDavid du Colombier  * stored in each clump's header and in the Arena's directory,
404368c31abSDavid du Colombier  * stored in reverse order just prior to the arena trailer
405368c31abSDavid du Colombier  */
406368c31abSDavid du Colombier struct ClumpInfo
407368c31abSDavid du Colombier {
408368c31abSDavid du Colombier 	u8int		type;
409368c31abSDavid du Colombier 	u16int		size;			/* size of disk data, not including header */
410368c31abSDavid du Colombier 	u16int		uncsize;		/* size of uncompressed data */
411368c31abSDavid du Colombier 	u8int		score[VtScoreSize];	/* score of the uncompressed data only */
412368c31abSDavid du Colombier };
413368c31abSDavid du Colombier 
414368c31abSDavid du Colombier /*
415368c31abSDavid du Colombier  * header for an immutable clump of data
416368c31abSDavid du Colombier  */
417368c31abSDavid du Colombier struct Clump
418368c31abSDavid du Colombier {
419368c31abSDavid du Colombier 	ClumpInfo	info;
420368c31abSDavid du Colombier 	u8int		encoding;
421368c31abSDavid du Colombier 	u32int		creator;		/* initial client which wrote the block */
422368c31abSDavid du Colombier 	u32int		time;			/* creation at gmt seconds since 1/1/1970 */
423368c31abSDavid du Colombier };
424368c31abSDavid du Colombier 
425368c31abSDavid du Colombier /*
426368c31abSDavid du Colombier  * index of all clumps according to their score
427368c31abSDavid du Colombier  * this is just a wrapper to tie together the index sections
428368c31abSDavid du Colombier  * <struct name="Index" type="Index *">
429368c31abSDavid du Colombier  *	<field name="name" val="s->name" type="AName"/>
430368c31abSDavid du Colombier  *	<field name="version" val="s->version" type="U32int"/>
431368c31abSDavid du Colombier  *	<field name="blocksize" val="s->blocksize" type="U32int"/>
432368c31abSDavid du Colombier  *	<field name="tabsize" val="s->tabsize" type="U32int"/>
433368c31abSDavid du Colombier  *	<field name="buckets" val="s->buckets" type="U32int"/>
434368c31abSDavid du Colombier  *	<field name="buckdiv" val="s->div" type="U32int"/>
435368c31abSDavid du Colombier  *	<field name="bitblocks" val="s->div" type="U32int"/>
436368c31abSDavid du Colombier  *	<field name="maxdepth" val="s->div" type="U32int"/>
437368c31abSDavid du Colombier  *	<field name="bitkeylog" val="s->div" type="U32int"/>
438368c31abSDavid du Colombier  *	<field name="bitkeymask" val="s->div" type="U32int"/>
439368c31abSDavid du Colombier  *	<array name="sect" val="&s->smap[i]" elems="s->nsects" type="Amap"/>
440368c31abSDavid du Colombier  *	<array name="amap" val="&s->amap[i]" elems="s->narenas" type="Amap"/>
441368c31abSDavid du Colombier  *	<array name="arena" val="s->arenas[i]" elems="s->narenas" type="Arena"/>
442368c31abSDavid du Colombier  * </struct>
443368c31abSDavid du Colombier  * <struct name="Amap" type="AMap *">
444368c31abSDavid du Colombier  *	<field name="name" val="s->name" type="AName"/>
445368c31abSDavid du Colombier  *	<field name="start" val="s->start" type="U64int"/>
446368c31abSDavid du Colombier  *	<field name="stop" val="s->stop" type="U64int"/>
447368c31abSDavid du Colombier  * </struct>
448368c31abSDavid du Colombier  */
449368c31abSDavid du Colombier struct Index
450368c31abSDavid du Colombier {
451368c31abSDavid du Colombier 	u32int		div;			/* divisor for mapping score to bucket */
452368c31abSDavid du Colombier 	u32int		buckets;		/* last bucket used in disk hash table */
453368c31abSDavid du Colombier 	u32int		blocksize;
454368c31abSDavid du Colombier 	u32int		tabsize;		/* max. bytes in index config */
455368c31abSDavid du Colombier 
456368c31abSDavid du Colombier 	int		mapalloc;		/* first arena to check when adding a lump */
457368c31abSDavid du Colombier 	Arena		**arenas;		/* arenas in the mapping */
458368c31abSDavid du Colombier 	ISect		**sects;		/* sections which hold the buckets */
459368c31abSDavid du Colombier 	Bloom		*bloom;	/* bloom filter */
460368c31abSDavid du Colombier 
461368c31abSDavid du Colombier 	/*
462368c31abSDavid du Colombier 	 * fields stored in config file
463368c31abSDavid du Colombier 	 */
464368c31abSDavid du Colombier 	u32int		version;
465368c31abSDavid du Colombier 	char		name[ANameSize];	/* text label */
466368c31abSDavid du Colombier 	int		nsects;
467368c31abSDavid du Colombier 	AMap		*smap;			/* mapping of buckets to index sections */
468368c31abSDavid du Colombier 	int		narenas;
469368c31abSDavid du Colombier 	AMap		*amap;			/* mapping from index addesses to arenas */
470f9e1cf08SDavid du Colombier 
471f9e1cf08SDavid du Colombier 	QLock	writing;
472368c31abSDavid du Colombier };
473368c31abSDavid du Colombier 
474368c31abSDavid du Colombier /*
475368c31abSDavid du Colombier  * one part of the bucket storage for an index.
476368c31abSDavid du Colombier  * the index blocks are sequentially allocated
477368c31abSDavid du Colombier  * across all of the sections.
478368c31abSDavid du Colombier  */
479368c31abSDavid du Colombier struct ISect
480368c31abSDavid du Colombier {
481368c31abSDavid du Colombier 	Part		*part;
482368c31abSDavid du Colombier 	int		blocklog;		/* log2(blocksize) */
483368c31abSDavid du Colombier 	int		buckmax;		/* max. entries in a index bucket */
484368c31abSDavid du Colombier 	u32int		tabbase;		/* base address of index config table on disk */
485368c31abSDavid du Colombier 	u32int		tabsize;		/* max. bytes in index config */
486368c31abSDavid du Colombier 	Channel	*writechan;
487368c31abSDavid du Colombier 	Channel	*writedonechan;
488368c31abSDavid du Colombier 	void		*ig;		/* used by buildindex only */
489368c31abSDavid du Colombier 	int		ng;
490368c31abSDavid du Colombier 
491368c31abSDavid du Colombier 	/*
492368c31abSDavid du Colombier 	 * fields stored on disk
493368c31abSDavid du Colombier 	 */
494368c31abSDavid du Colombier 	u32int		version;
495368c31abSDavid du Colombier 	u32int		bucketmagic;
496368c31abSDavid du Colombier 	char		name[ANameSize];	/* text label */
497368c31abSDavid du Colombier 	char		index[ANameSize];	/* index owning the section */
498368c31abSDavid du Colombier 	u32int		blocksize;		/* size of hash buckets in index */
499368c31abSDavid du Colombier 	u32int		blockbase;		/* address of start of on disk index table */
500368c31abSDavid du Colombier 	u32int		blocks;			/* total blocks on disk; some may be unused */
501368c31abSDavid du Colombier 	u32int		start;			/* first bucket in this section */
502368c31abSDavid du Colombier 	u32int		stop;			/* limit of buckets in this section */
503368c31abSDavid du Colombier };
504368c31abSDavid du Colombier 
505368c31abSDavid du Colombier /*
506368c31abSDavid du Colombier  * externally interesting part of an IEntry
507368c31abSDavid du Colombier  */
508368c31abSDavid du Colombier struct IAddr
509368c31abSDavid du Colombier {
510368c31abSDavid du Colombier 	u64int		addr;
511368c31abSDavid du Colombier 	u16int		size;			/* uncompressed size */
512368c31abSDavid du Colombier 	u8int		type;			/* type of block */
513368c31abSDavid du Colombier 	u8int		blocks;			/* arena io quanta for Clump + data */
514368c31abSDavid du Colombier };
515368c31abSDavid du Colombier 
516368c31abSDavid du Colombier /*
517368c31abSDavid du Colombier  * entries in the index
518368c31abSDavid du Colombier  * kept in IBuckets in the disk index table,
519368c31abSDavid du Colombier  * cached in the memory ICache.
520368c31abSDavid du Colombier  */
521368c31abSDavid du Colombier struct IEntry
522368c31abSDavid du Colombier {
523f9e1cf08SDavid du Colombier 	/* on disk data - 32 bytes*/
524368c31abSDavid du Colombier 	u8int	score[VtScoreSize];
525368c31abSDavid du Colombier 	IAddr	ia;
526f9e1cf08SDavid du Colombier 
527f9e1cf08SDavid du Colombier 	IEntry	*nexthash;
528f9e1cf08SDavid du Colombier 	IEntry	*nextdirty;
529f9e1cf08SDavid du Colombier 	IEntry	*next;
530f9e1cf08SDavid du Colombier 	IEntry	*prev;
531f9e1cf08SDavid du Colombier 	u8int	state;
532f9e1cf08SDavid du Colombier };
533f9e1cf08SDavid du Colombier enum {
534f9e1cf08SDavid du Colombier 	IEClean = 0,
535f9e1cf08SDavid du Colombier 	IEDirty = 1,
536f9e1cf08SDavid du Colombier 	IESummary = 2,
537368c31abSDavid du Colombier };
538368c31abSDavid du Colombier 
539368c31abSDavid du Colombier /*
540368c31abSDavid du Colombier  * buckets in the on disk index table
541368c31abSDavid du Colombier  */
542368c31abSDavid du Colombier struct IBucket
543368c31abSDavid du Colombier {
544368c31abSDavid du Colombier 	u16int		n;			/* number of active indices */
545368c31abSDavid du Colombier 	u32int		buck;		/* used by buildindex/checkindex only */
546368c31abSDavid du Colombier 	u8int		*data;
547368c31abSDavid du Colombier };
548368c31abSDavid du Colombier 
549368c31abSDavid du Colombier /*
550368c31abSDavid du Colombier  * temporary buffers used by individual threads
551368c31abSDavid du Colombier  */
552368c31abSDavid du Colombier struct ZBlock
553368c31abSDavid du Colombier {
554368c31abSDavid du Colombier 	u32int		len;
555368c31abSDavid du Colombier 	u32int		_size;
556368c31abSDavid du Colombier 	u8int		*data;
557368c31abSDavid du Colombier 	u8int		*free;
558368c31abSDavid du Colombier };
559368c31abSDavid du Colombier 
560368c31abSDavid du Colombier /*
561368c31abSDavid du Colombier  * simple input buffer for a '\0' terminated text file
562368c31abSDavid du Colombier  */
563368c31abSDavid du Colombier struct IFile
564368c31abSDavid du Colombier {
565368c31abSDavid du Colombier 	char		*name;				/* name of the file */
566368c31abSDavid du Colombier 	ZBlock		*b;				/* entire contents of file */
567368c31abSDavid du Colombier 	u32int		pos;				/* current position in the file */
568368c31abSDavid du Colombier };
569368c31abSDavid du Colombier 
570368c31abSDavid du Colombier struct Statdesc
571368c31abSDavid du Colombier {
572368c31abSDavid du Colombier 	char *name;
573368c31abSDavid du Colombier 	ulong max;
574368c31abSDavid du Colombier };
575368c31abSDavid du Colombier 
576368c31abSDavid du Colombier /* keep in sync with stats.c:/statdesc and httpd.c:/graphname*/
577368c31abSDavid du Colombier enum
578368c31abSDavid du Colombier {
579368c31abSDavid du Colombier 	StatRpcTotal,
580368c31abSDavid du Colombier 	StatRpcRead,
581368c31abSDavid du Colombier 	StatRpcReadOk,
582368c31abSDavid du Colombier 	StatRpcReadFail,
583368c31abSDavid du Colombier 	StatRpcReadBytes,
584368c31abSDavid du Colombier 	StatRpcReadTime,
585368c31abSDavid du Colombier 	StatRpcReadCached,
586368c31abSDavid du Colombier 	StatRpcReadCachedTime,
587368c31abSDavid du Colombier 	StatRpcReadUncached,
588368c31abSDavid du Colombier 	StatRpcReadUncachedTime,
589368c31abSDavid du Colombier 	StatRpcWrite,
590368c31abSDavid du Colombier 	StatRpcWriteNew,
591368c31abSDavid du Colombier 	StatRpcWriteOld,
592368c31abSDavid du Colombier 	StatRpcWriteFail,
593368c31abSDavid du Colombier 	StatRpcWriteBytes,
594368c31abSDavid du Colombier 	StatRpcWriteTime,
595368c31abSDavid du Colombier 	StatRpcWriteNewTime,
596368c31abSDavid du Colombier 	StatRpcWriteOldTime,
597368c31abSDavid du Colombier 
598368c31abSDavid du Colombier 	StatLcacheHit,
599368c31abSDavid du Colombier 	StatLcacheMiss,
600368c31abSDavid du Colombier 	StatLcacheRead,
601368c31abSDavid du Colombier 	StatLcacheWrite,
602368c31abSDavid du Colombier 	StatLcacheSize,
603368c31abSDavid du Colombier 	StatLcacheStall,
604368c31abSDavid du Colombier 	StatLcacheReadTime,
605368c31abSDavid du Colombier 
606368c31abSDavid du Colombier 	StatDcacheHit,
607368c31abSDavid du Colombier 	StatDcacheMiss,
608368c31abSDavid du Colombier 	StatDcacheLookup,
609368c31abSDavid du Colombier 	StatDcacheRead,
610368c31abSDavid du Colombier 	StatDcacheWrite,
611368c31abSDavid du Colombier 	StatDcacheDirty,
612368c31abSDavid du Colombier 	StatDcacheSize,
613368c31abSDavid du Colombier 	StatDcacheFlush,
614368c31abSDavid du Colombier 	StatDcacheStall,
615368c31abSDavid du Colombier 	StatDcacheLookupTime,
616368c31abSDavid du Colombier 
617368c31abSDavid du Colombier 	StatDblockStall,
618368c31abSDavid du Colombier 	StatLumpStall,
619368c31abSDavid du Colombier 
620368c31abSDavid du Colombier 	StatIcacheHit,
621368c31abSDavid du Colombier 	StatIcacheMiss,
622368c31abSDavid du Colombier 	StatIcacheRead,
623368c31abSDavid du Colombier 	StatIcacheWrite,
624368c31abSDavid du Colombier 	StatIcacheFill,
625368c31abSDavid du Colombier 	StatIcachePrefetch,
626368c31abSDavid du Colombier 	StatIcacheDirty,
627368c31abSDavid du Colombier 	StatIcacheSize,
628368c31abSDavid du Colombier 	StatIcacheFlush,
629368c31abSDavid du Colombier 	StatIcacheStall,
630368c31abSDavid du Colombier 	StatIcacheReadTime,
631f9e1cf08SDavid du Colombier 	StatIcacheLookup,
632f9e1cf08SDavid du Colombier 	StatScacheHit,
633f9e1cf08SDavid du Colombier 	StatScachePrefetch,
634368c31abSDavid du Colombier 
635368c31abSDavid du Colombier 	StatBloomHit,
636368c31abSDavid du Colombier 	StatBloomMiss,
637368c31abSDavid du Colombier 	StatBloomFalseMiss,
638368c31abSDavid du Colombier 	StatBloomLookup,
639368c31abSDavid du Colombier 	StatBloomOnes,
640368c31abSDavid du Colombier 	StatBloomBits,
641368c31abSDavid du Colombier 
642368c31abSDavid du Colombier 	StatApartRead,
643368c31abSDavid du Colombier 	StatApartReadBytes,
644368c31abSDavid du Colombier 	StatApartWrite,
645368c31abSDavid du Colombier 	StatApartWriteBytes,
646368c31abSDavid du Colombier 
647368c31abSDavid du Colombier 	StatIsectRead,
648368c31abSDavid du Colombier 	StatIsectReadBytes,
649368c31abSDavid du Colombier 	StatIsectWrite,
650368c31abSDavid du Colombier 	StatIsectWriteBytes,
651368c31abSDavid du Colombier 
652368c31abSDavid du Colombier 	StatSumRead,
653368c31abSDavid du Colombier 	StatSumReadBytes,
654368c31abSDavid du Colombier 
655f9e1cf08SDavid du Colombier 	StatCigLoad,
656f9e1cf08SDavid du Colombier 	StatCigLoadTime,
657f9e1cf08SDavid du Colombier 
658368c31abSDavid du Colombier 	NStat
659368c31abSDavid du Colombier };
660368c31abSDavid du Colombier 
661368c31abSDavid du Colombier extern Statdesc statdesc[NStat];
662368c31abSDavid du Colombier 
663368c31abSDavid du Colombier /*
664368c31abSDavid du Colombier  * statistics about the operation of the server
665368c31abSDavid du Colombier  * mainly for performance monitoring and profiling.
666368c31abSDavid du Colombier  */
667368c31abSDavid du Colombier struct Stats
668368c31abSDavid du Colombier {
669368c31abSDavid du Colombier 	ulong		now;
670368c31abSDavid du Colombier 	ulong		n[NStat];
671368c31abSDavid du Colombier };
672368c31abSDavid du Colombier 
673368c31abSDavid du Colombier struct Statbin
674368c31abSDavid du Colombier {
675368c31abSDavid du Colombier 	uint nsamp;
676368c31abSDavid du Colombier 	uint min;
677368c31abSDavid du Colombier 	uint max;
678368c31abSDavid du Colombier 	uint avg;
679368c31abSDavid du Colombier };
680368c31abSDavid du Colombier 
681368c31abSDavid du Colombier struct Graph
682368c31abSDavid du Colombier {
683368c31abSDavid du Colombier 	long (*fn)(Stats*, Stats*, void*);
684368c31abSDavid du Colombier 	void *arg;
685368c31abSDavid du Colombier 	long t0;
686368c31abSDavid du Colombier 	long t1;
687368c31abSDavid du Colombier 	long min;
688368c31abSDavid du Colombier 	long max;
689368c31abSDavid du Colombier 	long wid;
690368c31abSDavid du Colombier 	long ht;
691368c31abSDavid du Colombier 	int fill;
692368c31abSDavid du Colombier };
693368c31abSDavid du Colombier 
694368c31abSDavid du Colombier /*
695368c31abSDavid du Colombier  * for kicking background processes that run one round after another after another
696368c31abSDavid du Colombier  */
697368c31abSDavid du Colombier struct Round
698368c31abSDavid du Colombier {
699368c31abSDavid du Colombier 	QLock	lock;
700368c31abSDavid du Colombier 	Rendez	start;
701368c31abSDavid du Colombier 	Rendez	finish;
702368c31abSDavid du Colombier 	Rendez	delaywait;
703368c31abSDavid du Colombier 	int		delaytime;
704368c31abSDavid du Colombier 	int		delaykick;
705368c31abSDavid du Colombier 	char*	name;
706368c31abSDavid du Colombier 	int		last;
707368c31abSDavid du Colombier 	int		current;
708368c31abSDavid du Colombier 	int		next;
709368c31abSDavid du Colombier 	int		doanother;
710368c31abSDavid du Colombier };
711368c31abSDavid du Colombier 
712368c31abSDavid du Colombier /*
713368c31abSDavid du Colombier  * Bloom filter of stored block hashes
714368c31abSDavid du Colombier  */
715368c31abSDavid du Colombier struct Bloom
716368c31abSDavid du Colombier {
717368c31abSDavid du Colombier 	RWLock lk;		/* protects nhash, nbits, tab, mb */
718368c31abSDavid du Colombier 	QLock mod;		/* one marker at a time, protects nb */
719368c31abSDavid du Colombier 	int nhash;
720368c31abSDavid du Colombier 	ulong size;		/* bytes in tab */
721368c31abSDavid du Colombier 	ulong bitmask;		/* to produce bit index */
722368c31abSDavid du Colombier 	u8int *data;
723368c31abSDavid du Colombier 	Part *part;
724368c31abSDavid du Colombier 	Channel *writechan;
725368c31abSDavid du Colombier 	Channel *writedonechan;
726368c31abSDavid du Colombier };
727368c31abSDavid du Colombier 
728368c31abSDavid du Colombier extern	Index		*mainindex;
729368c31abSDavid du Colombier extern	u32int		maxblocksize;		/* max. block size used by any partition */
730368c31abSDavid du Colombier extern	int		paranoid;		/* should verify hashes on disk read */
731368c31abSDavid du Colombier extern	int		queuewrites;		/* put all lump writes on a queue and finish later */
732368c31abSDavid du Colombier extern	int		readonly;		/* only allowed to read the disk data */
733368c31abSDavid du Colombier extern	Stats		stats;
734368c31abSDavid du Colombier extern	u8int		zeroscore[VtScoreSize];
735368c31abSDavid du Colombier extern	int		compressblocks;
736368c31abSDavid du Colombier extern	int		writestodevnull;	/* dangerous - for performance debugging */
737368c31abSDavid du Colombier extern	int		collectstats;
738368c31abSDavid du Colombier extern	QLock	memdrawlock;
739368c31abSDavid du Colombier extern	int		icachesleeptime;
740368c31abSDavid du Colombier extern	int		minicachesleeptime;
741368c31abSDavid du Colombier extern	int		arenasumsleeptime;
742368c31abSDavid du Colombier extern	int		manualscheduling;
743368c31abSDavid du Colombier extern	int		l0quantum;
744368c31abSDavid du Colombier extern	int		l1quantum;
745368c31abSDavid du Colombier extern	int		ignorebloom;
746368c31abSDavid du Colombier extern	int		icacheprefetch;
747368c31abSDavid du Colombier extern	int		syncwrites;
748b8a11165SDavid du Colombier extern	int		debugarena; /* print in arena error msgs; -1==unknown */
749368c31abSDavid du Colombier 
750368c31abSDavid du Colombier extern	Stats	*stathist;
751368c31abSDavid du Colombier extern	int	nstathist;
752368c31abSDavid du Colombier extern	ulong	stattime;
753368c31abSDavid du Colombier 
754368c31abSDavid du Colombier #ifndef PLAN9PORT
755368c31abSDavid du Colombier #pragma varargck type "V" uchar*
756368c31abSDavid du Colombier #define ODIRECT 0
757368c31abSDavid du Colombier #endif
758f9e1cf08SDavid du Colombier 
759