Last active
July 25, 2020 18:52
-
-
Save pascaldekloe/a06e29c8f6b0ee66c55483321ec97a95 to your computer and use it in GitHub Desktop.
Concept: I/O units with Go
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package io | |
// ReadUniter provides an extension pattern for transaction metadata. | |
type ReadUniter interface { | |
Reader | |
ReadUnits() Units // best effort: possibly zero | |
} | |
// WriteUniter provides an extension pattern for transaction metadata. | |
type WriteUniter interface { | |
Writer | |
WriteUnits() Units // best effort: possibly zero | |
} | |
// Units provides metadata about the nature of I/O transactions. | |
// Each inidicator is optional, with the zero value for unknown. | |
type Units struct { | |
// BlockSize has the fixed resolution [minimum] in bytes. | |
// Negative values indicate a variable working size. | |
BlockSize int | |
/* | |
crypto: sha1.BlockSize, cipher.StreamReader, cipher.StreamWriter, … | |
net: ethernet Interface.MTU | |
disk sectors: | |
- Linux: /sys/block/sda/queue/hw_sector_size | |
- OpenBSD: disklabel(5) DIOCRLDINFO ioctl, e.g., https://cvsweb.openbsd.org/src/sbin/fdisk/disk.c?rev=1.56&content-type=text/x-cvsweb-markup | |
*/ | |
// DelaySize has a byte threshold for transaction optimization. | |
// Negative values indicate no delay—payload is transmitted on | |
// available. | |
DelaySize int | |
/* | |
bufio: Reader.Size, Writer.Size | |
POSIX: sys/stat.h: stat.st_blksize: preferred I/O block size (a.k.a filesystem segment size) | |
*/ | |
// MaxSize has the byte limit for a single transaction. | |
MaxSize int | |
/* | |
net: Interface.MTU, TCPConn [AddOverhead] | |
Plan9: iounit(2) | |
*/ | |
// OverheadSize has the amount of bytes added to each payload. | |
// Negative values indicate no overhead. See OverheadFlags. | |
// How about variable overhead? TCPConn for example…? | |
OverheadSize int | |
} | |
// Inherit applies the Units from an underlying medium on best effort basis. | |
func (u *Units) Inherit(parent Units) { | |
switch { | |
case u.BlockSize == 0, | |
u.BlockSize < 0 && parent.BlockSize > 0, | |
u.BlockSize > 0 && parent.BlockSize > u.BlockSize && parent.BlockSize%u.BlockSize == 0: | |
u.BlockSize = parent.BlockSize | |
} | |
switch { | |
case u.DelaySize == 0, | |
u.DelaySize < 0 && parent.DelaySize > 0, | |
u.DelaySize > 0 && parent.DelaySize > u.DelaySize: | |
u.DelaySize = parent.DelaySize | |
} | |
if parent.MaxSize > 0 && parent.MaxSize < u.MaxSize { | |
u.MaxSize = parent.MaxSize | |
} | |
} | |
// InheritReader uses ReadUnits (when available) on Inherit. | |
func (u *Units) InheritReader(r Reader) { | |
if ur, ok := r.(ReadUniter); ok { | |
u.Inherit(ur.ReadUnits()) | |
} | |
} | |
// InheritWriter uses WriteUnits (when available) on Inherit. | |
func (u *Units) InheritWriter(w Writer) { | |
if uw, ok := w.(WriteUniter); ok { | |
u.Inherit(uw.WriteUnits()) | |
} | |
} |
Author
pascaldekloe
commented
Jul 25, 2020
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment