/*
   some rdf about self:me

  (really, some of it is about me's host, but I don't have a decent
  way to handle that with rules here.)
  
   export facts about the system and this process, found via
   /proc [ PORTABILITY UNCERTAIN ], via RDF (says/4)


*/


/* These are in pages, which are 4K on my system. */

read_proc_self_statm(Stats) :-
	open('/proc/self/statm', read, Stat),
	read_line_to_codes(Stat, Codes),
	close(Stat),
	atom_codes(A, Codes),
	concat_atom(L, ' ', A),
				% from "man proc"
	numzip(L, [size, resident, share, trs, drs, lrs, dt], Stats)
	.

numzip([], [], []).
numzip([A|As], [T|Ts], [R|Rs]) :-
	atom_number(A, N),
	N1 is N * 4096,          % page size
	R=(T=N1),
	numzip(As, Ts, Rs).

sane_stats :-
	read_proc_self_statm(L),
	member(size=SIZE, L),
	member(resident=RSS, L),
	SIZE > 1023,
	RSS > 1023.

unit_test(sane_stats).

/*
:- update([], [
	       says(_,_,_,me(procfs_rss))
	      ], [(
says(self:me, sw:rss, RSS_MB, me(procfs_rss)) :-
	read_proc_self_statm(X),
	member(resident=RSS_PAGES, X),
	/*  Resident Set Size: number of  pages  the  process
	    has  in  real  memory, minus 3 for administrative
	    purposes. */
	RSS_MB is (3 * 4096 + RSS_PAGES) / 1048576
	)], ignore).

unit_test((
	   expand_goal(says(self:me, sw:rss, Megs, me(_)), G),
	   G,
	   Megs > 0.01
	  )).
*/

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%


/*  This is kind of an experiment....   The longer-term approach would
    be to treat file:/$localhost/proc/loadavg as a datasource with a
    custom format, I think.

    It's kinda goofy to run this on its own thread; it's great for
    efficiency -- we don't really want every traversal of says/4 to
    access /proc, but...

    well, I've seen it get hung up a few time.
    Ah -- seems to be when something gets compiled.  Does that kill
    threads?
    
*/


set_load_average_loop :-
	repeat,
	(
	  open('/proc/loadavg', read, Stream),
	  read_line_to_codes(Stream, Codes),
	  close(Stream),
	  atom_codes(Atom, Codes),
	  concat_atom([Av1|_], ' ', Atom),
	  atom_number(Av1, Load),
	  %format(user_error, 'Load is ~f~n', [Load]),
	  retractall(says(me, loadavg, _, me(load_average_poll))),
	  assert(says(me, loadavg, Load, me(load_average_poll))),
	  sleep(5),
	  fail
	).

load_average_start :-
   format('starting load-average poll...~n', []),
   % we have to set these low enough that allocating them doesn't
   % blow our process wide limits....
   thread_create(set_load_average_loop, _, [ detached(true),
					     alias(poll_load_average),
					     local(100),
					     global(100),
					     trail(100),
					     argument(100),
					     stack(100)]).
/*
% runs in 34 usec on my system; not worth the thread hassle
:- update([], [
	       says(_,_,_,me(procfs_loadavg))
	      ], [(
says(self:me, sw:loadavg, Load, me(procfs_loadavg)) :-
	open('/proc/loadavg', read, Stream),
	read_line_to_codes(Stream, Codes),
	close(Stream),
	atom_codes(Atom, Codes),
	concat_atom([Av1|_], ' ', Atom),
	atom_number(Av1, Load)
)], ignore).


:- update([], [
	       says(_,_,_,me(procfs_hostname))
	      ], [(
says(self:me, sw:hostname, literal(Hostname), me(procfs_hostname)) :-
	open('/proc/sys/kernel/hostname', read, X),
	read_line_to_codes(X, Codes),
	close(X),
	atom_codes(Hostname, Codes)
)], ignore).

*/