| 
									
										
										
										
											2021-04-19 03:41:13 +08:00
										 |  |  | // Copyright (c) 2015-2021 MinIO, Inc.
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | // This file is part of MinIO Object Storage stack
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | // This program is free software: you can redistribute it and/or modify
 | 
					
						
							|  |  |  | // it under the terms of the GNU Affero General Public License as published by
 | 
					
						
							|  |  |  | // the Free Software Foundation, either version 3 of the License, or
 | 
					
						
							|  |  |  | // (at your option) any later version.
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | // This program is distributed in the hope that it will be useful
 | 
					
						
							|  |  |  | // but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
					
						
							|  |  |  | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
					
						
							|  |  |  | // GNU Affero General Public License for more details.
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | // You should have received a copy of the GNU Affero General Public License
 | 
					
						
							|  |  |  | // along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
					
						
							| 
									
										
										
										
											2016-06-14 16:12:15 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-19 07:23:42 +08:00
										 |  |  | package cmd | 
					
						
							| 
									
										
										
										
											2016-06-14 16:12:15 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-07-29 07:49:59 +08:00
										 |  |  | import ( | 
					
						
							| 
									
										
										
										
											2022-02-05 04:21:21 +08:00
										 |  |  | 	"crypto/sha256" | 
					
						
							|  |  |  | 	"encoding/hex" | 
					
						
							| 
									
										
										
										
											2018-02-16 09:45:57 +08:00
										 |  |  | 	"encoding/json" | 
					
						
							| 
									
										
										
										
											2020-08-04 09:17:48 +08:00
										 |  |  | 	"errors" | 
					
						
							| 
									
										
										
										
											2018-02-16 09:45:57 +08:00
										 |  |  | 	"io/ioutil" | 
					
						
							| 
									
										
										
										
											2017-06-13 08:40:28 +08:00
										 |  |  | 	"os" | 
					
						
							| 
									
										
										
										
											2018-03-20 00:13:00 +08:00
										 |  |  | 	"reflect" | 
					
						
							| 
									
										
										
										
											2016-07-29 07:49:59 +08:00
										 |  |  | 	"testing" | 
					
						
							|  |  |  | ) | 
					
						
							| 
									
										
										
										
											2016-06-14 16:12:15 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-06-13 11:04:01 +08:00
										 |  |  | // tests fixFormatErasureV3 - fix format.json on all disks.
 | 
					
						
							| 
									
										
										
										
											2018-03-20 00:13:00 +08:00
										 |  |  | func TestFixFormatV3(t *testing.T) { | 
					
						
							| 
									
										
										
										
											2020-06-13 11:04:01 +08:00
										 |  |  | 	erasureDirs, err := getRandomDisks(8) | 
					
						
							| 
									
										
										
										
											2018-03-20 00:13:00 +08:00
										 |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		t.Fatal(err) | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2020-06-13 11:04:01 +08:00
										 |  |  | 	for _, erasureDir := range erasureDirs { | 
					
						
							|  |  |  | 		defer os.RemoveAll(erasureDir) | 
					
						
							| 
									
										
										
										
											2018-03-20 00:13:00 +08:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2020-06-13 11:04:01 +08:00
										 |  |  | 	endpoints := mustGetNewEndpoints(erasureDirs...) | 
					
						
							| 
									
										
										
										
											2018-03-20 00:13:00 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-09-28 07:47:12 +08:00
										 |  |  | 	storageDisks, errs := initStorageDisksWithErrors(endpoints) | 
					
						
							|  |  |  | 	for _, err := range errs { | 
					
						
							|  |  |  | 		if err != nil && err != errDiskNotFound { | 
					
						
							|  |  |  | 			t.Fatal(err) | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2018-04-04 12:58:48 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-01-17 04:08:02 +08:00
										 |  |  | 	format := newFormatErasureV3(1, 8) | 
					
						
							|  |  |  | 	format.Erasure.DistributionAlgo = formatErasureVersionV2DistributionAlgoV1 | 
					
						
							| 
									
										
										
										
											2020-06-13 11:04:01 +08:00
										 |  |  | 	formats := make([]*formatErasureV3, 8) | 
					
						
							| 
									
										
										
										
											2018-03-20 00:13:00 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	for j := 0; j < 8; j++ { | 
					
						
							| 
									
										
										
										
											2019-11-21 20:24:51 +08:00
										 |  |  | 		newFormat := format.Clone() | 
					
						
							| 
									
										
										
										
											2020-06-13 11:04:01 +08:00
										 |  |  | 		newFormat.Erasure.This = format.Erasure.Sets[0][j] | 
					
						
							| 
									
										
										
										
											2019-11-21 20:24:51 +08:00
										 |  |  | 		formats[j] = newFormat | 
					
						
							| 
									
										
										
										
											2018-03-20 00:13:00 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	formats[1] = nil | 
					
						
							| 
									
										
										
										
											2020-06-13 11:04:01 +08:00
										 |  |  | 	expThis := formats[2].Erasure.This | 
					
						
							|  |  |  | 	formats[2].Erasure.This = "" | 
					
						
							|  |  |  | 	if err := fixFormatErasureV3(storageDisks, endpoints, formats); err != nil { | 
					
						
							| 
									
										
										
										
											2018-03-20 00:13:00 +08:00
										 |  |  | 		t.Fatal(err) | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2018-04-04 12:58:48 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-06-13 11:04:01 +08:00
										 |  |  | 	newFormats, errs := loadFormatErasureAll(storageDisks, false) | 
					
						
							| 
									
										
										
										
											2018-03-20 00:13:00 +08:00
										 |  |  | 	for _, err := range errs { | 
					
						
							| 
									
										
										
										
											2018-04-11 00:36:37 +08:00
										 |  |  | 		if err != nil && err != errUnformattedDisk { | 
					
						
							| 
									
										
										
										
											2018-03-20 00:13:00 +08:00
										 |  |  | 			t.Fatal(err) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2020-06-13 11:04:01 +08:00
										 |  |  | 	gotThis := newFormats[2].Erasure.This | 
					
						
							| 
									
										
										
										
											2018-03-20 00:13:00 +08:00
										 |  |  | 	if expThis != gotThis { | 
					
						
							|  |  |  | 		t.Fatalf("expected uuid %s, got %s", expThis, gotThis) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-06-13 11:04:01 +08:00
										 |  |  | // tests formatErasureV3ThisEmpty conditions.
 | 
					
						
							|  |  |  | func TestFormatErasureEmpty(t *testing.T) { | 
					
						
							| 
									
										
										
										
											2021-01-17 04:08:02 +08:00
										 |  |  | 	format := newFormatErasureV3(1, 16) | 
					
						
							|  |  |  | 	format.Erasure.DistributionAlgo = formatErasureVersionV2DistributionAlgoV1 | 
					
						
							| 
									
										
										
										
											2020-06-13 11:04:01 +08:00
										 |  |  | 	formats := make([]*formatErasureV3, 16) | 
					
						
							| 
									
										
										
										
											2018-03-20 00:13:00 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	for j := 0; j < 16; j++ { | 
					
						
							| 
									
										
										
										
											2019-11-21 20:24:51 +08:00
										 |  |  | 		newFormat := format.Clone() | 
					
						
							| 
									
										
										
										
											2020-06-13 11:04:01 +08:00
										 |  |  | 		newFormat.Erasure.This = format.Erasure.Sets[0][j] | 
					
						
							| 
									
										
										
										
											2019-11-21 20:24:51 +08:00
										 |  |  | 		formats[j] = newFormat | 
					
						
							| 
									
										
										
										
											2018-03-20 00:13:00 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// empty format to indicate disk not found, but this
 | 
					
						
							|  |  |  | 	// empty should return false.
 | 
					
						
							|  |  |  | 	formats[0] = nil | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-06-13 11:04:01 +08:00
										 |  |  | 	if ok := formatErasureV3ThisEmpty(formats); ok { | 
					
						
							| 
									
										
										
										
											2018-03-20 00:13:00 +08:00
										 |  |  | 		t.Fatalf("expected value false, got %t", ok) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-06-13 11:04:01 +08:00
										 |  |  | 	formats[2].Erasure.This = "" | 
					
						
							|  |  |  | 	if ok := formatErasureV3ThisEmpty(formats); !ok { | 
					
						
							| 
									
										
										
										
											2018-03-20 00:13:00 +08:00
										 |  |  | 		t.Fatalf("expected value true, got %t", ok) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-02-16 09:45:57 +08:00
										 |  |  | // Tests xl format migration.
 | 
					
						
							| 
									
										
										
										
											2020-06-13 11:04:01 +08:00
										 |  |  | func TestFormatErasureMigrate(t *testing.T) { | 
					
						
							| 
									
										
										
										
											2018-02-16 09:45:57 +08:00
										 |  |  | 	// Get test root.
 | 
					
						
							|  |  |  | 	rootPath, err := getTestRoot() | 
					
						
							| 
									
										
										
										
											2016-07-29 07:49:59 +08:00
										 |  |  | 	if err != nil { | 
					
						
							| 
									
										
										
										
											2018-02-16 09:45:57 +08:00
										 |  |  | 		t.Fatal(err) | 
					
						
							| 
									
										
										
										
											2016-07-29 07:49:59 +08:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2018-02-16 09:45:57 +08:00
										 |  |  | 	defer os.RemoveAll(rootPath) | 
					
						
							| 
									
										
										
										
											2016-07-29 07:49:59 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-06-13 11:04:01 +08:00
										 |  |  | 	m := &formatErasureV1{} | 
					
						
							|  |  |  | 	m.Format = formatBackendErasure | 
					
						
							| 
									
										
										
										
											2018-02-16 09:45:57 +08:00
										 |  |  | 	m.Version = formatMetaVersionV1 | 
					
						
							| 
									
										
										
										
											2020-06-13 11:04:01 +08:00
										 |  |  | 	m.Erasure.Version = formatErasureVersionV1 | 
					
						
							|  |  |  | 	m.Erasure.Disk = mustGetUUID() | 
					
						
							|  |  |  | 	m.Erasure.JBOD = []string{m.Erasure.Disk, mustGetUUID(), mustGetUUID(), mustGetUUID()} | 
					
						
							| 
									
										
										
										
											2016-07-29 07:49:59 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-02-16 09:45:57 +08:00
										 |  |  | 	b, err := json.Marshal(m) | 
					
						
							| 
									
										
										
										
											2016-07-29 07:49:59 +08:00
										 |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		t.Fatal(err) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-01-03 01:15:06 +08:00
										 |  |  | 	if err = os.MkdirAll(pathJoin(rootPath, minioMetaBucket), os.FileMode(0o755)); err != nil { | 
					
						
							| 
									
										
										
										
											2016-07-29 07:49:59 +08:00
										 |  |  | 		t.Fatal(err) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-01-03 01:15:06 +08:00
										 |  |  | 	if err = ioutil.WriteFile(pathJoin(rootPath, minioMetaBucket, formatConfigFile), b, os.FileMode(0o644)); err != nil { | 
					
						
							| 
									
										
										
										
											2018-02-16 09:45:57 +08:00
										 |  |  | 		t.Fatal(err) | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2016-07-29 07:49:59 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-01-25 03:28:45 +08:00
										 |  |  | 	formatData, _, err := formatErasureMigrate(rootPath) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							| 
									
										
										
										
											2016-07-29 07:49:59 +08:00
										 |  |  | 		t.Fatal(err) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-01-25 03:28:45 +08:00
										 |  |  | 	migratedVersion, err := formatGetBackendErasureVersion(formatData) | 
					
						
							| 
									
										
										
										
											2018-03-16 04:55:23 +08:00
										 |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		t.Fatal(err) | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2019-12-24 08:31:03 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-06-13 11:04:01 +08:00
										 |  |  | 	if migratedVersion != formatErasureVersionV3 { | 
					
						
							|  |  |  | 		t.Fatalf("expected version: %s, got: %s", formatErasureVersionV3, migratedVersion) | 
					
						
							| 
									
										
										
										
											2018-03-20 00:13:00 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	b, err = ioutil.ReadFile(pathJoin(rootPath, minioMetaBucket, formatConfigFile)) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		t.Fatal(err) | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2020-06-13 11:04:01 +08:00
										 |  |  | 	formatV3 := &formatErasureV3{} | 
					
						
							| 
									
										
										
										
											2018-03-20 00:13:00 +08:00
										 |  |  | 	if err = json.Unmarshal(b, formatV3); err != nil { | 
					
						
							|  |  |  | 		t.Fatal(err) | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2020-06-13 11:04:01 +08:00
										 |  |  | 	if formatV3.Erasure.This != m.Erasure.Disk { | 
					
						
							|  |  |  | 		t.Fatalf("expected disk uuid: %s, got: %s", m.Erasure.Disk, formatV3.Erasure.This) | 
					
						
							| 
									
										
										
										
											2018-03-20 00:13:00 +08:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2020-06-13 11:04:01 +08:00
										 |  |  | 	if len(formatV3.Erasure.Sets) != 1 { | 
					
						
							|  |  |  | 		t.Fatalf("expected single set after migrating from v1 to v3, but found %d", len(formatV3.Erasure.Sets)) | 
					
						
							| 
									
										
										
										
											2018-03-20 00:13:00 +08:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2020-06-13 11:04:01 +08:00
										 |  |  | 	if !reflect.DeepEqual(formatV3.Erasure.Sets[0], m.Erasure.JBOD) { | 
					
						
							|  |  |  | 		t.Fatalf("expected disk uuid: %v, got: %v", m.Erasure.JBOD, formatV3.Erasure.Sets[0]) | 
					
						
							| 
									
										
										
										
											2018-03-16 04:55:23 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-06-13 11:04:01 +08:00
										 |  |  | 	m = &formatErasureV1{} | 
					
						
							| 
									
										
										
										
											2018-02-16 09:45:57 +08:00
										 |  |  | 	m.Format = "unknown" | 
					
						
							|  |  |  | 	m.Version = formatMetaVersionV1 | 
					
						
							| 
									
										
										
										
											2020-06-13 11:04:01 +08:00
										 |  |  | 	m.Erasure.Version = formatErasureVersionV1 | 
					
						
							|  |  |  | 	m.Erasure.Disk = mustGetUUID() | 
					
						
							|  |  |  | 	m.Erasure.JBOD = []string{m.Erasure.Disk, mustGetUUID(), mustGetUUID(), mustGetUUID()} | 
					
						
							| 
									
										
										
										
											2018-02-16 09:45:57 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	b, err = json.Marshal(m) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							| 
									
										
										
										
											2016-07-29 07:49:59 +08:00
										 |  |  | 		t.Fatal(err) | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2018-02-16 09:45:57 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-01-03 01:15:06 +08:00
										 |  |  | 	if err = ioutil.WriteFile(pathJoin(rootPath, minioMetaBucket, formatConfigFile), b, os.FileMode(0o644)); err != nil { | 
					
						
							| 
									
										
										
										
											2016-07-29 07:49:59 +08:00
										 |  |  | 		t.Fatal(err) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-01-25 03:28:45 +08:00
										 |  |  | 	if _, _, err = formatErasureMigrate(rootPath); err == nil { | 
					
						
							| 
									
										
										
										
											2018-02-16 09:45:57 +08:00
										 |  |  | 		t.Fatal("Expected to fail with unexpected backend format") | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2016-07-29 07:49:59 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-06-13 11:04:01 +08:00
										 |  |  | 	m = &formatErasureV1{} | 
					
						
							|  |  |  | 	m.Format = formatBackendErasure | 
					
						
							| 
									
										
										
										
											2018-02-16 09:45:57 +08:00
										 |  |  | 	m.Version = formatMetaVersionV1 | 
					
						
							| 
									
										
										
										
											2020-06-13 11:04:01 +08:00
										 |  |  | 	m.Erasure.Version = "30" | 
					
						
							|  |  |  | 	m.Erasure.Disk = mustGetUUID() | 
					
						
							|  |  |  | 	m.Erasure.JBOD = []string{m.Erasure.Disk, mustGetUUID(), mustGetUUID(), mustGetUUID()} | 
					
						
							| 
									
										
										
										
											2016-07-29 07:49:59 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-02-16 09:45:57 +08:00
										 |  |  | 	b, err = json.Marshal(m) | 
					
						
							| 
									
										
										
										
											2016-07-29 07:49:59 +08:00
										 |  |  | 	if err != nil { | 
					
						
							| 
									
										
										
										
											2018-02-16 09:45:57 +08:00
										 |  |  | 		t.Fatal(err) | 
					
						
							| 
									
										
										
										
											2016-07-29 07:49:59 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-01-03 01:15:06 +08:00
										 |  |  | 	if err = ioutil.WriteFile(pathJoin(rootPath, minioMetaBucket, formatConfigFile), b, os.FileMode(0o644)); err != nil { | 
					
						
							| 
									
										
										
										
											2018-02-16 09:45:57 +08:00
										 |  |  | 		t.Fatal(err) | 
					
						
							| 
									
										
										
										
											2016-07-29 07:49:59 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-01-25 03:28:45 +08:00
										 |  |  | 	if _, _, err = formatErasureMigrate(rootPath); err == nil { | 
					
						
							| 
									
										
										
										
											2018-02-16 09:45:57 +08:00
										 |  |  | 		t.Fatal("Expected to fail with unexpected backend format version number") | 
					
						
							| 
									
										
										
										
											2016-07-29 07:49:59 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-02-16 09:45:57 +08:00
										 |  |  | // Tests check format xl value.
 | 
					
						
							| 
									
										
										
										
											2020-06-13 11:04:01 +08:00
										 |  |  | func TestCheckFormatErasureValue(t *testing.T) { | 
					
						
							| 
									
										
										
										
											2016-06-14 16:12:15 +08:00
										 |  |  | 	testCases := []struct { | 
					
						
							| 
									
										
										
										
											2020-06-13 11:04:01 +08:00
										 |  |  | 		format  *formatErasureV3 | 
					
						
							| 
									
										
										
										
											2018-02-16 09:45:57 +08:00
										 |  |  | 		success bool | 
					
						
							| 
									
										
										
										
											2016-06-14 16:12:15 +08:00
										 |  |  | 	}{ | 
					
						
							| 
									
										
										
										
											2020-06-13 11:04:01 +08:00
										 |  |  | 		// Invalid Erasure format version "2".
 | 
					
						
							| 
									
										
										
										
											2016-06-14 16:12:15 +08:00
										 |  |  | 		{ | 
					
						
							| 
									
										
										
										
											2020-06-13 11:04:01 +08:00
										 |  |  | 			&formatErasureV3{ | 
					
						
							| 
									
										
										
										
											2018-07-17 11:26:42 +08:00
										 |  |  | 				formatMetaV1: formatMetaV1{ | 
					
						
							|  |  |  | 					Version: "2", | 
					
						
							| 
									
										
										
										
											2020-06-13 11:04:01 +08:00
										 |  |  | 					Format:  "Erasure", | 
					
						
							| 
									
										
										
										
											2018-07-17 11:26:42 +08:00
										 |  |  | 				}, | 
					
						
							| 
									
										
										
										
											2020-06-13 11:04:01 +08:00
										 |  |  | 				Erasure: struct { | 
					
						
							| 
									
										
										
										
											2018-02-16 09:45:57 +08:00
										 |  |  | 					Version          string     `json:"version"` | 
					
						
							|  |  |  | 					This             string     `json:"this"` | 
					
						
							|  |  |  | 					Sets             [][]string `json:"sets"` | 
					
						
							|  |  |  | 					DistributionAlgo string     `json:"distributionAlgo"` | 
					
						
							|  |  |  | 				}{ | 
					
						
							|  |  |  | 					Version: "2", | 
					
						
							|  |  |  | 				}, | 
					
						
							|  |  |  | 			}, | 
					
						
							|  |  |  | 			false, | 
					
						
							| 
									
										
										
										
											2016-06-14 16:12:15 +08:00
										 |  |  | 		}, | 
					
						
							| 
									
										
										
										
											2020-06-13 11:04:01 +08:00
										 |  |  | 		// Invalid Erasure format "Unknown".
 | 
					
						
							| 
									
										
										
										
											2016-06-14 16:12:15 +08:00
										 |  |  | 		{ | 
					
						
							| 
									
										
										
										
											2020-06-13 11:04:01 +08:00
										 |  |  | 			&formatErasureV3{ | 
					
						
							| 
									
										
										
										
											2018-07-17 11:26:42 +08:00
										 |  |  | 				formatMetaV1: formatMetaV1{ | 
					
						
							|  |  |  | 					Version: "1", | 
					
						
							|  |  |  | 					Format:  "Unknown", | 
					
						
							|  |  |  | 				}, | 
					
						
							| 
									
										
										
										
											2020-06-13 11:04:01 +08:00
										 |  |  | 				Erasure: struct { | 
					
						
							| 
									
										
										
										
											2018-02-16 09:45:57 +08:00
										 |  |  | 					Version          string     `json:"version"` | 
					
						
							|  |  |  | 					This             string     `json:"this"` | 
					
						
							|  |  |  | 					Sets             [][]string `json:"sets"` | 
					
						
							|  |  |  | 					DistributionAlgo string     `json:"distributionAlgo"` | 
					
						
							|  |  |  | 				}{ | 
					
						
							|  |  |  | 					Version: "2", | 
					
						
							|  |  |  | 				}, | 
					
						
							|  |  |  | 			}, | 
					
						
							|  |  |  | 			false, | 
					
						
							| 
									
										
										
										
											2016-06-14 16:12:15 +08:00
										 |  |  | 		}, | 
					
						
							| 
									
										
										
										
											2020-06-13 11:04:01 +08:00
										 |  |  | 		// Invalid Erasure format version "0".
 | 
					
						
							| 
									
										
										
										
											2016-06-14 16:12:15 +08:00
										 |  |  | 		{ | 
					
						
							| 
									
										
										
										
											2020-06-13 11:04:01 +08:00
										 |  |  | 			&formatErasureV3{ | 
					
						
							| 
									
										
										
										
											2018-07-17 11:26:42 +08:00
										 |  |  | 				formatMetaV1: formatMetaV1{ | 
					
						
							|  |  |  | 					Version: "1", | 
					
						
							| 
									
										
										
										
											2020-06-13 11:04:01 +08:00
										 |  |  | 					Format:  "Erasure", | 
					
						
							| 
									
										
										
										
											2018-07-17 11:26:42 +08:00
										 |  |  | 				}, | 
					
						
							| 
									
										
										
										
											2020-06-13 11:04:01 +08:00
										 |  |  | 				Erasure: struct { | 
					
						
							| 
									
										
										
										
											2018-02-16 09:45:57 +08:00
										 |  |  | 					Version          string     `json:"version"` | 
					
						
							|  |  |  | 					This             string     `json:"this"` | 
					
						
							|  |  |  | 					Sets             [][]string `json:"sets"` | 
					
						
							|  |  |  | 					DistributionAlgo string     `json:"distributionAlgo"` | 
					
						
							|  |  |  | 				}{ | 
					
						
							|  |  |  | 					Version: "0", | 
					
						
							|  |  |  | 				}, | 
					
						
							|  |  |  | 			}, | 
					
						
							|  |  |  | 			false, | 
					
						
							| 
									
										
										
										
											2016-09-10 03:53:09 +08:00
										 |  |  | 		}, | 
					
						
							| 
									
										
										
										
											2016-06-14 16:12:15 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-02-16 09:45:57 +08:00
										 |  |  | 	// Valid all test cases.
 | 
					
						
							| 
									
										
										
										
											2016-06-14 16:12:15 +08:00
										 |  |  | 	for i, testCase := range testCases { | 
					
						
							| 
									
										
										
										
											2021-01-30 03:40:55 +08:00
										 |  |  | 		if err := checkFormatErasureValue(testCase.format, nil); err != nil && testCase.success { | 
					
						
							| 
									
										
										
										
											2018-02-16 09:45:57 +08:00
										 |  |  | 			t.Errorf("Test %d: Expected failure %s", i+1, err) | 
					
						
							| 
									
										
										
										
											2016-06-14 16:12:15 +08:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2016-09-10 03:53:09 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-06-13 11:04:01 +08:00
										 |  |  | // Tests getFormatErasureInQuorum()
 | 
					
						
							|  |  |  | func TestGetFormatErasureInQuorumCheck(t *testing.T) { | 
					
						
							| 
									
										
										
										
											2018-02-16 09:45:57 +08:00
										 |  |  | 	setCount := 2 | 
					
						
							| 
									
										
										
										
											2020-08-27 10:29:35 +08:00
										 |  |  | 	setDriveCount := 16 | 
					
						
							| 
									
										
										
										
											2016-09-10 03:53:09 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-01-17 04:08:02 +08:00
										 |  |  | 	format := newFormatErasureV3(setCount, setDriveCount) | 
					
						
							|  |  |  | 	format.Erasure.DistributionAlgo = formatErasureVersionV2DistributionAlgoV1 | 
					
						
							| 
									
										
										
										
											2020-06-13 11:04:01 +08:00
										 |  |  | 	formats := make([]*formatErasureV3, 32) | 
					
						
							| 
									
										
										
										
											2017-08-03 19:37:02 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-02-16 09:45:57 +08:00
										 |  |  | 	for i := 0; i < setCount; i++ { | 
					
						
							| 
									
										
										
										
											2020-08-27 10:29:35 +08:00
										 |  |  | 		for j := 0; j < setDriveCount; j++ { | 
					
						
							| 
									
										
										
										
											2019-11-21 20:24:51 +08:00
										 |  |  | 			newFormat := format.Clone() | 
					
						
							| 
									
										
										
										
											2020-06-13 11:04:01 +08:00
										 |  |  | 			newFormat.Erasure.This = format.Erasure.Sets[i][j] | 
					
						
							| 
									
										
										
										
											2020-08-27 10:29:35 +08:00
										 |  |  | 			formats[i*setDriveCount+j] = newFormat | 
					
						
							| 
									
										
										
										
											2017-08-03 19:37:02 +08:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2016-09-10 03:53:09 +08:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2016-09-11 00:54:22 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-02-16 09:45:57 +08:00
										 |  |  | 	// Return a format from list of formats in quorum.
 | 
					
						
							| 
									
										
										
										
											2020-06-13 11:04:01 +08:00
										 |  |  | 	quorumFormat, err := getFormatErasureInQuorum(formats) | 
					
						
							| 
									
										
										
										
											2016-09-11 10:32:18 +08:00
										 |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		t.Fatal(err) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-02-16 09:45:57 +08:00
										 |  |  | 	// Check if the reference format and input formats are same.
 | 
					
						
							| 
									
										
										
										
											2020-06-13 11:04:01 +08:00
										 |  |  | 	if err = formatErasureV3Check(quorumFormat, formats[0]); err != nil { | 
					
						
							| 
									
										
										
										
											2016-09-11 00:54:22 +08:00
										 |  |  | 		t.Fatal(err) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-02-16 09:45:57 +08:00
										 |  |  | 	// QuorumFormat has .This field empty on purpose, expect a failure.
 | 
					
						
							| 
									
										
										
										
											2020-06-13 11:04:01 +08:00
										 |  |  | 	if err = formatErasureV3Check(formats[0], quorumFormat); err == nil { | 
					
						
							| 
									
										
										
										
											2018-02-16 09:45:57 +08:00
										 |  |  | 		t.Fatal("Unexpected success") | 
					
						
							| 
									
										
										
										
											2016-09-11 00:54:22 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-02-16 09:45:57 +08:00
										 |  |  | 	formats[0] = nil | 
					
						
							| 
									
										
										
										
											2020-06-13 11:04:01 +08:00
										 |  |  | 	quorumFormat, err = getFormatErasureInQuorum(formats) | 
					
						
							| 
									
										
										
										
											2016-09-11 10:32:18 +08:00
										 |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		t.Fatal(err) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-02-16 09:45:57 +08:00
										 |  |  | 	badFormat := *quorumFormat | 
					
						
							| 
									
										
										
										
											2020-06-13 11:04:01 +08:00
										 |  |  | 	badFormat.Erasure.Sets = nil | 
					
						
							|  |  |  | 	if err = formatErasureV3Check(quorumFormat, &badFormat); err == nil { | 
					
						
							| 
									
										
										
										
											2018-02-16 09:45:57 +08:00
										 |  |  | 		t.Fatal("Unexpected success") | 
					
						
							| 
									
										
										
										
											2016-09-11 00:54:22 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-02-16 09:45:57 +08:00
										 |  |  | 	badFormatUUID := *quorumFormat | 
					
						
							| 
									
										
										
										
											2020-06-13 11:04:01 +08:00
										 |  |  | 	badFormatUUID.Erasure.Sets[0][0] = "bad-uuid" | 
					
						
							|  |  |  | 	if err = formatErasureV3Check(quorumFormat, &badFormatUUID); err == nil { | 
					
						
							| 
									
										
										
										
											2018-02-16 09:45:57 +08:00
										 |  |  | 		t.Fatal("Unexpected success") | 
					
						
							| 
									
										
										
										
											2016-09-11 00:54:22 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-02-16 09:45:57 +08:00
										 |  |  | 	badFormatSetSize := *quorumFormat | 
					
						
							| 
									
										
										
										
											2020-06-13 11:04:01 +08:00
										 |  |  | 	badFormatSetSize.Erasure.Sets[0] = nil | 
					
						
							|  |  |  | 	if err = formatErasureV3Check(quorumFormat, &badFormatSetSize); err == nil { | 
					
						
							| 
									
										
										
										
											2018-02-16 09:45:57 +08:00
										 |  |  | 		t.Fatal("Unexpected success") | 
					
						
							| 
									
										
										
										
											2016-09-11 10:32:18 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-02-16 09:45:57 +08:00
										 |  |  | 	for i := range formats { | 
					
						
							|  |  |  | 		if i < 17 { | 
					
						
							|  |  |  | 			formats[i] = nil | 
					
						
							| 
									
										
										
										
											2016-09-11 00:54:22 +08:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2020-06-13 11:04:01 +08:00
										 |  |  | 	if _, err = getFormatErasureInQuorum(formats); err == nil { | 
					
						
							| 
									
										
										
										
											2018-02-16 09:45:57 +08:00
										 |  |  | 		t.Fatal("Unexpected success") | 
					
						
							| 
									
										
										
										
											2016-09-11 00:54:22 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-02-05 04:21:21 +08:00
										 |  |  | // Get backend Erasure format in quorum `format.json`.
 | 
					
						
							|  |  |  | func getFormatErasureInQuorumOld(formats []*formatErasureV3) (*formatErasureV3, error) { | 
					
						
							|  |  |  | 	formatHashes := make([]string, len(formats)) | 
					
						
							|  |  |  | 	for i, format := range formats { | 
					
						
							|  |  |  | 		if format == nil { | 
					
						
							|  |  |  | 			continue | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		h := sha256.New() | 
					
						
							|  |  |  | 		for _, set := range format.Erasure.Sets { | 
					
						
							|  |  |  | 			for _, diskID := range set { | 
					
						
							|  |  |  | 				h.Write([]byte(diskID)) | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		formatHashes[i] = hex.EncodeToString(h.Sum(nil)) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	formatCountMap := make(map[string]int) | 
					
						
							|  |  |  | 	for _, hash := range formatHashes { | 
					
						
							|  |  |  | 		if hash == "" { | 
					
						
							|  |  |  | 			continue | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		formatCountMap[hash]++ | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	maxHash := "" | 
					
						
							|  |  |  | 	maxCount := 0 | 
					
						
							|  |  |  | 	for hash, count := range formatCountMap { | 
					
						
							|  |  |  | 		if count > maxCount { | 
					
						
							|  |  |  | 			maxCount = count | 
					
						
							|  |  |  | 			maxHash = hash | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if maxCount < len(formats)/2 { | 
					
						
							|  |  |  | 		return nil, errErasureReadQuorum | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	for i, hash := range formatHashes { | 
					
						
							|  |  |  | 		if hash == maxHash { | 
					
						
							|  |  |  | 			format := formats[i].Clone() | 
					
						
							|  |  |  | 			format.Erasure.This = "" | 
					
						
							|  |  |  | 			return format, nil | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return nil, errErasureReadQuorum | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func BenchmarkGetFormatErasureInQuorumOld(b *testing.B) { | 
					
						
							|  |  |  | 	setCount := 200 | 
					
						
							|  |  |  | 	setDriveCount := 15 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	format := newFormatErasureV3(setCount, setDriveCount) | 
					
						
							|  |  |  | 	format.Erasure.DistributionAlgo = formatErasureVersionV2DistributionAlgoV1 | 
					
						
							|  |  |  | 	formats := make([]*formatErasureV3, 15*200) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	for i := 0; i < setCount; i++ { | 
					
						
							|  |  |  | 		for j := 0; j < setDriveCount; j++ { | 
					
						
							|  |  |  | 			newFormat := format.Clone() | 
					
						
							|  |  |  | 			newFormat.Erasure.This = format.Erasure.Sets[i][j] | 
					
						
							|  |  |  | 			formats[i*setDriveCount+j] = newFormat | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	b.ResetTimer() | 
					
						
							|  |  |  | 	b.ReportAllocs() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	for i := 0; i < b.N; i++ { | 
					
						
							|  |  |  | 		_, _ = getFormatErasureInQuorumOld(formats) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func BenchmarkGetFormatErasureInQuorum(b *testing.B) { | 
					
						
							|  |  |  | 	setCount := 200 | 
					
						
							|  |  |  | 	setDriveCount := 15 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	format := newFormatErasureV3(setCount, setDriveCount) | 
					
						
							|  |  |  | 	format.Erasure.DistributionAlgo = formatErasureVersionV2DistributionAlgoV1 | 
					
						
							|  |  |  | 	formats := make([]*formatErasureV3, 15*200) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	for i := 0; i < setCount; i++ { | 
					
						
							|  |  |  | 		for j := 0; j < setDriveCount; j++ { | 
					
						
							|  |  |  | 			newFormat := format.Clone() | 
					
						
							|  |  |  | 			newFormat.Erasure.This = format.Erasure.Sets[i][j] | 
					
						
							|  |  |  | 			formats[i*setDriveCount+j] = newFormat | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	b.ResetTimer() | 
					
						
							|  |  |  | 	b.ReportAllocs() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	for i := 0; i < b.N; i++ { | 
					
						
							|  |  |  | 		_, _ = getFormatErasureInQuorum(formats) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-06-13 11:04:01 +08:00
										 |  |  | // Tests formatErasureGetDeploymentID()
 | 
					
						
							|  |  |  | func TestGetErasureID(t *testing.T) { | 
					
						
							| 
									
										
										
										
											2018-07-19 11:17:35 +08:00
										 |  |  | 	setCount := 2 | 
					
						
							| 
									
										
										
										
											2020-08-27 10:29:35 +08:00
										 |  |  | 	setDriveCount := 8 | 
					
						
							| 
									
										
										
										
											2018-07-19 11:17:35 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-01-17 04:08:02 +08:00
										 |  |  | 	format := newFormatErasureV3(setCount, setDriveCount) | 
					
						
							|  |  |  | 	format.Erasure.DistributionAlgo = formatErasureVersionV2DistributionAlgoV1 | 
					
						
							| 
									
										
										
										
											2020-06-13 11:04:01 +08:00
										 |  |  | 	formats := make([]*formatErasureV3, 16) | 
					
						
							| 
									
										
										
										
											2018-07-19 11:17:35 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	for i := 0; i < setCount; i++ { | 
					
						
							| 
									
										
										
										
											2020-08-27 10:29:35 +08:00
										 |  |  | 		for j := 0; j < setDriveCount; j++ { | 
					
						
							| 
									
										
										
										
											2019-11-21 20:24:51 +08:00
										 |  |  | 			newFormat := format.Clone() | 
					
						
							| 
									
										
										
										
											2020-06-13 11:04:01 +08:00
										 |  |  | 			newFormat.Erasure.This = format.Erasure.Sets[i][j] | 
					
						
							| 
									
										
										
										
											2020-08-27 10:29:35 +08:00
										 |  |  | 			formats[i*setDriveCount+j] = newFormat | 
					
						
							| 
									
										
										
										
											2018-07-19 11:17:35 +08:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Return a format from list of formats in quorum.
 | 
					
						
							| 
									
										
										
										
											2020-06-13 11:04:01 +08:00
										 |  |  | 	quorumFormat, err := getFormatErasureInQuorum(formats) | 
					
						
							| 
									
										
										
										
											2018-07-19 11:17:35 +08:00
										 |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		t.Fatal(err) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Check if the reference format and input formats are same.
 | 
					
						
							|  |  |  | 	var id string | 
					
						
							| 
									
										
										
										
											2020-06-13 11:04:01 +08:00
										 |  |  | 	if id, err = formatErasureGetDeploymentID(quorumFormat, formats); err != nil { | 
					
						
							| 
									
										
										
										
											2018-07-19 11:17:35 +08:00
										 |  |  | 		t.Fatal(err) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if id == "" { | 
					
						
							|  |  |  | 		t.Fatal("ID cannot be empty.") | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	formats[0] = nil | 
					
						
							| 
									
										
										
										
											2020-06-13 11:04:01 +08:00
										 |  |  | 	if id, err = formatErasureGetDeploymentID(quorumFormat, formats); err != nil { | 
					
						
							| 
									
										
										
										
											2018-07-19 11:17:35 +08:00
										 |  |  | 		t.Fatal(err) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if id == "" { | 
					
						
							|  |  |  | 		t.Fatal("ID cannot be empty.") | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-06-13 11:04:01 +08:00
										 |  |  | 	formats[1].Erasure.Sets[0][0] = "bad-uuid" | 
					
						
							|  |  |  | 	if id, err = formatErasureGetDeploymentID(quorumFormat, formats); err != nil { | 
					
						
							| 
									
										
										
										
											2018-07-19 11:17:35 +08:00
										 |  |  | 		t.Fatal(err) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if id == "" { | 
					
						
							|  |  |  | 		t.Fatal("ID cannot be empty.") | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	formats[2].ID = "bad-id" | 
					
						
							| 
									
										
										
										
											2020-08-04 09:17:48 +08:00
										 |  |  | 	if _, err = formatErasureGetDeploymentID(quorumFormat, formats); !errors.Is(err, errCorruptedFormat) { | 
					
						
							|  |  |  | 		t.Fatalf("Unexpect error %s", err) | 
					
						
							| 
									
										
										
										
											2018-07-19 11:17:35 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-02-16 09:45:57 +08:00
										 |  |  | // Initialize new format sets.
 | 
					
						
							|  |  |  | func TestNewFormatSets(t *testing.T) { | 
					
						
							|  |  |  | 	setCount := 2 | 
					
						
							| 
									
										
										
										
											2020-08-27 10:29:35 +08:00
										 |  |  | 	setDriveCount := 16 | 
					
						
							| 
									
										
										
										
											2016-09-11 00:54:22 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-01-17 04:08:02 +08:00
										 |  |  | 	format := newFormatErasureV3(setCount, setDriveCount) | 
					
						
							|  |  |  | 	format.Erasure.DistributionAlgo = formatErasureVersionV2DistributionAlgoV1 | 
					
						
							| 
									
										
										
										
											2020-06-13 11:04:01 +08:00
										 |  |  | 	formats := make([]*formatErasureV3, 32) | 
					
						
							| 
									
										
										
										
											2018-02-16 09:45:57 +08:00
										 |  |  | 	errs := make([]error, 32) | 
					
						
							| 
									
										
										
										
											2016-09-11 10:32:18 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-02-16 09:45:57 +08:00
										 |  |  | 	for i := 0; i < setCount; i++ { | 
					
						
							| 
									
										
										
										
											2020-08-27 10:29:35 +08:00
										 |  |  | 		for j := 0; j < setDriveCount; j++ { | 
					
						
							| 
									
										
										
										
											2019-11-21 20:24:51 +08:00
										 |  |  | 			newFormat := format.Clone() | 
					
						
							| 
									
										
										
										
											2020-06-13 11:04:01 +08:00
										 |  |  | 			newFormat.Erasure.This = format.Erasure.Sets[i][j] | 
					
						
							| 
									
										
										
										
											2020-08-27 10:29:35 +08:00
										 |  |  | 			formats[i*setDriveCount+j] = newFormat | 
					
						
							| 
									
										
										
										
											2016-09-11 00:54:22 +08:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-06-13 11:04:01 +08:00
										 |  |  | 	quorumFormat, err := getFormatErasureInQuorum(formats) | 
					
						
							| 
									
										
										
										
											2016-11-17 08:42:23 +08:00
										 |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		t.Fatal(err) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-02-16 09:45:57 +08:00
										 |  |  | 	// 16th disk is unformatted.
 | 
					
						
							|  |  |  | 	errs[15] = errUnformattedDisk | 
					
						
							| 
									
										
										
										
											2016-09-11 10:32:18 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-27 10:29:35 +08:00
										 |  |  | 	newFormats := newHealFormatSets(quorumFormat, setCount, setDriveCount, formats, errs) | 
					
						
							| 
									
										
										
										
											2018-02-16 09:45:57 +08:00
										 |  |  | 	if newFormats == nil { | 
					
						
							|  |  |  | 		t.Fatal("Unexpected failure") | 
					
						
							| 
									
										
										
										
											2016-09-11 00:54:22 +08:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2019-01-23 10:32:06 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	// Check if deployment IDs are preserved.
 | 
					
						
							|  |  |  | 	for i := range newFormats { | 
					
						
							|  |  |  | 		for j := range newFormats[i] { | 
					
						
							| 
									
										
										
										
											2020-10-27 01:29:29 +08:00
										 |  |  | 			if newFormats[i][j] == nil { | 
					
						
							|  |  |  | 				continue | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2019-01-23 10:32:06 +08:00
										 |  |  | 			if newFormats[i][j].ID != quorumFormat.ID { | 
					
						
							|  |  |  | 				t.Fatal("Deployment id in the new format is lost") | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2016-09-11 00:54:22 +08:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2019-09-28 07:47:12 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | func BenchmarkInitStorageDisks256(b *testing.B) { | 
					
						
							|  |  |  | 	benchmarkInitStorageDisksN(b, 256) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func BenchmarkInitStorageDisks1024(b *testing.B) { | 
					
						
							|  |  |  | 	benchmarkInitStorageDisksN(b, 1024) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func BenchmarkInitStorageDisks2048(b *testing.B) { | 
					
						
							|  |  |  | 	benchmarkInitStorageDisksN(b, 2048) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func BenchmarkInitStorageDisksMax(b *testing.B) { | 
					
						
							|  |  |  | 	benchmarkInitStorageDisksN(b, 32*204) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func benchmarkInitStorageDisksN(b *testing.B, nDisks int) { | 
					
						
							|  |  |  | 	b.ResetTimer() | 
					
						
							|  |  |  | 	b.ReportAllocs() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	fsDirs, err := getRandomDisks(nDisks) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		b.Fatal(err) | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2019-11-20 09:42:27 +08:00
										 |  |  | 	endpoints := mustGetNewEndpoints(fsDirs...) | 
					
						
							| 
									
										
										
										
											2019-09-28 07:47:12 +08:00
										 |  |  | 	b.RunParallel(func(pb *testing.PB) { | 
					
						
							|  |  |  | 		endpoints := endpoints | 
					
						
							|  |  |  | 		for pb.Next() { | 
					
						
							|  |  |  | 			initStorageDisksWithErrors(endpoints) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	}) | 
					
						
							|  |  |  | } |