hopp: Add SetDeadline methods to Conn and Trans
This commit is contained in:
75
metadapta.go
75
metadapta.go
@@ -1,9 +1,11 @@
|
||||
package hopp
|
||||
|
||||
import "io"
|
||||
import "os"
|
||||
import "fmt"
|
||||
import "net"
|
||||
import "sync"
|
||||
import "time"
|
||||
import "sync/atomic"
|
||||
import "git.tebibyte.media/sashakoshka/go-util/sync"
|
||||
|
||||
@@ -108,6 +110,10 @@ func (this *a) AcceptTrans() (Trans, error) {
|
||||
}
|
||||
}
|
||||
|
||||
func (this *a) SetDeadline(t time.Time) error {
|
||||
return this.underlying.SetDeadline(t)
|
||||
}
|
||||
|
||||
func (this *a) SetSizeLimit(limit int64) {
|
||||
this.sizeLimit = limit
|
||||
}
|
||||
@@ -212,6 +218,10 @@ type transA struct {
|
||||
currentWriter io.Closer
|
||||
writeBuffer []byte
|
||||
closed atomic.Bool
|
||||
closeErr error
|
||||
|
||||
deadline *time.Timer
|
||||
deadlineLock sync.Mutex
|
||||
}
|
||||
|
||||
func (this *transA) Close() error {
|
||||
@@ -221,6 +231,11 @@ func (this *transA) Close() error {
|
||||
return err
|
||||
}
|
||||
|
||||
func (this *transA) closeWithError(err error) error {
|
||||
this.closeErr = err
|
||||
return this.Close()
|
||||
}
|
||||
|
||||
func (this *transA) closeDontUnlist() (err error) {
|
||||
// MUST be goroutine safe
|
||||
this.incoming.Close()
|
||||
@@ -269,9 +284,9 @@ func (this *transA) Receive() (method uint16, data []byte, err error) {
|
||||
}
|
||||
|
||||
func (this *transA) ReceiveReader() (uint16, io.Reader, error) {
|
||||
// if the transaction has been closed, return an io.EOF
|
||||
if this.closed.Load() {
|
||||
return 0, nil, io.EOF
|
||||
// if the transaction has been closed, return an appropriate error.
|
||||
if err := this.errIfClosed(); err != nil {
|
||||
return 0, nil, err
|
||||
}
|
||||
|
||||
// drain previous reader if necessary
|
||||
@@ -289,6 +304,54 @@ func (this *transA) ReceiveReader() (uint16, io.Reader, error) {
|
||||
return method, reader, nil
|
||||
}
|
||||
|
||||
func (this *transA) SetDeadline(t time.Time) error {
|
||||
this.deadlineLock.Lock()
|
||||
defer this.deadlineLock.Unlock()
|
||||
|
||||
if t == (time.Time { }) {
|
||||
if this.deadline != nil {
|
||||
this.deadline.Stop()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
until := time.Until(t)
|
||||
if this.deadline == nil {
|
||||
this.deadline.Reset(until)
|
||||
return nil
|
||||
}
|
||||
this.deadline = time.AfterFunc(until, func () {
|
||||
this.closeWithError(os.ErrDeadlineExceeded)
|
||||
})
|
||||
return nil
|
||||
}
|
||||
|
||||
// TODO
|
||||
// func (this *transA) SetReadDeadline(t time.Time) error {
|
||||
// // TODO
|
||||
// }
|
||||
//
|
||||
// func (this *transA) SetWriteDeadline(t time.Time) error {
|
||||
// // TODO
|
||||
// }
|
||||
|
||||
func (this *transA) errIfClosed() error {
|
||||
if !this.closed.Load() {
|
||||
return nil
|
||||
}
|
||||
return this.bestErr()
|
||||
}
|
||||
|
||||
func (this *transA) bestErr() error {
|
||||
if this.parent.err != nil {
|
||||
return this.parent.err
|
||||
}
|
||||
if this.closeErr != nil {
|
||||
return this.closeErr
|
||||
}
|
||||
return io.EOF
|
||||
}
|
||||
|
||||
type readerA struct {
|
||||
parent *transA
|
||||
leftover []byte
|
||||
@@ -319,11 +382,7 @@ func (this *readerA) pull() (uint16, error) {
|
||||
// close and return error on failure
|
||||
this.eof = true
|
||||
this.parent.Close()
|
||||
if this.parent.parent.err == nil {
|
||||
return 0, fmt.Errorf("could not receive message: %w", io.EOF)
|
||||
} else {
|
||||
return 0, this.parent.parent.err
|
||||
}
|
||||
return 0, fmt.Errorf("could not receive message: %w", this.parent.bestErr())
|
||||
}
|
||||
|
||||
func (this *readerA) Read(buffer []byte) (int, error) {
|
||||
|
||||
Reference in New Issue
Block a user