func Overcapacity(i int) string { deck := deque.New(i) for j := 1; j <= i; j++ { deck.Push(j) } for j := 1; j <= i; j++ { deck.Pop() } // now the internal buffer is filled with the numbers 1,...,i raw, _ := deck.Raw(-1) if len(raw) != i { return fmt.Sprintf("len(%v) != %v", raw, i) } if cap(raw) != i { return fmt.Sprintf("cap(%v) != %v", raw, i) } if deck.Overcapacity(uint(i)) != deck { return fmt.Sprintf("Overcapacity(%v) does not return self", i) } deck.CheckInvariant() raw2, _ := deck.Raw(-1) if fmt.Sprintf("%v", raw2) != fmt.Sprintf("%v", raw) { return fmt.Sprintf("Overcapacity(i) with i==Capacity() must leave internal buffer untouched") } data := []interface{}{"bar", 1, 2, 3, 4, 5, 6, 7, 8, 9, "foo"} for _, rotation := range []int{0, 1, 4, 7, len(data) - 1, len(data) - 2} { deck = deque.New(data) deck.Raw(rotation) deck.CheckInvariant() for j := 0; j <= i; j++ { if deck.Overcapacity(uint(j)) != deck { return fmt.Sprintf("Overcapacity(%v) does not return self", j) } res := Deque(deck, data...) if res != "" { return res } if deck.Capacity() != len(data)+j { return fmt.Sprintf("Overcapacity(%v) resulted in %v", j, deck.Capacity()-len(data)) } } for j := i; j >= 0; j-- { deck.Raw(i >> 1) if deck.Overcapacity(uint(j)) != deck { return fmt.Sprintf("Overcapacity(%v) does not return self", j) } res := Deque(deck, data...) if res != "" { return res } if deck.Capacity() != len(data)+j { return fmt.Sprintf("Overcapacity(%v) resulted in %v", j, deck.Capacity()-len(data)) } } } return "" }
func Search(item int, x ...int) int { deck := deque.New(len(x) * 2) for _, xx := range x { deck.Push(xx) } return deck.Search(item, intcmp) }
func Insert(maxcapacity int) string { for capa := 0; capa <= maxcapacity; capa++ { for sz := 0; sz <= capa; sz++ { testdata := []interface{}{} for n := 1; n <= sz; n++ { testdata = append(testdata, n) } for a := 0; a < capa; a++ { for idx := -2; idx <= capa+2; idx++ { testdeque := deque.New(capa, testdata) _, rawidx := testdeque.Raw(a) if rawidx != a { return fmt.Sprintf("Raw(%v) is broken", a) } var res bool if idx >= 0 && idx <= len(testdata) { res = true } x := testdeque.InsertAt(idx, "foo") if x != res { return fmt.Sprintf("After Raw(%v) Deque(%v,%v).InsertAt(%v) == %v but should be %v", a, capa, testdata, idx, x, res) } var testdata2 []interface{} if x { testdata2 = make([]interface{}, len(testdata)+1) copy(testdata2[0:idx], testdata[0:idx]) testdata2[idx] = "foo" copy(testdata2[idx+1:], testdata[idx:]) } else { testdata2 = testdata } ck := Deque(testdeque, testdata2...) if ck != "" { return ck } } } } } return "" }
// Returns all system templates that apply to the given system (which may be // incomplete). // // The format of the reply is: // <systemdb> // <xml> // <dn>...</dn> // <objectclass>objectclass_1</objectclass> // <objectclass>objectclass_2</objectclass> // ... // </xml> // <xml> // <dn>...</dn> // ... // </xml> // ... // </systemdb> // // The order of the template objects is such that the first entry is the // best match (i.e. the template with the most specific matching rules). // See "detected_hardware" documentation in the go-susi operator's manual for // information on how to mark a system object as a template and how to specify // the systems to which it should apply. // // If there is no matching template, the returned hash is <systemdb></systemdb>. // // NOTE: The returned template objects always contain only the attributes from // the objects themselves, not from any groups they may be members of. // // ATTENTION! This function accesses LDAP and may therefore take a while. // If possible you should use it asynchronously. func SystemGetTemplatesFor(system *xml.Hash) *xml.Hash { // ATTENTION: No space between "for" and "*" because there may be some other // kind of whitespace (such as CR) x, err := xml.LdifToHash("xml", true, ldapSearch(fmt.Sprintf("(&(objectClass=GOhard)(gocomment=Template for*/*/*)%v)", config.UnitTagFilter))) if err != nil { util.Log(0, "ERROR! LDAP error while looking for template objects: %v", err) return xml.NewHash("systemdb") } templates := deque.New() // templates.At(0) is the most specific match templates.Push(xml.NewHash("xml", "TEMPLATE_MATCH_SPECIFICITY", "0")) //sentinel for t := x.RemoveFirst("xml"); t != nil; t = x.RemoveFirst("xml") { specificity := templateMatch(system, t.Text("gocomment")) if specificity > 0 { t.Add("TEMPLATE_MATCH_SPECIFICITY", specificity) for i := 0; i < templates.Count(); i++ { tspec, _ := strconv.Atoi(templates.At(i).(*xml.Hash).Text("TEMPLATE_MATCH_SPECIFICITY")) if specificity >= tspec { templates.InsertAt(i, t) break } } } } templates.Pop() // remove sentinel ret := xml.NewHash("systemdb") for !templates.IsEmpty() { t := templates.Next().(*xml.Hash) t.RemoveFirst("TEMPLATE_MATCH_SPECIFICITY") ret.AddWithOwnership(t) } return ret }
// Unit tests for the package github.com/mbenkmann/golib/deque. func Deque_test() { fmt.Printf("\n==== deque ===\n\n") whatever := []uint{0, 1, 2, 3, 4, 5, 21, 127, 200} zero := []uint{0} one := []uint{1} check(Growth(deque.Double, zero, zero, whatever, one), "") check(Growth(deque.Double, zero, one, whatever, one), "") check(Growth(deque.Double, []uint{1, 2, 3, 4, 8, 16, 32, 111}, one, []uint{11}, []uint{1, 2, 3, 4, 8, 16, 32, 111}), "") check(Growth(deque.Double, []uint{1, 2, 3, 4, 8, 16, 32, 111}, []uint{11}, []uint{11}, []uint{15, 14, 21, 12, 24, 16, 32, 111}), "") deque.GrowthFactor = 0 check(Growth(deque.Exponential, whatever, zero, zero, one), "") check(Growth(deque.Exponential, whatever, one, zero, one), "") check(Growth(deque.Exponential, whatever, one, one, []uint{2}), "") check(Growth(deque.Exponential, whatever, one, []uint{2}, []uint{4}), "") deque.GrowthFactor = 7 check(Growth(deque.Exponential, []uint{666}, one, []uint{0, 1, 2, 3, 4}, []uint{7, 14, 28, 56, 112}), "") check(Growth(deque.Exponential, []uint{666}, []uint{30}, []uint{0, 1, 2, 3, 4}, []uint{56, 56, 56, 56, 112}), "") deque.GrowthFactor = 0 var i uint for i = 0; i < 5; i++ { check(Growth(deque.Accelerated, whatever, []uint{i}, whatever, []uint{i}), "") } deque.GrowthFactor = 7 check(Growth(deque.Accelerated, []uint{111}, one, []uint{0, 1, 2, 3, 4}, []uint{7, 14, 21, 28, 35}), "") check(Growth(deque.GrowBy(0), []uint{111}, []uint{0, 1, 2, 3, 4, 5, 6, 7, 8}, []uint{222}, []uint{0, 1, 2, 3, 4, 5, 6, 7, 8}), "") check(Growth(deque.GrowBy(1), []uint{111}, []uint{0, 1, 2, 3, 4, 5, 6, 7, 8}, []uint{222}, []uint{1, 1, 2, 3, 4, 5, 6, 7, 8}), "") check(Growth(deque.GrowBy(2), []uint{111}, []uint{0, 1, 2, 3, 4, 5, 6, 7, 8}, []uint{222}, []uint{2, 2, 2, 3, 4, 5, 6, 7, 8}), "") check(Growth(deque.GrowBy(3), []uint{111}, []uint{0, 1, 2, 3, 4, 5, 6, 7, 8}, []uint{222}, []uint{3, 3, 3, 3, 4, 5, 6, 7, 8}), "") check(Growth(deque.BlockIfFull, whatever, whatever, whatever, zero), "") func() { defer func() { check(recover(), deque.Overflow) }() deque.PanicIfOverflow(1, 2, 3) }() d2 := deque.New(deque.GrowthFunc(deque.Exponential)) d2.CheckInvariant() check(d2.Growth, deque.Exponential) check(deque.New(111).Capacity(), 111) check(deque.New(22, []interface{}{1, "foo", 2, "bar"}, 111).Capacity(), 111) check(deque.New([]interface{}{1, "foo", 2, "bar"}, 2).Capacity(), 4) d1 := deque.New([]interface{}{1, "foo", 2, "bar"}, 2, deque.Accelerated, []interface{}{3, "foobar", 10, "xxx", "yyy"}) check(Deque(d1, 1, "foo", 2, "bar", 3, "foobar", 10, "xxx", "yyy"), "") check(d1.Capacity(), 9) check(d1.Growth, deque.Accelerated) d1.Init([]interface{}{"bla", "argl", "bart"}, d1, []interface{}{}, []interface{}{"mark", "susi", "karl", "peter"}, []interface{}{}, d1) check(Deque(d1, "bla", "argl", "bart", 1, "foo", 2, "bar", 3, "foobar", 10, "xxx", "yyy", "mark", "susi", "karl", "peter", 1, "foo", 2, "bar", 3, "foobar", 10, "xxx", "yyy"), "") check(d1.Capacity(), 25) check(d1.Count(), 25) check(d1.String(), "Deque[bla argl bart 1 foo 2 bar 3 foobar 10 xxx yyy mark susi karl peter 1 foo 2 bar 3 foobar 10 xxx yyy]") check(deque.New().String(), "Deque[]") check(deque.New([]interface{}{"foobar"}).String(), "Deque[foobar]") var stack deque.Deque check(Deque(&stack), "") check(stack.Capacity(), deque.CapacityDefault) stack.Push(1) stack.Push(2) stack.Push(3) stack.Push(4) stack.Push(5) check(Deque(&stack, 1, 2, 3, 4, 5), "") check(stack.Next(), 1) check(Deque(&stack, 2, 3, 4, 5), "") check(stack.Next(), 2) check(Deque(&stack, 3, 4, 5), "") check(stack.Pop(), 5) check(Deque(&stack, 3, 4), "") check(stack.Next(), 3) check(Deque(&stack, 4), "") check(stack.Pop().(int), 4) check(Deque(&stack), "") go func() { time.Sleep(1 * time.Second) stack.Insert("foo") time.Sleep(1 * time.Second) stack.Insert("bar") }() check(stack.Pop().(string), "foo") check(Deque(&stack), "") check(stack.Next(), "bar") check(Deque(&stack), "") check(Remove(11), "") check(Insert(11), "") deck := deque.New([]interface{}{1}) check(Wait(deck, (*deque.Deque).WaitForItem, true, 0), "") check(Wait(deque.New(), (*deque.Deque).WaitForItem, false, 3*time.Second), "") deck.Init() go func() { time.Sleep(1 * time.Second) deck.Push(1) }() check(Wait(deck, (*deque.Deque).WaitForItem, true, 1*time.Second), "") deck.Init() go func() { time.Sleep(1 * time.Second) deck.Init() }() check(Wait(deck, (*deque.Deque).WaitForItem, false, 3*time.Second), "") go func() { time.Sleep(1 * time.Second) deck.Init([]interface{}{1, 2}) }() check(Wait(deck, (*deque.Deque).WaitForItem, true, 1*time.Second), "") deck = deque.New(4, []interface{}{1, 2, 3}, deque.BlockIfFull) check(Wait(deck, (*deque.Deque).WaitForSpace, true, 0), "") deck.Push(4) check(Wait(deck, (*deque.Deque).WaitForSpace, false, 3*time.Second), "") go func() { time.Sleep(1 * time.Second) deck.Pop() }() check(Wait(deck, (*deque.Deque).WaitForSpace, true, 1*time.Second), "") deck.Push(1) go func() { time.Sleep(1 * time.Second) deck.Init(3, []interface{}{1, 2, 3}) }() check(Wait(deck, (*deque.Deque).WaitForSpace, false, 3*time.Second), "") go func() { time.Sleep(1 * time.Second) deck.Init(4, []interface{}{1, 2, 3}) }() check(Wait(deck, (*deque.Deque).WaitForSpace, true, 1*time.Second), "") check(Wait(deck, (*deque.Deque).WaitForEmpty, false, 3*time.Second), "") go func() { time.Sleep(1 * time.Second) deck.Pop() deck.Pop() deck.Pop() }() check(Wait(deck, (*deque.Deque).WaitForEmpty, true, 1*time.Second), "") check(Wait(deck, (*deque.Deque).WaitForEmpty, true, 0), "") deck.Push(1) go func() { time.Sleep(1 * time.Second) deck.Init(4, []interface{}{1, 2, 3}) }() check(Wait(deck, (*deque.Deque).WaitForEmpty, false, 3*time.Second), "") go func() { time.Sleep(1 * time.Second) deck.Init(4) }() check(Wait(deck, (*deque.Deque).WaitForEmpty, true, 1*time.Second), "") for i := 0; i < 33; i++ { check(Overcapacity(i), "") } deck = deque.New(4) deck.Raw(2) check(deck.Overcapacity(0) == deck, true) check(Deque(deck), "") check(deck.Capacity(), 0) deck = deque.New(4) deck.Raw(5) check(deck.Overcapacity(10) == deck, true) check(Deque(deck), "") check(deck.Capacity(), 10) deck.Init(deque.BlockIfFull, []interface{}{1, 2, 3}) go func() { time.Sleep(500 * time.Millisecond) check(Deque(deck, 1, 2, 3), "") check(deck.Capacity(), 3) deck.Overcapacity(1) }() deck.Push(4) check(Deque(deck, 1, 2, 3, 4), "") check(deck.Capacity(), 4) deck = deque.New() check(deck.Push(1), true) check(Deque(deck, 1), "") check(deck.Push(2), true) check(Deque(deck, 1, 2), "") check(deck.PushAt(-2, "x"), false) check(Deque(deck, 1, 2), "") check(deck.PushAt(-1, "x"), false) check(Deque(deck, 1, 2), "") check(deck.PushAt(3, "x"), false) check(Deque(deck, 1, 2), "") check(deck.PushAt(4, "x"), false) check(Deque(deck, 1, 2), "") check(deck.PushAt(0, "foo"), true) check(Deque(deck, 1, 2, "foo"), "") check(deck.PushAt(1, "bar"), true) check(Deque(deck, 1, 2, "bar", "foo"), "") check(deck.PushAt(4, "FOO"), true) check(Deque(deck, "FOO", 1, 2, "bar", "foo"), "") check(deck.PushAt(5, "BAR"), true) check(Deque(deck, "BAR", "FOO", 1, 2, "bar", "foo"), "") check(deck.PushAt(3, 1.5), true) check(Deque(deck, "BAR", "FOO", 1, 1.5, 2, "bar", "foo"), "") check(deck.Pop(), "foo") check(Deque(deck, "BAR", "FOO", 1, 1.5, 2, "bar"), "") check(deck.PopAt(0), "bar") check(Deque(deck, "BAR", "FOO", 1, 1.5, 2), "") check(deck.PopAt(5), nil) check(Deque(deck, "BAR", "FOO", 1, 1.5, 2), "") check(deck.PopAt(4), "BAR") check(Deque(deck, "FOO", 1, 1.5, 2), "") check(deck.PopAt(1), 1.5) check(Deque(deck, "FOO", 1, 2), "") deck = deque.New() go func() { time.Sleep(1 * time.Second); deck.Push("Yeah!") }() for i := -2; i <= 2; i++ { check(deck.PopAt(i), nil) check(Deque(deck), "") } check(deck.PopAt(0), nil) time.Sleep(2 * time.Second) check(deck.PopAt(0), "Yeah!") for i := 0; i < 50; i++ { go func() { p := deck.Pop().(string) if p != "MSB" { check(p, "MSB") } }() } for i = 0; i < 50; i++ { deck.Push("MSB") time.Sleep(100 * time.Millisecond) } deck = deque.New() check(deck.Insert(1), true) check(DequeReversed(deck, 1), "") check(deck.Insert(2), true) check(DequeReversed(deck, 1, 2), "") check(deck.InsertAt(-2, "x"), false) check(DequeReversed(deck, 1, 2), "") check(deck.InsertAt(-1, "x"), false) check(DequeReversed(deck, 1, 2), "") check(deck.InsertAt(3, "x"), false) check(DequeReversed(deck, 1, 2), "") check(deck.InsertAt(4, "x"), false) check(DequeReversed(deck, 1, 2), "") check(deck.InsertAt(0, "foo"), true) check(DequeReversed(deck, 1, 2, "foo"), "") check(deck.InsertAt(1, "bar"), true) check(DequeReversed(deck, 1, 2, "bar", "foo"), "") check(deck.InsertAt(4, "FOO"), true) check(DequeReversed(deck, "FOO", 1, 2, "bar", "foo"), "") check(deck.InsertAt(5, "BAR"), true) check(DequeReversed(deck, "BAR", "FOO", 1, 2, "bar", "foo"), "") check(deck.InsertAt(3, 1.5), true) check(DequeReversed(deck, "BAR", "FOO", 1, 1.5, 2, "bar", "foo"), "") check(deck.Next(), "foo") check(DequeReversed(deck, "BAR", "FOO", 1, 1.5, 2, "bar"), "") check(deck.RemoveAt(0), "bar") check(DequeReversed(deck, "BAR", "FOO", 1, 1.5, 2), "") check(deck.RemoveAt(5), nil) check(DequeReversed(deck, "BAR", "FOO", 1, 1.5, 2), "") check(deck.RemoveAt(4), "BAR") check(DequeReversed(deck, "FOO", 1, 1.5, 2), "") check(deck.RemoveAt(1), 1.5) check(DequeReversed(deck, "FOO", 1, 2), "") deck = deque.New() go func() { time.Sleep(1 * time.Second); deck.Insert("Yeah!") }() for i := -2; i <= 2; i++ { check(deck.RemoveAt(i), nil) check(DequeReversed(deck), "") } check(deck.RemoveAt(0), nil) time.Sleep(2 * time.Second) check(deck.RemoveAt(0), "Yeah!") for i := 0; i < 50; i++ { go func() { p := deck.Next().(string) if p != "MSB" { check(p, "MSB") } }() } for i = 0; i < 50; i++ { deck.Insert("MSB") time.Sleep(100 * time.Millisecond) } deck.Init() check(deck.Remove(nil), 0) check(deck.Remove("foo"), 0) check(deck.Remove(nil, strcmp), 0) check(deck.Remove("foo", strcmp), 0) check(Deque(deck), "") deck.Push("foobar") check(deck.Remove(nil), 0) check(deck.Remove("foo"), 0) check(deck.Remove("foo", strcmp), 0) check(Deque(deck, "foobar"), "") tmp := []byte{0, 'o', 'o', 'b', 'a', 'r'} tmp[0] = 'f' check(deck.Remove(string(tmp), strcmp), 1) check(Deque(deck), "") deck.Push("foobar") check(deck.Remove(string(tmp)), 1) check(Deque(deck), "") deck.Init([]interface{}{"foobar", "foobar"}) check(deck.Remove("foobar"), 2) check(Deque(deck), "") deck.Init([]interface{}{"foobar", "foobar"}) check(deck.Remove("foobar", strcmp), 2) check(Deque(deck), "") deck.Init([]interface{}{"foobar", "a", "b", "foobar", "c", "foobar", "d", "e", "f", "foobar"}) deck.Raw(5) check(deck.Remove("foobart"), 0) check(Deque(deck, "foobar", "a", "b", "foobar", "c", "foobar", "d", "e", "f", "foobar"), "") check(deck.Remove("foobar"), 4) check(Deque(deck, "a", "b", "c", "d", "e", "f"), "") deck.Init([]interface{}{"foobar", "a", "b", "foobar", "c", "foobar", "d", "e", "f", "foobar"}) deck.Raw(5) check(deck.Remove("foobart", strcmp), 0) check(Deque(deck, "foobar", "a", "b", "foobar", "c", "foobar", "d", "e", "f", "foobar"), "") check(deck.Remove("foobar", strcmp), 4) check(Deque(deck, "a", "b", "c", "d", "e", "f"), "") var errormsg interface{} func() { defer func() { errormsg = recover() }() deck.Remove("foobar", strcmp, strcmp) }() check(errormsg, "Remove() takes 1 or 2 parameters") func() { defer func() { errormsg = recover() }() deck.Init(nil) }() check(errormsg, "Argument #1 is unsupported by deque.Init()") func() { defer func() { errormsg = recover() }() deck.Init(stack) // stack is not a pointer. That's why this doesn't work. }() check(errormsg, "Argument #1 is unsupported by deque.Init()") growth := func(uint, uint, uint) uint { return 10 } var uninitialized deque.Deque check(Deque(deque.New(&uninitialized, &uninitialized)), "") d1 = deque.New([]interface{}{1, 2, 3, 4, 5}, 10) d1.Raw(6) d2 = deque.New([]interface{}{6, 7, 8}) d3 := deque.New([]interface{}{}, 4) deck.Init(&uninitialized, d1, d2, d3, []interface{}{"a", "b", "c", "d"}, []interface{}{"e", "f", "g", "h"}, growth) check(Deque(deck, 1, 2, 3, 4, 5, 6, 7, 8, "a", "b", "c", "d", "e", "f", "g", "h"), "") deck.Init([]interface{}{"a", "b", "c", "d"}, []interface{}{"e", "f", "g", "h"}, growth, d1, d2) check(Deque(deck, "a", "b", "c", "d", "e", "f", "g", "h", 1, 2, 3, 4, 5, 6, 7, 8), "") check(deque.New(0).Capacity(), 0) check(deque.New(1).Capacity(), 1) check(deque.New(-100).Capacity(), deque.CapacityDefault) check(deque.New(3, []interface{}{}).Capacity(), 3) check(deque.New(int64(3), []interface{}{1}).Capacity(), 3) check(deque.New(uint(3), []interface{}{1, 2}).Capacity(), 3) check(deque.New(uint64(3), []interface{}{1, 2}).Capacity(), 3) check(deque.New(uint64(3), []interface{}{1, 2, 3}).Capacity(), 3) check(deque.New(3, []interface{}{1, 2, 3, 4}).Capacity(), 4) check(deque.New(3, []interface{}{1, 2}, []interface{}{3, 4}).Capacity(), 4) deck.Init(3, []interface{}{1, 2}, []interface{}{3, 4}) deck.Clear() check(deck.Capacity(), deque.CapacityDefault) check(deck.Count(), 0) deck.Init([]interface{}{0, 1, 2, 3, 4, 5}) deck.Raw(3) // 3,4,5,[b][a]0,1,2 check(deck.RemoveAt(-1), nil) check(deck.RemoveAt(deck.Count()), nil) check(deck.RemoveAt(3), 3) // 2,4,5,[b]_,[a]0,1 check(Deque(deck, 0, 1, 2, 4, 5), "") check(deck.RemoveAt(2), 2) // 1,4,5,[b]_,_,[a]0 check(Deque(deck, 0, 1, 4, 5), "") check(deck.RemoveAt(2), 4) // [a]0,1,5,[b]_,_,_ check(Deque(deck, 0, 1, 5), "") deck.Init([]interface{}{0, 1, 2, 3, 4, 5}) deck.Raw(3) // 3,4,5,[b][a]0,1,2 check(deck.RemoveAt(0), "0") // 3,4,5,[b]_,[a]1,2 check(Deque(deck, 1, 2, 3, 4, 5), "") deck.Init([]interface{}{0, 1, 2, 3, 4, 5}) deck.Raw(3) // 3,4,5,[b][a]0,1,2 check(deck.RemoveAt(4), "4") // 3,5,[b]_,[a]0,1,2 check(Deque(deck, 0, 1, 2, 3, 5), "") deck.Init([]interface{}{0, 1, 2, 3, 4, 5, 6, 7}) deck.Raw(2) // 6,7,[b][a]0,1,2,3,4,5 check(deck.RemoveAt(7), "7") // 6,[b]_,[a]0,1,2,3,4,5 check(Deque(deck, 0, 1, 2, 3, 4, 5, 6), "") check(deck.RemoveAt(4), "4") // [b]_,_,[a]0,1,2,3,5,6 check(Deque(deck, 0, 1, 2, 3, 5, 6), "") check(deck.RemoveAt(5), "6") // _,_,[a]0,1,2,3,5,[b]_ check(Deque(deck, 0, 1, 2, 3, 5), "") deck.Init([]interface{}{0, 1, 2, 3, 4, 5, 6, 7}) deck.Overcapacity(4) // [a]0,1,2,3,4,5,6,7,[b]_,_,_,_ deck.Raw(2) // _,_,[a]0,1,2,3,4,5,6,7,[b]_,_ check(deck.RemoveAt(6), "6") // _,_,[a]0,1,2,3,4,5,7,[b]_,_,_ check(Deque(deck, 0, 1, 2, 3, 4, 5, 7), "") check(deck.RemoveAt(2), "2") // _,_,_,[a]0,1,3,4,5,7,[b]_,_,_ check(Deque(deck, 0, 1, 3, 4, 5, 7), "") deck.Init([]interface{}{}, deque.GrowBy(1)) check(deck.InsertAt(-1, "foo"), false) check(deck.InsertAt(1, "foo"), false) check(deck.InsertAt(0, 11), true) check(Deque(deck, 11), "") deck.Init(deck, deque.BlockIfFull) go func() { time.Sleep(1 * time.Second); deck.Pop() }() check(deck.InsertAt(0, 22), true) check(Deque(deck, 22), "") deck.Init([]interface{}{0, 1, 2}, deque.GrowBy(1)) check(deck.InsertAt(0, -1), true) check(Deque(deck, -1, 0, 1, 2), "") deck.Init([]interface{}{0, 1, 2}, deque.GrowBy(1)) deck.Raw(1) check(deck.InsertAt(0, -1), true) check(Deque(deck, -1, 0, 1, 2), "") deck.Init([]interface{}{0, 1, 2}, deque.GrowBy(1)) deck.Raw(2) check(deck.InsertAt(0, -1), true) check(Deque(deck, -1, 0, 1, 2), "") deck.Init(0, deque.GrowBy(2)) go func() { time.Sleep(500 * time.Millisecond) deck.InsertAt(0, 0) }() check(deck.Capacity(), 0) check(deck.WaitForSpace(2*time.Second), true) check(deck.Capacity(), 2) deck.Init([]interface{}{0, 1, 2, 3, 4, 5, 6, 7}, deque.BlockIfFull) go func() { time.Sleep(500 * time.Millisecond) deck.Init([]interface{}{0, 1}, 3) }() check(deck.Push(2), true) check(Deque(deck, 0, 1, 2), "") deck.Init(0, deque.DropFarEndIfOverflow) check(deck.Push("should be discarded"), false) check(Deque(deck), "") deck.Init([]interface{}{0}, deque.DropFarEndIfOverflow) check(deck.PushAt(0, 1), true) check(Deque(deck, 1), "") check(deck.PushAt(1, 2), true) check(Deque(deck, 2), "") deck.Init([]interface{}{3, 5}, deque.DropFarEndIfOverflow) check(deck.InsertAt(0, 1), true) check(Deque(deck, 1, 3), "") check(deck.InsertAt(1, 2), true) if deck.At(0).(int) == 2 { check(Deque(deck, 2, 3), "") } else { check(Deque(deck, 1, 2), "") } deck.Init([]interface{}{3, 5}, deque.DropFarEndIfOverflow) deck.Raw(1) check(deck.InsertAt(0, 1), true) check(Deque(deck, 1, 3), "") check(deck.InsertAt(1, 2), true) if deck.At(0).(int) == 2 { check(Deque(deck, 2, 3), "") } else { check(Deque(deck, 1, 2), "") } deck.Init([]interface{}{1, 3, 5}, deque.DropFarEndIfOverflow) check(deck.InsertAt(1, 2), true) check(Deque(deck, 1, 2, 3), "") check(deck.InsertAt(2, 2.5), true) check(Deque(deck, 2, 2.5, 3), "") deck.Init(0, deque.DropItemIfOverflow) check(deck.InsertAt(1, 2), false) check(deck.Insert(2), false) check(deck.Push(2), false) check(Deque(deck), "") deck.Init([]interface{}{1, 2, 3}, deque.DropItemIfOverflow) check(deck.InsertAt(1, 2), false) check(deck.Insert(2), false) check(deck.Push(2), false) check(Deque(deck, 1, 2, 3), "") deck.Init(0, deque.GrowBy(1)) check(deck.Push(42), true) check(deck.Push(43), true) check(Deque(deck, 42, 43), "") deck.Init(0, deque.GrowBy(2)) go func() { deck.WaitForSpace(0) deck.Push(2) }() time.Sleep(500 * time.Millisecond) check(deck.Push(1), true) time.Sleep(500 * time.Millisecond) check(deck.Push(3), true) check(Deque(deck, 1, 2, 3), "") check(deck.Capacity(), 4) deck.Init([]interface{}{0, 1}, 3) deck.Raw(2) check(deck.Push(2), true) check(Deque(deck, 0, 1, 2), "") deck.Init(3) go func() { deck.WaitForItem(0) deck.Push(2) }() time.Sleep(500 * time.Millisecond) check(deck.Push(1), true) time.Sleep(500 * time.Millisecond) deck.Push(3) deck.Push(4) deck.Push(5) check(deck.InsertAt(2, 2.5), true) check(Deque(deck, 1, 2, 2.5, 3, 4, 5), "") deck.Init([]interface{}{1, 2, 3, 4, 5}, 7) check(deck.InsertAt(0, -1), true) check(Deque(deck, -1, 1, 2, 3, 4, 5), "") deck.Raw(0) check(deck.InsertAt(4, 3.5), true) check(Deque(deck, -1, 1, 2, 3, 3.5, 4, 5), "") deck.Init([]interface{}{1, 2, 3, 4, 5}, 10) deck.Raw(8) check(deck.InsertAt(2, 2.5), true) check(Deque(deck, 1, 2, 2.5, 3, 4, 5), "") deck.Init([]interface{}{1, 2, 3, 4, 5, 6, 7}, 10) deck.Raw(8) check(deck.InsertAt(3, 3.5), true) check(Deque(deck, 1, 2, 3, 3.5, 4, 5, 6, 7), "") deck.Init([]interface{}{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}, 12) deck.Raw(10) check(deck.InsertAt(4, 4.5), true) check(Deque(deck, 1, 2, 3, 4, 4.5, 5, 6, 7, 8, 9, 10), "") deck.Init([]interface{}{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}, 12) deck.Raw(10) check(deck.InsertAt(5, 5.5), true) check(Deque(deck, 1, 2, 3, 4, 5, 5.5, 6, 7, 8, 9, 10), "") deck.Init([]interface{}{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}, 12) deck.Raw(5) check(deck.InsertAt(6, 6.5), true) check(Deque(deck, 1, 2, 3, 4, 5, 6, 6.5, 7, 8, 9, 10), "") deck.Init([]interface{}{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}, 11) deck.Raw(5) check(deck.InsertAt(5, 5.5), true) check(Deque(deck, 1, 2, 3, 4, 5, 5.5, 6, 7, 8, 9, 10), "") check(Search(2), 0) check(Search(2, 1), 1) check(Search(2, 2), 0) check(Search(2, 3), 0) check(Search(2, 1, 2), 1) check(Search(2, 2, 2), 0) check(Search(2, 1, 1), 2) check(Search(2, 3, 4), 0) check(Search(2, 2, 3, 4), 0) check(Search(2, 1, 1, 2), 2) check(Search(2, 1, 1, 1), 3) check(Search(2, 1, 2, 3), 1) check(Search(2, 3, 4, 5, 6), 0) check(Search(2, 2, 3, 4, 5), 0) check(Search(2, 1, 2, 3, 4), 1) check(Search(2, 1, 3, 4, 5), 1) check(Search(2, 1, 1, 4, 5), 2) check(Search(2, 1, 1, 2, 5), 2) check(Search(2, 1, 1, 1, 5), 3) check(Search(2, 1, 1, 1, 2), 3) check(Search(2, 1, 1, 1, 1), 4) check(Search(2, 2, 2, 2, 2), 0) deck.Init(deque.DropItemIfOverflow, 0) check(deck.InsertSorted(42, intcmp), -1) deck.Init(deque.BlockIfFull, 0) go func() { time.Sleep(500 * time.Millisecond) deck.Init([]interface{}{1, 2, 3, 4, 5, 6}, 10, deque.BlockIfFull) }() check(deck.InsertSorted(3, intcmp), 2) check(Deque(deck, 1, 2, 3, 3, 4, 5, 6), "") check(deck.InsertSorted(5, intcmp), 5) check(Deque(deck, 1, 2, 3, 3, 4, 5, 5, 6), "") }
// Handles the message "gosa_query_jobdb". // xmlmsg: the decrypted and parsed message // Returns: // unencrypted reply func gosa_query_jobdb(xmlmsg *xml.Hash) *xml.Hash { where := xmlmsg.First("where") if where == nil { where = xml.NewHash("where") } filter, err := xml.WhereFilter(where) if err != nil { util.Log(0, "ERROR! gosa_query_jobdb: Error parsing <where>: %v", err) filter = xml.FilterNone } // If necessary, wait for the effects of forwarded modify requests t_forward := db.MostRecentForwardModifyRequestTime.At(0).(time.Time) delay := config.GosaQueryJobdbMaxDelay - time.Since(t_forward) if delay > 0 { util.Log(1, "INFO! Waiting %v before replying to gosa_query_jobdb to allow forwarded job modifications to take effect", delay) time.Sleep(delay) } jobdb_xml := db.JobsQuery(filter) // sort jobs cmp := func(a, b interface{}) int { x := a.(*xml.Hash) y := b.(*xml.Hash) ts := x.Text("timestamp") + "00000000000000" // NOTE: The first component has only the 1st 10 digits of the timestamp. // This quantizes jobs by hour (i.e. ignoring minutes and seconds). // For this reason we have "timestamp" listed a 2nd time as the final component, // in that case including all digits. c1 := ts[0:10] + x.Text("headertag", "status", "plainname", "macaddress", "timestamp") ts = y.Text("timestamp") + "00000000000000" c2 := ts[0:10] + y.Text("headertag", "status", "plainname", "macaddress", "timestamp") if c1 < c2 { return -1 } if c1 > c2 { return +1 } return 0 } answers := deque.New() for child := jobdb_xml.FirstChild(); child != nil; child = child.Next() { answer := child.Remove() answers.InsertSorted(answer, cmp) } // maps IP:PORT to a string representation of that peer's downtime // the empty string represents a peer that is up downtime := map[string]string{config.ServerSourceAddress: ""} // maps IP:PORT to server name servername := map[string]string{} for count := 0; count < answers.Count(); { answer := answers.At(count).(*xml.Hash) count++ { siserver := answer.Text("siserver") // If we encounter this siserver for the first time, // get its downtime (if any) and cache it. if _, found := downtime[siserver]; !found { dur := Peer(siserver).Downtime() if t := dur / time.Second; t == 0 { downtime[siserver] = "" } else { downtime[siserver] = verbalDuration(dur) } } // If the server is down, set status="error" and result=<error message> if downtime[siserver] != "" { // Look up server name if we don't have it cached, yet. if _, have := servername[siserver]; !have { servername[siserver] = siserver host, _, err := net.SplitHostPort(siserver) if err != nil { util.Log(0, "ERROR! SplitHostPort(%v): %v", siserver, err) } else { names, err := net.LookupAddr(host) if err != nil { util.Log(0, "ERROR! LookupAddr: %v", err) } else { if len(names) == 0 { names = []string{siserver} } servername[siserver] = names[0] } } } answer.FirstOrAdd("status").SetText("error") answer.FirstOrAdd("result").SetText("%v has been down for %v.", servername[siserver], downtime[siserver]) } answer.Rename("answer" + strconv.FormatUint(uint64(count), 10)) jobdb_xml.AddWithOwnership(answer) } } jobdb_xml.Add("header", "query_jobdb") jobdb_xml.Add("source", config.ServerSourceAddress) jobdb_xml.Add("target", xmlmsg.Text("source")) jobdb_xml.Add("session_id", "1") jobdb_xml.Rename("xml") return jobdb_xml }
// the listener of the test server var listener net.Listener // port the test client listens on var client_listen_port = "18341" // host:port address of the test client. var client_listen_address string // the listener of the test client var client_listener net.Listener // Elements of type net.Conn for all current active incoming connections // handled by handleConnection() var active_connections = deque.New() // keys[0] is the key of the test server started by listen(). // keys[len(keys)-1] is the key of the test client started by listen() // The other elements are copies of config.ModuleKeys // ATTENTION! You must call init_keys() to initialize this. var keys []string // returns all messages currently in the queue that were received at time t or later. func get(t time.Time) []*queueElement { queue_mutex.Lock() defer queue_mutex.Unlock() result := []*queueElement{} for _, q := range queue { if !q.Time.Before(t) {
// be called after delivery of the foreign_job_updates to the peer. // <SyncIfNotGoSusi> is only permitted if <target> is a specific peer. It will not // be transmitted as part of the foreign_job_updates. // A second effect of <SyncIfNotGoSusi> is that if the <target> is not a go-susi, // instead of sending the foreign_job_updates just to the target, it will be // sent to all known peers. This is done to compensate for the fact that // unlike go-susi gosa-si does not rebroadcast changes to its jobdb when those // changes are the result of foreign_job_updates. // The <SyncIfNotGoSusi> tag is used when forwarding change requests for // jobs belonging to other servers to them via foreign_job_updates. var ForeignJobUpdates = make(chan *xml.Hash, 16384) // Stores exactly 1 time.Time that indicates when the most recent job modification // request was forwarded to a peer. A Deque is used only for its synchronization. // Access is permitted with At() and Put() only. var MostRecentForwardModifyRequestTime = deque.New([]interface{}{time.Now().Add(-1 * time.Hour)}, deque.DropFarEndIfOverflow) // Fields that can be updated via Jobs*Modify*() var updatableFields = []string{"progress", "status", "periodic", "timestamp", "result"} // A packaged request to perform some action on the jobDB. // Most db.Job...() functions attach their core code to a jobDBRequest, // push that into the jobDBRequests channel and then return. type jobDBRequest struct { // The function to execute. It is passed a pointer to its own request. Action func(request *jobDBRequest) // Selects the jobs to act upon. Filter xml.HashFilter // Additional job data to be added in whole or part to the database. Job *xml.Hash // If a reply is necessary, it will be transmitted over this channel.