Skip to content

Commit

Permalink
hit everything with a fmt stick
Browse files Browse the repository at this point in the history
  • Loading branch information
hdonnay committed Sep 3, 2019
1 parent dabb6f9 commit a79f3ad
Show file tree
Hide file tree
Showing 18 changed files with 1,013 additions and 1,012 deletions.
1 change: 1 addition & 0 deletions streamingreadseeker/streamingreadseeker_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ const emptyMD5 = "d41d8cd98f00b204e9800998ecf8427e"

// raw data length must remain divisible by 4
const testDataBase64 = "YYHWqJWrHbj+H9ei+AbLHO79sSrbMElQQ+iwZ0j+0JPrbRJnqaxoWeFXEqg2ONub8YjExM0R1L1pDr9Oj5YdHg=="

var fSize int64
var hSize int64
var qSize int64
Expand Down
170 changes: 85 additions & 85 deletions util/bitmask.go
Original file line number Diff line number Diff line change
@@ -1,118 +1,118 @@
package util

import (
"fmt"
"math"
"strings"
"fmt"
"math"
"strings"
)

// Allows using named bitmask values. Useful for commandline flag options
// that need to be treated as bitmask values. In all functions, names are
// case-insensitive.
type BitMask struct {
fields map[string]uint64
values map[uint64]string
nextVal uint64
fields map[string]uint64
values map[uint64]string
nextVal uint64
}

func (this *BitMask) addName(name string) error {
if this.nextVal == 0 {
this.fields = make(map[string]uint64, 64)
this.values = make(map[uint64]string, 64)
this.nextVal = 1
}
name = strings.ToLower(name)
if name == "all" || name == "none" {
return fmt.Errorf("reserved field name: %s", name)
}
_, ok := this.fields[name]
if ok {
return fmt.Errorf("field already exists: %s", name)
}
if this.nextVal == math.MaxUint64 {
return fmt.Errorf("too many fields")
}
this.fields[name] = this.nextVal
this.values[this.nextVal] = name
if this.nextVal == uint64(0x8000000000000000) {
this.nextVal = math.MaxUint64
} else {
this.nextVal <<= 1
}
return nil
if this.nextVal == 0 {
this.fields = make(map[string]uint64, 64)
this.values = make(map[uint64]string, 64)
this.nextVal = 1
}
name = strings.ToLower(name)
if name == "all" || name == "none" {
return fmt.Errorf("reserved field name: %s", name)
}
_, ok := this.fields[name]
if ok {
return fmt.Errorf("field already exists: %s", name)
}
if this.nextVal == math.MaxUint64 {
return fmt.Errorf("too many fields")
}
this.fields[name] = this.nextVal
this.values[this.nextVal] = name
if this.nextVal == uint64(0x8000000000000000) {
this.nextVal = math.MaxUint64
} else {
this.nextVal <<= 1
}
return nil
}

// Add list of names to the bitmask. Takes a single string with names
// separated by the '|' character.
func (this *BitMask) Add(names string) error {
ss := strings.Split(names, "|")
if len(ss) == 0 {
return fmt.Errorf("invalid bitmask string")
}
for _, sn := range ss {
err := this.addName(sn)
if err != nil {
return err
}
}
return nil
ss := strings.Split(names, "|")
if len(ss) == 0 {
return fmt.Errorf("invalid bitmask string")
}
for _, sn := range ss {
err := this.addName(sn)
if err != nil {
return err
}
}
return nil
}

// Get the bitmask value for a list of names. Takes a single string with names
// separated by the '|' character.
func (this *BitMask) Parse(s string) (uint64, error) {
s = strings.ToLower(s)
if s == "all" {
v := uint64(0)
for vn := range this.values {
v |= vn
}
return v, nil
} else if s == "none" {
return 0, nil
}
ss := strings.Split(s, "|")
if len(ss) == 0 {
return 0, fmt.Errorf("invalid bitmask string")
}
v := uint64(0)
for _, sn := range ss {
vn, ok := this.fields[sn]
if !ok {
return 0, fmt.Errorf("field not found: %s", sn)
}
v |= vn
}
return v, nil
s = strings.ToLower(s)
if s == "all" {
v := uint64(0)
for vn := range this.values {
v |= vn
}
return v, nil
} else if s == "none" {
return 0, nil
}
ss := strings.Split(s, "|")
if len(ss) == 0 {
return 0, fmt.Errorf("invalid bitmask string")
}
v := uint64(0)
for _, sn := range ss {
vn, ok := this.fields[sn]
if !ok {
return 0, fmt.Errorf("field not found: %s", sn)
}
v |= vn
}
return v, nil
}

// Given a bitmask value, check if the value corresponding to the given
// string is set. Takes a single string with names separated by the '|'
// character.
func (this *BitMask) IsSet(v uint64, s string) bool {
check, err := this.Parse(s)
if err == nil && (v & check) != 0 {
return true
}
return false
check, err := this.Parse(s)
if err == nil && (v&check) != 0 {
return true
}
return false
}

// Get the names for a bitmask value.
func (this *BitMask) Format(v uint64) (string, error) {
if v == 0 {
return "none", nil
}
s := make([]string, 0)
vn := uint64(1)
for vn != uint64(0x8000000000000000) {
if (v & vn) != 0 {
sn, ok := this.values[vn]
if !ok {
return "", fmt.Errorf("bitmask not found: %d\n", vn)
}
s = append(s, sn)
}
vn <<= 1
}
return strings.Join(s, "|"), nil
if v == 0 {
return "none", nil
}
s := make([]string, 0)
vn := uint64(1)
for vn != uint64(0x8000000000000000) {
if (v & vn) != 0 {
sn, ok := this.values[vn]
if !ok {
return "", fmt.Errorf("bitmask not found: %d\n", vn)
}
s = append(s, sn)
}
vn <<= 1
}
return strings.Join(s, "|"), nil
}
38 changes: 19 additions & 19 deletions util/cmd.go
Original file line number Diff line number Diff line change
@@ -1,31 +1,31 @@
package util

import (
"errors"
"os/exec"
"time"
"errors"
"os/exec"
"time"
)

// ErrReadTimeout is the error used when a command times out before completing.
var ErrCommandTimeout = errors.New("command timed out")

// Run a command, killing it if it does not finish before the specified timeout
func RunCommandWithTimeout(cmd *exec.Cmd, timeout time.Duration) error {
done := make(chan error, 1)
t := time.After(timeout)
done := make(chan error, 1)
t := time.After(timeout)

err := cmd.Start()
if err != nil {
return err
}
go func() {
done <- cmd.Wait()
}()
select {
case err := <- done:
return err
case <- t:
cmd.Process.Kill()
return ErrCommandTimeout
}
err := cmd.Start()
if err != nil {
return err
}
go func() {
done <- cmd.Wait()
}()
select {
case err := <-done:
return err
case <-t:
cmd.Process.Kill()
return ErrCommandTimeout
}
}
48 changes: 24 additions & 24 deletions util/concurrencypool.go
Original file line number Diff line number Diff line change
@@ -1,53 +1,53 @@
package util

import (
"sync"
"sync"
)

// Pool of concurrency slots. Can be used, for example, to limit asynchronous
// processing of items in a queue. Warning: If you mistakenly do more Release()
// calls than Get() calls, the extra Release() call will block, as well as a
// Close() call.
type ConcurrencyPool struct {
pool chan int
closed bool
mutex sync.Mutex
pool chan int
closed bool
mutex sync.Mutex
}

// Create a new ConcurrencyPool
func NewConcurrencyPool(slots int) *ConcurrencyPool {
slots = MaxInt(1, slots)
cp := new(ConcurrencyPool)
cp.pool = make(chan int, slots)
for i := 0; i < slots; i++ {
cp.pool <- 0
}
return cp
slots = MaxInt(1, slots)
cp := new(ConcurrencyPool)
cp.pool = make(chan int, slots)
for i := 0; i < slots; i++ {
cp.pool <- 0
}
return cp
}

// Get one slot from the ConcurrencyPool
func (this *ConcurrencyPool) Get() {
<- this.pool
<-this.pool
}

// Release one slot back to the ConcurrencyPool
func (this *ConcurrencyPool) Release() {
this.mutex.Lock()
defer this.mutex.Unlock()
// avoid writing to a closed channel, which would panic
if !this.closed {
this.pool <- 0
}
this.mutex.Lock()
defer this.mutex.Unlock()
// avoid writing to a closed channel, which would panic
if !this.closed {
this.pool <- 0
}
}

// Close the ConcurrencyPool.
// After closing, all Get() will unblock and all future Get() and Release()
// will just return without blocking.
func (this *ConcurrencyPool) Close() {
this.mutex.Lock()
defer this.mutex.Unlock()
if !this.closed {
close(this.pool)
this.closed = true
}
this.mutex.Lock()
defer this.mutex.Unlock()
if !this.closed {
close(this.pool)
this.closed = true
}
}
Loading

0 comments on commit a79f3ad

Please sign in to comment.