mirror of
https://github.com/zrepl/zrepl.git
synced 2025-08-19 11:19:03 +02:00
zfs: use channel as iterator for ZFSList results
The old approach with ZFSList would keep the two-dimensional array of lines and their fields in memory (for a short time), which could easily consume 100s of MiB with > 10000 snapshots / bookmarks (see #34) fixes #61
This commit is contained in:
@@ -2,6 +2,7 @@ package zfs
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"strconv"
|
||||
@@ -61,17 +62,23 @@ type FilesystemVersionFilter interface {
|
||||
}
|
||||
|
||||
func ZFSListFilesystemVersions(fs *DatasetPath, filter FilesystemVersionFilter) (res []FilesystemVersion, err error) {
|
||||
var fieldLines [][]string
|
||||
fieldLines, err = ZFSList(
|
||||
listResults := make(chan ZFSListResult)
|
||||
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
defer cancel()
|
||||
go ZFSListChan(ctx, listResults,
|
||||
[]string{"name", "guid", "createtxg", "creation"},
|
||||
"-r", "-d", "1",
|
||||
"-t", "bookmark,snapshot",
|
||||
"-s", "createtxg", fs.ToString())
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
res = make([]FilesystemVersion, 0, len(fieldLines))
|
||||
for _, line := range fieldLines {
|
||||
|
||||
res = make([]FilesystemVersion, 0)
|
||||
for listResult := range listResults {
|
||||
if listResult.err != nil {
|
||||
return nil, listResult.err
|
||||
}
|
||||
|
||||
line := listResult.fields
|
||||
|
||||
if len(line[0]) < 3 {
|
||||
err = errors.New(fmt.Sprintf("snapshot or bookmark name implausibly short: %s", line[0]))
|
||||
|
Reference in New Issue
Block a user