Esempio n. 1
0
/*
	Sets up the global variables needed by the whole package. This should be invoked by the
	main tegu function (main/tegu.go).

	CAUTION:  this is not implemented as an init() function as we must pass information from the
			main to here.
*/
func Initialise(cfg_fname *string, ver *string, nwch chan *ipc.Chmsg, rmch chan *ipc.Chmsg, rmluch chan *ipc.Chmsg, osifch chan *ipc.Chmsg, fqch chan *ipc.Chmsg, amch chan *ipc.Chmsg) (err error) {
	err = nil

	def_log_dir := "."
	log_dir := &empty_str

	nw_ch = nwch
	rmgr_ch = rmch
	rmgrlu_ch = rmluch
	osif_ch = osifch
	fq_ch = fqch
	am_ch = amch

	if ver != nil {
		version = *ver
	}

	tegu_sheep = bleater.Mk_bleater(1, os.Stderr) // the main (parent) bleater used by libraries and as master 'volume' control
	tegu_sheep.Set_prefix("tegu")

	pid = os.Getpid() // used to keep reservation names unique across invocations

	tklr = ipc.Mk_tickler(30)                   // shouldn't need more than 30 different tickle spots
	tklr.Add_spot(2, rmgr_ch, REQ_NOOP, nil, 1) // a quick burst tickle to prevent a long block if the first goroutine to schedule a tickle schedules a long wait

	if cfg_fname != nil {
		cfg_data, err = config.Parse2strs(nil, *cfg_fname) // capture config data as strings -- referenced as cfg_data["sect"]["key"]
		if err != nil {
			err = fmt.Errorf("unable to parse config file %s: %s", *cfg_fname, err)
			return
		}

		if p := cfg_data["default"]["shell"]; p != nil {
			shell_cmd = *p
		}
		if p := cfg_data["default"]["verbose"]; p != nil {
			tegu_sheep.Set_level(uint(clike.Atoi(*p)))
		}
		if log_dir = cfg_data["default"]["log_dir"]; log_dir == nil {
			log_dir = &def_log_dir
		}
	} else {
		cfg_data = nil
	}

	tegu_sheep.Add_child(gizmos.Get_sheep()) // since we don't directly initialise the gizmo environment we ask for its sheep
	if *log_dir != "stderr" {                // if overriden in config
		lfn := tegu_sheep.Mk_logfile_nm(log_dir, 86400)
		tegu_sheep.Baa(1, "switching to log file: %s", *lfn)
		tegu_sheep.Append_target(*lfn, false)      // switch bleaters to the log file rather than stderr
		go tegu_sheep.Sheep_herder(log_dir, 86400) // start the function that will roll the log now and again
	}

	return
}
Esempio n. 2
0
func TestIpc(t *testing.T) {
	req := ipc.Mk_chmsg()
	if req == nil {
		fmt.Fprintf(os.Stderr, "unable to create a request\n")
		t.Fail()
		return
	}

	start_ts := time.Now().Unix()
	fmt.Fprintf(os.Stderr, "this test runs for 60 seconds and will generate updates periodically....\n")
	req.Response_ch = nil // use it to keep compiler happy

	data := "data for tickled bit"
	ch := make(chan *ipc.Chmsg, 10) // allow 10 messages to queue on the channel
	// to test non-blocking aspect, set to 1 test should run longer than 60 seconds

	tklr := ipc.Mk_tickler(6) // allow max of 6 ticklers; we test 'full' error at end

	tklr.Add_spot(35, ch, 30, &data, 0) // will automatically start the tickler
	tklr.Add_spot(20, ch, 20, &data, 0)
	tklr.Add_spot(15, ch, 15, &data, 0)
	id, err := tklr.Add_spot(10, ch, 10, &data, 0) // nick the id so we can drop it later
	_, err = tklr.Add_spot(10, ch, 1, &data, 2)    // should drive type 1 only twice; 10s apart

	if err != nil {
		fmt.Fprintf(os.Stderr, "unable to add tickle spot: %s\n", err)
		t.Fail()
		return
	}

	fmt.Fprintf(os.Stderr, "type 10 and type 1 written every 10 seconds; type 1 only written twice\n")
	fmt.Fprintf(os.Stderr, "type 10 will be dropped after 35 seconds\n")
	fmt.Fprintf(os.Stderr, "type 15 will appear every 15 seconds\n")
	fmt.Fprintf(os.Stderr, "type 20 will appear every 20 seconds\n")
	fmt.Fprintf(os.Stderr, "type 30 will appear every 35 seconds\n")

	limited_count := 0
	for count := 0; count < 2; {
		req = <-ch // wait for tickle
		fmt.Fprintf(os.Stderr, "got a tickle: @%ds type=%d count=%d\n", time.Now().Unix()-start_ts, req.Msg_type, count)
		if req.Msg_type == 30 {
			if count == 0 {
				fmt.Fprintf(os.Stderr, "dropping type 10 from list; no more type 10 should appear\n")
				tklr.Drop_spot(id) // drop the 10s tickler after first 30 second one pops
			}
			count++ // count updated only at 30s point
		}

		if req.Msg_type == 1 {
			if limited_count > 1 {
				fmt.Fprintf(os.Stderr, "limited count tickle was driven more than twice [FAIL]\n")
				t.Fail()
			}

			limited_count++
		}

		if req.Msg_type == 10 && count > 0 {
			fmt.Fprintf(os.Stderr, "req 10 driven after it was dropped  [FAIL]\n")
			t.Fail()
		}
	}

	tklr.Stop()

	// when we get here there should only be three active ticklers in the list, so we should be
	// able to add 3 before we get a full error.
	// add more spots until we max out to test the error logic in tickle
	err = nil
	for i := 0; i < 3 && err == nil; i++ {
		_, err = tklr.Add_spot(20, ch, 20, &data, 0)
		if err != nil {
			fmt.Fprintf(os.Stderr, "early failure when adding more: i=%d %s\n", i, err)
			t.Fail()
			return
		}
	}

	// the table should be full (6 active ticklers now) and this should return an error
	_, err = tklr.Add_spot(10, ch, 10, &data, 0)
	if err != nil {
		fmt.Fprintf(os.Stderr, "test to over fill the table resulted in the expected error: %s   [OK]\n", err)
	} else {
		fmt.Fprintf(os.Stderr, "adding a 7th tickle spot didn't cause an error and should have  [FAIL]\n")
		t.Fail()
	}
}