package sftp

import (
	
)

type allocator struct {
	sync.Mutex
	available [][]byte
	// map key is the request order
	used map[uint32][][]byte
}

func newAllocator() *allocator {
	return &allocator{
		// micro optimization: initialize available pages with an initial capacity
		available: make([][]byte, 0, SftpServerWorkerCount*2),
		used:      make(map[uint32][][]byte),
	}
}

// GetPage returns a previously allocated and unused []byte or create a new one.
// The slice have a fixed size = maxMsgLength, this value is suitable for both
// receiving new packets and reading the files to serve
func ( *allocator) ( uint32) []byte {
	.Lock()
	defer .Unlock()

	var  []byte

	// get an available page and remove it from the available ones.
	if len(.available) > 0 {
		 := len(.available) - 1
		 = .available[]

		.available[] = nil          // clear out the internal pointer
		.available = .available[:] // truncate the slice
	}

	// no preallocated slice found, just allocate a new one
	if  == nil {
		 = make([]byte, maxMsgLength)
	}

	// put result in used pages
	.used[] = append(.used[], )

	return 
}

// ReleasePages marks unused all pages in use for the given requestID
func ( *allocator) ( uint32) {
	.Lock()
	defer .Unlock()

	if  := .used[]; len() > 0 {
		.available = append(.available, ...)
	}
	delete(.used, )
}

// Free removes all the used and available pages.
// Call this method when the allocator is not needed anymore
func ( *allocator) () {
	.Lock()
	defer .Unlock()

	.available = nil
	.used = make(map[uint32][][]byte)
}

func ( *allocator) () int {
	.Lock()
	defer .Unlock()

	 := 0
	for ,  := range .used {
		 += len()
	}
	return 
}

func ( *allocator) () int {
	.Lock()
	defer .Unlock()

	return len(.available)
}

func ( *allocator) ( uint32) bool {
	.Lock()
	defer .Unlock()

	,  := .used[]
	return 
}