add query totals by group

This commit is contained in:
Ben McClelland
2021-10-04 13:09:09 -07:00
parent 0cca7e27f0
commit 777740e7e1
2 changed files with 111 additions and 7 deletions
+33 -7
View File
@@ -4,6 +4,14 @@
// that can be found in the LICENSE file in the root of the source
// tree.
// This example returns the values of a "group" of totl counts/values
// given a 2 uint64 id group tuple. Or it will return the single value
// for a unique 3 uint64 id triple.
// id1 id2 id3
// |--group--|
// |--specific id---|
package main
import (
@@ -16,8 +24,9 @@ import (
)
func main() {
if len(os.Args) != 5 || os.Args[1] == "-h" {
fmt.Fprintln(os.Stderr, "usage:", os.Args[0], "<scoutfs mount point> <id1> <id2> <id3>")
if (len(os.Args) != 4 && len(os.Args) != 5) || os.Args[1] == "-h" {
fmt.Fprintln(os.Stderr, "usage:", os.Args[0],
"<scoutfs mount point> <id1> <id2> or <scoutfs mount point> <id1> <id2> <id3>")
os.Exit(1)
}
@@ -35,16 +44,33 @@ func main() {
if err != nil {
log.Fatalln("error parsing id2:", err)
}
if len(os.Args) == 4 {
tg := scoutfs.NewTotalsGroup(f, u1, u2, 10)
for {
ttls, err := tg.Next()
if err != nil {
log.Fatalln("error read totals:", err)
}
if ttls == nil {
break
}
for _, t := range ttls {
fmt.Println("id:", t.ID[2], "xattrs match:", t.Count, "total value:", t.Total)
}
}
return
}
u3, err := strconv.ParseUint(os.Args[4], 10, 64)
if err != nil {
log.Fatalln("error parsing id3:", err)
log.Fatalln("error parsing id2:", err)
}
t, err := scoutfs.ReadXattrTotals(f, u1, u2, u3)
if err != nil {
log.Fatalln("error read totals:", err)
log.Fatalln("error reading totals:", err)
}
fmt.Println("xattrs match: ", t.Count)
fmt.Println("total value : ", t.Total)
fmt.Println("Count", t.Count)
fmt.Println("Total", t.Total)
}
+78
View File
@@ -12,6 +12,7 @@ import (
"encoding/binary"
"fmt"
"io"
"math"
"os"
"path/filepath"
"strconv"
@@ -870,6 +871,8 @@ type XattrTotal struct {
Total uint64
// Count is number of xattrs matching ids
Count uint64
// ID is the id for this total
ID [3]uint64
}
// ReadXattrTotals returns the XattrTotal for the given id
@@ -895,3 +898,78 @@ func ReadXattrTotals(f *os.File, id1, id2, id3 uint64) (XattrTotal, error) {
Count: totls[0].Count,
}, nil
}
type TotalsGroup struct {
totls []xattrTotal
pos [3]uint64
id1 uint64
id2 uint64
count int
f *os.File
done bool
}
// NewTotalsGroup creates a query to get the totals values for a defined
// group of totls (group is defined to match first 2 identifiers). Count
// specifies max number returned for each Next() call.
func NewTotalsGroup(f *os.File, id1, id2 uint64, count int) *TotalsGroup {
totls := make([]xattrTotal, count)
return &TotalsGroup{
totls: totls,
f: f,
id1: id1,
id2: id2,
count: count,
pos: [3]uint64{id1, id2, 0},
}
}
// Next returns next set of total values for the group
func (t *TotalsGroup) Next() ([]XattrTotal, error) {
if t.done {
return nil, nil
}
query := readXattrTotals{
Pos_name: t.pos,
Totals_ptr: uint64(uintptr(unsafe.Pointer(&t.totls[0]))),
Totals_bytes: sizeofxattrTotal * uint64(t.count),
}
n, err := scoutfsctl(t.f, IOCREADXATTRTOTALS, unsafe.Pointer(&query))
if err != nil {
return nil, err
}
if n == 0 {
t.done = true
return nil, nil
}
t.pos = t.totls[n-1].Name
if t.pos[2] == math.MaxUint64 {
t.done = true
}
t.pos[2]++
ret := make([]XattrTotal, n)
for i := range ret {
if t.totls[i].Name[0] != t.id1 || t.totls[i].Name[1] != t.id2 {
t.done = true
// id sequence we want is done
return ret[:i], nil
}
ret[i].Count = t.totls[i].Count
ret[i].Total = t.totls[i].Total
ret[i].ID = t.totls[i].Name
}
return ret, nil
}
// Reset resets the totl query to the start of the group id again
func (t *TotalsGroup) Reset() {
t.done = false
t.pos[0] = t.id1
t.pos[1] = t.id2
t.pos[2] = 0
}