a geicko-2 based round robin ranking system designed to test c++ battleship submissions
battleship.dunkirk.sh
1package sftp
2
3import (
4 "sync"
5)
6
7type allocator struct {
8 sync.Mutex
9 available [][]byte
10 // map key is the request order
11 used map[uint32][][]byte
12}
13
14func newAllocator() *allocator {
15 return &allocator{
16 // micro optimization: initialize available pages with an initial capacity
17 available: make([][]byte, 0, SftpServerWorkerCount*2),
18 used: make(map[uint32][][]byte),
19 }
20}
21
22// GetPage returns a previously allocated and unused []byte or create a new one.
23// The slice have a fixed size = maxMsgLength, this value is suitable for both
24// receiving new packets and reading the files to serve
25func (a *allocator) GetPage(requestOrderID uint32) []byte {
26 a.Lock()
27 defer a.Unlock()
28
29 var result []byte
30
31 // get an available page and remove it from the available ones.
32 if len(a.available) > 0 {
33 truncLength := len(a.available) - 1
34 result = a.available[truncLength]
35
36 a.available[truncLength] = nil // clear out the internal pointer
37 a.available = a.available[:truncLength] // truncate the slice
38 }
39
40 // no preallocated slice found, just allocate a new one
41 if result == nil {
42 result = make([]byte, maxMsgLength)
43 }
44
45 // put result in used pages
46 a.used[requestOrderID] = append(a.used[requestOrderID], result)
47
48 return result
49}
50
51// ReleasePages marks unused all pages in use for the given requestID
52func (a *allocator) ReleasePages(requestOrderID uint32) {
53 a.Lock()
54 defer a.Unlock()
55
56 if used := a.used[requestOrderID]; len(used) > 0 {
57 a.available = append(a.available, used...)
58 }
59 delete(a.used, requestOrderID)
60}
61
62// Free removes all the used and available pages.
63// Call this method when the allocator is not needed anymore
64func (a *allocator) Free() {
65 a.Lock()
66 defer a.Unlock()
67
68 a.available = nil
69 a.used = make(map[uint32][][]byte)
70}
71
72func (a *allocator) countUsedPages() int {
73 a.Lock()
74 defer a.Unlock()
75
76 num := 0
77 for _, p := range a.used {
78 num += len(p)
79 }
80 return num
81}
82
83func (a *allocator) countAvailablePages() int {
84 a.Lock()
85 defer a.Unlock()
86
87 return len(a.available)
88}
89
90func (a *allocator) isRequestOrderIDUsed(requestOrderID uint32) bool {
91 a.Lock()
92 defer a.Unlock()
93
94 _, ok := a.used[requestOrderID]
95 return ok
96}