From e0fc7253acdb6aad3ab082328fd5166fc8fe0c33 Mon Sep 17 00:00:00 2001 From: Arthur Lu Date: Mon, 28 Jul 2025 18:49:49 +0000 Subject: [PATCH] reduce usage of string split --- app/model.go | 24 ++++++++-------- app/proxmox.go | 75 +++++++++++++++++++++++++++++++------------------- 2 files changed, 58 insertions(+), 41 deletions(-) diff --git a/app/model.go b/app/model.go index 76056d0..dea3979 100644 --- a/app/model.go +++ b/app/model.go @@ -253,31 +253,31 @@ func (instance *Instance) RebuildBoot() { eligibleBoot[string(k)] = true } - x := strings.Split(instance.configBoot, "order=") // should be a;b;c;d ... - if len(x) == 2 { - y := strings.Split(x[1], ";") - for _, bootTarget := range y { + bootOrder := PVEObjectStringToMap(instance.configBoot)["order"] + + if len(bootOrder) != 0 { + for bootTarget := range strings.SplitSeq(bootOrder, ";") { // iterate over elements selected for boot, add them to Enabled, and remove them from eligible boot target _, isEligible := eligibleBoot[bootTarget] if val, ok := instance.Volumes[VolumeID(bootTarget)]; ok && isEligible { // if the item is eligible and is in volumes instance.Boot.Enabled = append(instance.Boot.Enabled, val) - eligibleBoot[bootTarget] = false + delete(eligibleBoot, bootTarget) } else if val, ok := instance.Nets[NetID(bootTarget)]; ok && isEligible { // if the item is eligible and is in nets instance.Boot.Enabled = append(instance.Boot.Enabled, val) - eligibleBoot[bootTarget] = false - } else { - log.Printf("Encountered non-eligible boot target %s in instance %s\n", bootTarget, instance.Name) - eligibleBoot[bootTarget] = false + delete(eligibleBoot, bootTarget) + } else { // item is not eligible for boot but is included in the boot order + log.Printf("Encountered enabled but non-eligible boot target %s in instance %s\n", bootTarget, instance.Name) + delete(eligibleBoot, bootTarget) } } } - for bootTarget, isEligible := range eligibleBoot { + for bootTarget, isEligible := range eligibleBoot { // iterate over remaining items, add them to Disabled if val, ok := instance.Volumes[VolumeID(bootTarget)]; ok && isEligible { // if the item is eligible and is in volumes instance.Boot.Disabled = append(instance.Boot.Disabled, val) } else if val, ok := instance.Nets[NetID(bootTarget)]; ok && isEligible { // if the item is eligible and is in nets instance.Boot.Disabled = append(instance.Boot.Disabled, val) - } else { - log.Printf("Encountered non-eligible boot target %s in instance %s\n", bootTarget, instance.Name) + } else { // item is not eligible and is not already in the boot order, skip adding to model + log.Printf("Encountered disabled and non-eligible boot target %s in instance %s\n", bootTarget, instance.Name) } } } diff --git a/app/proxmox.go b/app/proxmox.go index 64e1ed6..7407796 100644 --- a/app/proxmox.go +++ b/app/proxmox.go @@ -232,14 +232,11 @@ func MergeCTDisksAndUnused(cc *proxmox.ContainerConfig) map[string]string { func GetVolumeInfo(host *Node, volume string) (*Volume, error) { volumeData := Volume{} - storageID := strings.Split(volume, ":")[0] - volumeID := strings.Split(volume, ",")[0] - mp := "" - if strings.Contains(volume, "mp=") { - x := strings.Split(volume, "mp=")[1] - mp = strings.Split(x, ",")[0] - } - storage, err := host.pvenode.Storage(context.Background(), storageID) + volumeObj := PVEObjectStringToMap(volume) + volumeFile := volumeObj[""] + volumeStorage := strings.Split(volumeFile, ":")[0] + + storage, err := host.pvenode.Storage(context.Background(), volumeStorage) if err != nil { return &volumeData, nil } @@ -250,38 +247,58 @@ func GetVolumeInfo(host *Node, volume string) (*Volume, error) { } for _, c := range content { - if c.Volid == volumeID { - volumeData.Storage = storageID + if c.Volid == volumeFile { + volumeData.Storage = volumeStorage volumeData.Format = c.Format volumeData.Size = uint64(c.Size) - volumeData.File = volumeID - volumeData.MP = mp + volumeData.File = volumeFile + volumeData.MP = volumeObj["mp"] } } return &volumeData, nil } -func GetNetInfo(net string) (*Net, error) { +func GetNetInfo(netstring string) (*Net, error) { n := Net{} - for _, val := range strings.Split(net, ",") { - if strings.HasPrefix(val, "rate=") { - rate, err := strconv.ParseUint(strings.TrimPrefix(val, "rate="), 10, 64) - if err != nil { - return &n, err - } - n.Rate = rate - } else if strings.HasPrefix(val, "tag=") { - vlan, err := strconv.ParseUint(strings.TrimPrefix(val, "tag="), 10, 64) - if err != nil { - return &n, err - } - n.VLAN = vlan - } - } + netobj := PVEObjectStringToMap(netstring) - n.Value = net + rate, err := strconv.ParseUint(netobj["rate"], 10, 64) + if err != nil { + return &n, err + } + n.Rate = rate + + vlan, err := strconv.ParseUint(netobj["tag"], 10, 64) + if err != nil { + return &n, err + } + n.VLAN = vlan + + n.Value = netstring return &n, nil } + +// most pve objects (nets, disks, pcie, etc) have the following similar format: +// objname: v1,k2=v2,k3=v3,k4=v4 ... +// this function maps such strings to a map so that each individual key or value can be found more quickly +// in pcie or disks, the first value often does not have a key name, in such cases the key will be empty string "" +func PVEObjectStringToMap(objectstring string) map[string]string { + objectmap := map[string]string{} + for v := range strings.SplitSeq(objectstring, ",") { + key := "" + val := "" + if strings.Contains(v, "=") { + x := strings.Split(v, "=") + key = x[0] + val = x[1] + } else { + key = "" + val = v + } + objectmap[key] = val + } + return objectmap +}