xl: StatVol and ListVols should handle cases when disks are missing. (#1703)

Remove unnecessary code, handle cases of missing disk.
master
Harshavardhana 9 years ago
parent 6015a7a3cd
commit f76d975304
  1. 120
      xl-erasure-v1.go

@ -188,8 +188,6 @@ func (xl XL) DeleteVol(volume string) error {
// ListVols - list volumes. // ListVols - list volumes.
func (xl XL) ListVols() (volsInfo []VolInfo, err error) { func (xl XL) ListVols() (volsInfo []VolInfo, err error) {
emptyCount := 0
// Initialize sync waitgroup. // Initialize sync waitgroup.
var wg = &sync.WaitGroup{} var wg = &sync.WaitGroup{}
@ -202,45 +200,37 @@ func (xl XL) ListVols() (volsInfo []VolInfo, err error) {
defer wg.Done() defer wg.Done()
// Initiate listing. // Initiate listing.
vlsInfo, lErr := disk.ListVols() vlsInfo, _ := disk.ListVols()
if lErr == nil { successVols[index] = vlsInfo
if len(vlsInfo) == 0 {
emptyCount++ // Calculate empty count specially.
} else {
successVols[index] = vlsInfo
}
}
}(index, disk) }(index, disk)
} }
// For all the list volumes running in parallel to finish. // For all the list volumes running in parallel to finish.
wg.Wait() wg.Wait()
// If all list operations resulted in an empty count which is same
// as your total storage disks, then it is a valid case return
// success with empty vols.
if emptyCount == len(xl.storageDisks) {
return []VolInfo{}, nil
} else if len(successVols) < xl.readQuorum {
// If there is data and not empty, then we attempt quorum verification.
// Verify if we have enough quorum to list vols.
return nil, errReadQuorum
}
var total, free int64
// Loop through success vols and get aggregated usage values. // Loop through success vols and get aggregated usage values.
for _, vlsInfo := range successVols { var vlsInfo []VolInfo
if len(vlsInfo) == 0 { var total, free int64
for _, vlsInfo = range successVols {
if len(vlsInfo) <= 1 {
continue continue
} }
free += vlsInfo[0].Free var vlInfo VolInfo
total += vlsInfo[0].Total for _, vlInfo = range vlsInfo {
if vlInfo.Name == "" {
continue
}
break
}
free += vlInfo.Free
total += vlInfo.Total
} }
// Save the updated usage values back into the vols. // Save the updated usage values back into the vols.
for _, volInfo := range successVols[0] { for _, vlInfo := range vlsInfo {
volInfo.Free = free vlInfo.Free = free
volInfo.Total = total vlInfo.Total = total
volsInfo = append(volsInfo, volInfo) volsInfo = append(volsInfo, vlInfo)
} }
// NOTE: The assumption here is that volumes across all disks in // NOTE: The assumption here is that volumes across all disks in
@ -252,10 +242,10 @@ func (xl XL) ListVols() (volsInfo []VolInfo, err error) {
// getAllVolInfo - list bucket volume info from all disks. // getAllVolInfo - list bucket volume info from all disks.
// Returns error slice indicating the failed volume stat operations. // Returns error slice indicating the failed volume stat operations.
func (xl XL) getAllVolInfo(volume string) (volsInfo []VolInfo, errs []error) { func (xl XL) getAllVolInfo(volume string) ([]VolInfo, []error) {
// Create errs and volInfo slices of storageDisks size. // Create errs and volInfo slices of storageDisks size.
errs = make([]error, len(xl.storageDisks)) var errs = make([]error, len(xl.storageDisks))
volsInfo = make([]VolInfo, len(xl.storageDisks)) var volsInfo = make([]VolInfo, len(xl.storageDisks))
// Allocate a new waitgroup. // Allocate a new waitgroup.
var wg = &sync.WaitGroup{} var wg = &sync.WaitGroup{}
@ -287,7 +277,6 @@ func (xl XL) getAllVolInfo(volume string) (volsInfo []VolInfo, errs []error) {
// - error if any. // - error if any.
func (xl XL) listAllVolInfo(volume string) ([]VolInfo, bool, error) { func (xl XL) listAllVolInfo(volume string) ([]VolInfo, bool, error) {
volsInfo, errs := xl.getAllVolInfo(volume) volsInfo, errs := xl.getAllVolInfo(volume)
volsInfo = removeDuplicateVols(volsInfo)
notFoundCount := 0 notFoundCount := 0
for _, err := range errs { for _, err := range errs {
if err == errVolumeNotFound { if err == errVolumeNotFound {
@ -327,75 +316,42 @@ func (xl XL) listAllVolInfo(volume string) ([]VolInfo, bool, error) {
return volsInfo, heal, nil return volsInfo, heal, nil
} }
// healVolume - heals any missing volumes.
func (xl XL) healVolume(volume string) error {
// Lists volume info for all online disks.
volsInfo, heal, err := xl.listAllVolInfo(volume)
if err != nil {
return err
}
if !heal {
return nil
}
// Create volume if missing on online disks.
for index, volInfo := range volsInfo {
if volInfo.Name != "" {
continue
}
// Volinfo name would be an empty string, create it.
if err = xl.storageDisks[index].MakeVol(volume); err != nil {
continue
}
}
return nil
}
// Removes any duplicate vols.
func removeDuplicateVols(volsInfo []VolInfo) []VolInfo {
// Use map to record duplicates as we find them.
result := []VolInfo{}
m := make(map[string]VolInfo)
for _, v := range volsInfo {
if _, found := m[v.Name]; !found {
m[v.Name] = v
}
}
result = make([]VolInfo, 0, len(m))
for _, v := range m {
result = append(result, v)
}
// Return the new slice.
return result
}
// StatVol - get volume stat info. // StatVol - get volume stat info.
func (xl XL) StatVol(volume string) (volInfo VolInfo, err error) { func (xl XL) StatVol(volume string) (volInfo VolInfo, err error) {
if !isValidVolname(volume) { if !isValidVolname(volume) {
return VolInfo{}, errInvalidArgument return VolInfo{}, errInvalidArgument
} }
// List and figured out if we need healing.
volsInfo, heal, err := xl.listAllVolInfo(volume) volsInfo, heal, err := xl.listAllVolInfo(volume)
if err != nil { if err != nil {
return VolInfo{}, err return VolInfo{}, err
} }
// Heal for missing entries.
if heal { if heal {
go func() { go func() {
hErr := xl.healVolume(volume) // Create volume if missing on disks.
errorIf(hErr, "Unable to heal volume "+volume+".") for index, volInfo := range volsInfo {
if volInfo.Name != "" {
continue
}
// Volinfo name would be an empty string, create it.
xl.storageDisks[index].MakeVol(volume)
}
}() }()
} }
// Loop through all statVols, calculate the actual usage values. // Loop through all statVols, calculate the actual usage values.
var total, free int64 var total, free int64
for _, volInfo := range volsInfo { for _, volInfo = range volsInfo {
if volInfo.Name == "" {
continue
}
free += volInfo.Free free += volInfo.Free
total += volInfo.Total total += volInfo.Total
} }
// Filter volsInfo and update the volInfo. // Update the aggregated values.
volInfo = volsInfo[0]
volInfo.Free = free volInfo.Free = free
volInfo.Total = total volInfo.Total = total
return volInfo, nil return volInfo, nil

Loading…
Cancel
Save