From e29eb0041f8ad3984122207c3a4f8203d440ea6c Mon Sep 17 00:00:00 2001 From: Christian Pointner Date: Tue, 19 Sep 2017 21:10:24 +0200 Subject: sequence window partially implemented --- satp/sequence-window.go | 39 +++++++++++++++++-- satp/sequence-window_test.go | 90 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 125 insertions(+), 4 deletions(-) create mode 100644 satp/sequence-window_test.go diff --git a/satp/sequence-window.go b/satp/sequence-window.go index c74ca62..94a7b0b 100644 --- a/satp/sequence-window.go +++ b/satp/sequence-window.go @@ -32,23 +32,43 @@ package satp import ( "errors" + "sync" + "sync/atomic" ) type SequenceWindow struct { - size int + size int + head uint64 + body []uint32 + mutex *sync.RWMutex +} + +func (w *SequenceWindow) Size() int { + return w.size +} + +func (w *SequenceWindow) Top() uint32 { + if w.size > 0 { + w.mutex.RLock() + defer w.mutex.RUnlock() + } + v := atomic.LoadUint64(&w.head) + return uint32(v >> 32) } func (w *SequenceWindow) Check(sequenceNumber uint32) (bool, error) { - if w.size == 0 { + if w.size <= 0 { return false, nil } + // TODO: implement this return false, nil } func (w *SequenceWindow) CheckAndSet(sequenceNumber uint32) (bool, error) { - if w.size == 0 { + if w.size <= 0 { return false, nil } + // TODO: implement this return false, nil } @@ -56,6 +76,17 @@ func NewSequenceWindow(size int) (w *SequenceWindow, err error) { if size < 0 { return nil, errors.New("invalid sequence window size") } - w = &SequenceWindow{size: size} + w = &SequenceWindow{size: size, head: 0} + if w.size > 0 { + bodyLen := (w.size / 32) + if (w.size % 32) != 0 { + bodyLen++ + } + w.body = make([]uint32, bodyLen, bodyLen) + for i := range w.body { + w.body[i] = 0 + } + w.mutex = &sync.RWMutex{} + } return } diff --git a/satp/sequence-window_test.go b/satp/sequence-window_test.go new file mode 100644 index 0000000..4fc244a --- /dev/null +++ b/satp/sequence-window_test.go @@ -0,0 +1,90 @@ +// +// Copyright (c) 2017 anygone contributors (see AUTHORS file) +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// * Neither the name of anygone nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// + +package satp + +import ( + "testing" +) + +func TestSequenceWindowNew(t *testing.T) { + testvectors := []struct { + size int + bodyLen int + valid bool + }{ + {-1, 0, false}, + {0, 0, true}, + {1, 1, true}, + {10, 1, true}, + {32, 1, true}, + {33, 2, true}, + {63, 2, true}, + {64, 2, true}, + {65, 3, true}, + {100, 4, true}, + } + + for _, vector := range testvectors { + w, err := NewSequenceWindow(vector.size) + if vector.valid { + if err != nil { + t.Fatal("unexpected error:", err) + } + if w.Size() != vector.size { + t.Fatalf("sequence-window has wrong size, is: %d, should be %d", w.Size(), vector.size) + } + if w.Top() != 0 { + t.Fatalf("sequence-window(%d) top value not 0: 0x%08X", vector.size, w.Top()) + } + if w.head != 0 { + t.Fatalf("sequence-window(%d) head not 0: 0x%16X", vector.size, w.head) + } + bodyLen := len(w.body) + if bodyLen != vector.bodyLen { + t.Fatalf("sequence-window(%d) body length has invalid length, is: %d, should be %d", vector.size, bodyLen, vector.bodyLen) + } + isEmpty := true + for _, v := range w.body { + if v != 0 { + isEmpty = false + } + } + if !isEmpty { + t.Fatalf("sequence-window(%d) body not empty, is: %v", vector.size, w.body) + } + } else { + if err == nil { + t.Fatalf("creating sequence-window(%d) should give an error", vector.size) + } + } + } + +} -- cgit v1.2.3