/*
 * Copyright (C) 2000-2002 ASANO Masahiro
 */

#include <sys/stat.h>
#include <unistd.h>
#include "crash.h"

PRIVATE addr_t buffer_head();
const commandtable_t command_buffer_head =
	{"buffer_head", buffer_head, "[-f] [address]", "print buffer_head table\n  -f  show detail\n  -c  show clean list\n  -l  show locked list\n  -d  show dirty list"};

addr_t hash_table_addr;
addr_t bh_hash_mask_addr;
addr_t lru_list_addr;

extern addr_t print_buffer_head();

PRIVATE addr_t
buffer_head()
{
	int i, c;
	int full = 0;
	addr_t addr, hash_table, start;
	int bh_hash_mask;
	extern void prhead_buffer_head();
	int lru = -1;

	while ((c = getopt(argcnt, args, "fcld")) != EOF) {
		switch (c) {
		case 'f':
			full = 1;
			break;
		case 'c':	/* clean list */
			if (lru != -1) THROW(usage);
			lru = 0;
			break;
		case 'l':	/* locked list */
			if (lru != -1) THROW(usage);
			lru = 1;
			break;
		case 'd':	/* dirty list */
			if (lru != -1) THROW(usage);
			lru = 2;
			break;
		default:
			THROW(usage);
		}
	}

	if (argcnt > optind) {
		if (lru != -1) {
			THROW(usage);
		}
		if (!full) prhead_buffer_head();
		for (i = optind; i < argcnt; i++) {
			addr = getaddr(args[i]);
			if (full) prhead_buffer_head();
			addr = print_buffer_head(addr, full, -1);
		}
	} else if (lru != -1) {
		GETADDR(lru_list);
		memread(lru_list_addr + sizeof(addr_t) * lru, sizeof(addr), &addr, "lru_list");

		start = addr;
		if (!full) prhead_buffer_head();
		while (addr) {
			if (full) prhead_buffer_head();
			addr = print_buffer_head(addr, full, lru);
			if (addr == start)
				break;
		}
	} else {
		GETADDR(hash_table);
		GETADDR(bh_hash_mask);
		memread(hash_table_addr, sizeof(addr_t), &hash_table, "hash_table");
		if (hash_table == 0) {
			THROW("hash_table is NULL");
		}
		memread(bh_hash_mask_addr, sizeof(bh_hash_mask), &bh_hash_mask, "bh_hash_mask");
		if (bh_hash_mask == 0) {
			THROW("bh_hash_mask == 0");
		}

		mprintf("bh_hash_mask %x\n", bh_hash_mask);
		if (!full) prhead_buffer_head();
		for (i = 0; i <= bh_hash_mask; i++) {
			memread(hash_table + sizeof(addr) * i, sizeof(addr), &addr, "bh_hash_mask");
#ifdef DEBUG
			mprintf("[%x] %lx\n", i, addr);
#endif
			while (addr) {
				if (full) prhead_buffer_head();
				addr = print_buffer_head(addr, full, -1);
			}
		}
	}
	return addr;
}
