#include "ktypes.h"
#include "filesys.h"


static char     what[] = "$Header: readj.c,v 1.5 86/12/04 10:22:59 tom Exp $";


#define NBUF    20

struct buf
{
	struct buf      *b_next;
	struct buf      *b_prev;
	integer32       b_unit;
	cardinal32      b_bno;
	struct jnode    b_jdata[SPB];
};


struct buf      *bhead, bufs[NBUF];


readj(ex, slot, item)
	struct extp             *ex;
	long	                slot;
	struct jnode            *item;
{
	cardinal32              ix;
	static int              init;
	cardinal32              bno;
	register struct buf     *b;
	char	my_disk_buffer[512];

#ifdef DEBUG
dumpextp("readj (ex)",ex);
printf("readj(DEBUG): slot %d\n",slot);
#endif
	if (slot < 0 || slot >= ex->x_slots)
	{
		printf("readj: RANGE ERROR -- unit %d offset %d slot %d\n",
		ex->x_unit, ex->x_offset, slot);

		return -1;
	}

	if (!init)
	{
#ifdef DEBUG
printf("readj(DEBUG): initializing the buffers\n");
#endif /* DEBUG */
	  for (b = &bufs[0]; b < bufs + NBUF; b++)
		{
			b->b_next = b + 1;
			b->b_prev = b - 1;
			b->b_unit = -1;
#ifdef DEBUG
			dumpbuf(b);
#endif /* DEBUG */
		}

	  bhead = &bufs[0];
#ifdef DEBUG
	printf("readj(DEBUG): bhead %X\n",bhead);
#endif /* DEBUG */

	  b = bufs + (NBUF - 1);
#ifdef DEBUG
	printf("readj(DEBUG): b %X\n",b);
#endif

	  bhead->b_prev = b;
	  b->b_next = bhead;

	  init++;
	}

#ifdef
printf("readj(DEBUG): after buffer init, offset %d, slot %d, SPB %d\n",
       ex->x_offset, slot, SPB);
	printf("readj(DEBUG): size of struct buf %d, sizeof bufs %d\n",
	       sizeof(struct buf), sizeof bufs);
#endif /* DEBUG */

	bno = (long) ex->x_offset + (slot / SPB);

	ix = slot % SPB;

#ifdef
printf("readj(DEBUG): calcs done, bno %d, ix %d ... searching\n",
       bno, ix);
#endif

	for (b = bhead;;)
	{
#ifdef DEBUG
printf("readj(DEBUG): b %X, b->b_unit %d\n",b,b->b_unit);
#endif

		if (b->b_unit == -1)
			break;
#ifdef DEBUG
printf("readj(DEBUG): ex %X, ex->x_unit %d\n",ex,ex->x_unit);
#endif
		if (ex->x_unit == b->b_unit
		&& bno == b->b_bno)
		{
			if (b != bhead)
			{
				b->b_prev->b_next = b->b_next;
				b->b_next->b_prev = b->b_prev;

				b->b_next = bhead;
				b->b_prev = bhead->b_prev;

				bhead->b_prev->b_next = b;
				bhead->b_prev = b;

				bhead = b;
			}
#ifdef DEBUG
printf("readj(DEBUG): found in cache:\n\t");
dumpbuf(b);
#endif
			move(&b->b_jdata[ix], item, sizeof *item);
			return 0;
		}

		if ((b = b->b_next) == bhead)
			break;
	}
#ifdef DEBUG
printf("readj(DEBUG): getting from disk\n");
#endif
	if (get_abs_block(ex->x_unit, bno, &my_disk_buffer[0]) < 0)
		return -1;

#ifdef DEBUG
printf("readj(DEBUG): got from disk\n");
#endif

	b = bhead->b_prev;

#ifdef DEBUG
printf("readj(DEBUG): moving to cache area\n");
#endif
	move(&my_disk_buffer[0], b->b_jdata, sizeof b->b_jdata);

	b->b_unit = ex->x_unit;
	b->b_bno = bno;

	bhead = b;

#ifdef DEBUG
dumpbuf(b);
printf("readj(DEBUG): moving to data area\n");
#endif
	move(&b->b_jdata[ix], item, sizeof *item);
#ifdef DEBUG
dumpjnode("readj (filled-in item)",item);
#endif
	return 0;
}

#ifdef DEBUG
dumpbuf(ptr)
     struct buf *ptr;
{
  printf("dumpbuf: b %X, b_next %X, b_prev %X, b_unit %d b_bno %d\n",
	 ptr, ptr->b_next, ptr->b_prev, ptr->b_unit, ptr->b_bno);

}
#endif


