/**********************************************************************
 
	Copyright (C) 2003 Hirohisa MORI <joshua@nichibun.ac.jp>
 
	This program is free software; you can redistribute it 
	and/or modify it under the terms of the GLOBALBASE 
	Library General Public License (G-LGPL) as published by 

	http://www.globalbase.org/
 
	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.

**********************************************************************/


#define STREAM_LIB

#include	"pri_level.h"
#include	"task.h"
#include	"stream.h"
#include	"lock_level.h"

SEM stream_lock;
extern STREAM * stream_list;

STREAM ** recv_streams;
int recv_streams_len;

STREAM * s_stdin = (STREAM*)&__s_std[0];
STREAM * s_stdout = (STREAM*)&__s_std[1];
STREAM * s_stderr = (STREAM*)&__s_std[2];


S_TABLE * stream_table_list;

void
insert_s_table(S_TABLE * tbl)
{
	lock_task(stream_lock);
	tbl->next = stream_table_list;
	stream_table_list = tbl;
	unlock_task(stream_lock,"insert_s_table");
}


void
thput_task()
{
STREAM * s;
unsigned int t;
float bytes;
int interval,avg;
	for ( ; ; ) {
		t = get_xltime();
		lock_task(stream_lock);
		for ( s = stream_list ; s ; s = s->h.next ) {
			if ( s->h.last_time + s->h.interval > t )
				continue;
			interval = t - s->h.last_time;
			bytes = ((float)s->h.bytes_per_interval)
					/ interval;
			s->h.bytes_per_interval = 0;
			avg = s->h.avg_thput;
			if ( avg < 0 || avg < bytes )
				avg = s->h.avg_thput = bytes;
			else	avg = s->h.avg_thput =
					avg*0.9 + bytes*0.1;
			if ( avg ) {
				interval = 30000/avg + 1;
				if ( interval < 2 )
					interval = 2;
				else if ( interval > 10 )
					interval = 10;
			}
			else	interval = 10;
			s->h.interval = interval;
			s->h.last_time = t;
		}
		unlock_task(stream_lock,"thput_task");
		sleep_sec(2);
	}
}

void
init_stream()
{
void zonbie_tick();
void s_write_tick();

	stream_lock = new_lock(LL_STREAM);
	if ( std_cm == 0 ) {
		er_panic(stderr,"init_longchar is required\n");
	}

	s_stdin = (STREAM*)&__s_std[0];
	s_stdout = (STREAM*)&__s_std[1];
	s_stderr = (STREAM*)&__s_std[2];

	s_stdin->h.cm = std_cm;
	s_stdin->h.cm_work = (*std_cm->open)();
	s_stdout->h.cm = std_cm;
	s_stdout->h.cm_work = (*std_cm->open)();
	s_stderr->h.cm = std_cm;
	s_stderr->h.cm_work = (*std_cm->open)();

	init_machine_stream();

	init_chain_stream();
	init_string_stream();
	init_XLoHTTP_stream();

	create_task(thput_task,0,PRI_FETCH_STRONG);

	new_tick(zonbie_tick,11,0);
	new_tick(s_write_tick,2,0);
}
