mirror of
https://github.com/featurebasedb/featurebase.git
synced 2026-08-28 10:54:59 +00:00
We switch everything to use QueryContext/QueryRead/etc instead of Qcx/Tx. We drop the short_txkey subpackage (it's now handled by either keys or querycontext). We drop all the dbshard stuff, and all the tx/txfactory stuff. We remove all the things that related to the old "Block" concept, which was mostly used by the anti-entropy code, but had one fragmentary usage left in the ImportRoaringOverwrite case of ImportRoaring. That's replaced by using a rewriter that deletes all bits (not just bits in specific columns) from an existing thing, but writes in new bits. Actually we could probably do that better with a custom "eradicate-rewriter" that doesn't try to be clever, and just eliminates things. This includes a number of minor bug fixes that were exposed by getting the testing to work. For example: * When checking whether an operation "requires write", we now consider a Delete a kind of a Write, because it is. * Several tests were relying on the fact that writes through Qcx were being committed whether or not the Qcx was ever told to finish. With QueryContext, you actually have to reach a Commit() or the writes don't happen (except for special cases in Delete). * Replaced a lot of panics with t.Fatalf in tests. There's also some minor staticcheck fixes, like deleting the unused "db" member of a boltdb transaction wrapper.
103 lines
3 KiB
Go
103 lines
3 KiB
Go
// Copyright 2021 Molecula Corp. All rights reserved.
|
|
package pilosa
|
|
|
|
// util.go: a place for generic, reusable utilities.
|
|
import (
|
|
"fmt"
|
|
"os"
|
|
"os/user"
|
|
"path/filepath"
|
|
"strings"
|
|
"time"
|
|
|
|
"github.com/shirou/gopsutil/v3/mem"
|
|
)
|
|
|
|
// LeftShifted16MaxContainerKey is 0xffffffffffff0000. It is similar
|
|
// to the roaring.maxContainerKey 0x0000ffffffffffff, but
|
|
// shifted 16 bits to the left so its domain is the full [0, 2^64) bit space.
|
|
// It is used to match the semantics of the roaring.OffsetRange() API.
|
|
// This is the maximum endx value for Tx.OffsetRange(), because the lowbits,
|
|
// as in the roaring.OffsetRange(), are not allowed to be set.
|
|
// It is used in Tx.RoaringBitamp() to obtain the full contents of a fragment
|
|
// from a call from tx.OffsetRange() by requesting [0, LeftShifted16MaxContainerKey)
|
|
// with an offset of 0.
|
|
const LeftShifted16MaxContainerKey = uint64(0xffffffffffff0000) // or math.MaxUint64 - (1<<16 - 1), or 18446744073709486080
|
|
|
|
//////////////////////////////////
|
|
// helper utility functions
|
|
|
|
// GetLoopProgress returns the estimated remaining time to iterate through some
|
|
// items as well as the loop completion percentage with the following
|
|
// parameters:
|
|
// the start time, the current time, the iteration, and the number of items
|
|
func GetLoopProgress(start time.Time, now time.Time, iteration uint, total uint) (remaining time.Duration, pctDone float64) {
|
|
itemsLeft := total - (iteration + 1)
|
|
avgItemTime := float64(now.Sub(start)) / float64(iteration+1)
|
|
pctDone = (float64(iteration+1) / float64(total)) * 100
|
|
return time.Duration(avgItemTime * float64(itemsLeft)), pctDone
|
|
}
|
|
|
|
type MemoryUsage struct {
|
|
Capacity uint64 `json:"capacity"`
|
|
TotalUse uint64 `json:"totalUsed"`
|
|
}
|
|
|
|
// GetMemoryUsage gets the memory usage
|
|
func GetMemoryUsage() (MemoryUsage, error) {
|
|
usage, err := mem.VirtualMemory()
|
|
if usage == nil || err != nil {
|
|
return MemoryUsage{}, fmt.Errorf("reading virtual memory: %v", err)
|
|
}
|
|
return MemoryUsage{Capacity: usage.Total, TotalUse: usage.Used}, nil
|
|
}
|
|
|
|
type DiskUsage struct {
|
|
Usage int64 `json:"usage"`
|
|
}
|
|
|
|
// GetDiskUsage gets the disk usage of the path
|
|
func GetDiskUsage(path string) (DiskUsage, error) {
|
|
usr, _ := user.Current()
|
|
dir := usr.HomeDir
|
|
if path == "~" {
|
|
path = dir
|
|
} else if strings.HasPrefix(path, "~/") {
|
|
path = filepath.Join(dir, path[2:])
|
|
}
|
|
|
|
var size int64
|
|
err := filepath.Walk(path, func(_ string, info os.FileInfo, err error) error {
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if !info.IsDir() {
|
|
size += info.Size()
|
|
}
|
|
return err
|
|
})
|
|
return DiskUsage{size}, err
|
|
}
|
|
|
|
// Rev reverses a string
|
|
func Rev(input string) string {
|
|
n := 0
|
|
runes := make([]rune, len(input))
|
|
for _, r := range input {
|
|
runes[n] = r
|
|
n++
|
|
}
|
|
runes = runes[0:n]
|
|
|
|
for i := 0; i < n/2; i++ {
|
|
runes[i], runes[n-1-i] = runes[n-1-i], runes[i]
|
|
}
|
|
|
|
return string(runes)
|
|
}
|
|
|
|
// ReplaceFirstFromBack replaces the first instance of toReplace from the back of
|
|
// the string s
|
|
func ReplaceFirstFromBack(s, toReplace, replacement string) string {
|
|
return Rev(strings.Replace(Rev(s), Rev(toReplace), Rev(replacement), 1))
|
|
}
|