mirror of
https://github.com/hanzoai/metrics.git
synced 2026-10-30 20:03:39 +00:00
134 lines
3.5 KiB
Go
134 lines
3.5 KiB
Go
package filestream
|
|
|
|
import (
|
|
"io"
|
|
"sync"
|
|
|
|
"github.com/VictoriaMetrics/VictoriaMetrics/lib/fs/fsutil"
|
|
"github.com/VictoriaMetrics/VictoriaMetrics/lib/logger"
|
|
)
|
|
|
|
// ParallelFileCreator is used for parallel creating of files for the given dstPath.
|
|
//
|
|
// ParallelFileCreator is needed for speeding up creating many files on high-latency
|
|
// storage systems such as NFS or Ceph.
|
|
type ParallelFileCreator struct {
|
|
tasks []parallelFileCreatorTask
|
|
}
|
|
|
|
type parallelFileCreatorTask struct {
|
|
dstPath string
|
|
wc *WriteCloser
|
|
nocache bool
|
|
}
|
|
|
|
// Add registers a task for creating the file at dstPath and assigning it to *wc.
|
|
//
|
|
// Tasks are executed in parallel on Run() call.
|
|
func (pfc *ParallelFileCreator) Add(dstPath string, wc *WriteCloser, nocache bool) {
|
|
pfc.tasks = append(pfc.tasks, parallelFileCreatorTask{
|
|
dstPath: dstPath,
|
|
wc: wc,
|
|
nocache: nocache,
|
|
})
|
|
}
|
|
|
|
// Run runs all the registered tasks for creating files in parallel.
|
|
func (pfc *ParallelFileCreator) Run() {
|
|
var wg sync.WaitGroup
|
|
concurrencyCh := fsutil.GetConcurrencyCh()
|
|
for _, task := range pfc.tasks {
|
|
concurrencyCh <- struct{}{}
|
|
wg.Go(func() {
|
|
*task.wc = MustCreate(task.dstPath, task.nocache)
|
|
<-concurrencyCh
|
|
})
|
|
}
|
|
wg.Wait()
|
|
}
|
|
|
|
// ParallelFileOpener is used for parallel opening of files at the given dstPath.
|
|
//
|
|
// ParallelFileOpener is needed for speeding up opening many files on high-latency
|
|
// storage systems such as NFS or Ceph.
|
|
type ParallelFileOpener struct {
|
|
tasks []parallelFileOpenerTask
|
|
}
|
|
|
|
type parallelFileOpenerTask struct {
|
|
path string
|
|
rc *ReadCloser
|
|
nocache bool
|
|
}
|
|
|
|
// Add registers a task for opening the file ath the given path and assigning it to *rc.
|
|
//
|
|
// Tasks are executed in parallel on Run() call.
|
|
func (pfo *ParallelFileOpener) Add(path string, rc *ReadCloser, nocache bool) {
|
|
pfo.tasks = append(pfo.tasks, parallelFileOpenerTask{
|
|
path: path,
|
|
rc: rc,
|
|
nocache: nocache,
|
|
})
|
|
}
|
|
|
|
// Run runs all the registered tasks for opening files in parallel.
|
|
func (pfo *ParallelFileOpener) Run() {
|
|
var wg sync.WaitGroup
|
|
concurrencyCh := fsutil.GetConcurrencyCh()
|
|
for _, task := range pfo.tasks {
|
|
concurrencyCh <- struct{}{}
|
|
wg.Go(func() {
|
|
*task.rc = MustOpen(task.path, task.nocache)
|
|
<-concurrencyCh
|
|
})
|
|
}
|
|
wg.Wait()
|
|
}
|
|
|
|
// ParallelStreamWriter is used for parallel writing of data from io.WriterTo to the given dstPath files.
|
|
//
|
|
// ParallelStreamWriter is needed for speeding up writing data to many files on high-latency
|
|
// storage systems such as NFS or Ceph.
|
|
type ParallelStreamWriter struct {
|
|
tasks []parallelStreamWriterTask
|
|
}
|
|
|
|
type parallelStreamWriterTask struct {
|
|
dstPath string
|
|
src io.WriterTo
|
|
}
|
|
|
|
// Add adds a task to execute in parallel - to write the data from src to the dstPath.
|
|
//
|
|
// Tasks are executed in parallel on Run() call.
|
|
func (psw *ParallelStreamWriter) Add(dstPath string, src io.WriterTo) {
|
|
psw.tasks = append(psw.tasks, parallelStreamWriterTask{
|
|
dstPath: dstPath,
|
|
src: src,
|
|
})
|
|
}
|
|
|
|
// Run executes all the tasks added via Add() call in parallel.
|
|
func (psw *ParallelStreamWriter) Run() {
|
|
var wg sync.WaitGroup
|
|
concurrencyCh := fsutil.GetConcurrencyCh()
|
|
for _, task := range psw.tasks {
|
|
concurrencyCh <- struct{}{}
|
|
|
|
wg.Go(func() {
|
|
f := MustCreate(task.dstPath, false)
|
|
if _, err := task.src.WriteTo(f); err != nil {
|
|
f.MustClose()
|
|
// Do not call MustRemovePath(path), so the user could inspect
|
|
// the file contents during investigation of the issue.
|
|
logger.Panicf("FATAL: cannot write data to %q: %s", task.dstPath, err)
|
|
}
|
|
f.MustClose()
|
|
|
|
<-concurrencyCh
|
|
})
|
|
}
|
|
wg.Wait()
|
|
}
|