// newXLObjects - initialize new xl object layer. func newXLObjects(storageDisks []StorageAPI) (ObjectLayer, error) { if storageDisks == nil { return nil, errInvalidArgument } readQuorum := len(storageDisks) / 2 writeQuorum := len(storageDisks)/2 + 1 // Load saved XL format.json and validate. newStorageDisks, err := loadFormatXL(storageDisks, readQuorum) if err != nil { return nil, fmt.Errorf("Unable to recognize backend format, %s", err) } // Calculate data and parity blocks. dataBlocks, parityBlocks := len(newStorageDisks)/2, len(newStorageDisks)/2 // Initialize object cache. objCache := objcache.New(globalMaxCacheSize, globalCacheExpiry) // Initialize list pool. listPool := newTreeWalkPool(globalLookupTimeout) // Check if object cache is disabled. objCacheDisabled := strings.EqualFold(os.Getenv("_MINIO_CACHE"), "off") // Initialize xl objects. xl := &xlObjects{ mutex: &sync.Mutex{}, storageDisks: newStorageDisks, dataBlocks: dataBlocks, parityBlocks: parityBlocks, listPool: listPool, objCache: objCache, objCacheEnabled: !objCacheDisabled, } // Initialize meta volume, if volume already exists ignores it. if err = initMetaVolume(storageDisks); err != nil { return nil, fmt.Errorf("Unable to initialize '.minio.sys' meta volume, %s", err) } // Figure out read and write quorum based on number of storage disks. // READ and WRITE quorum is always set to (N/2) number of disks. xl.readQuorum = readQuorum xl.writeQuorum = writeQuorum // Do a quick heal on the buckets themselves for any discrepancies. if err := quickHeal(xl.storageDisks, xl.writeQuorum, xl.readQuorum); err != nil { return xl, err } // Return successfully initialized object layer. return xl, nil }
// newXLObjects - initialize new xl object layer. func newXLObjects(disks, ignoredDisks []string) (ObjectLayer, error) { if disks == nil { return nil, errInvalidArgument } disksSet := set.NewStringSet() if len(ignoredDisks) > 0 { disksSet = set.CreateStringSet(ignoredDisks...) } // Bootstrap disks. storageDisks := make([]StorageAPI, len(disks)) for index, disk := range disks { // Check if disk is ignored. if disksSet.Contains(disk) { storageDisks[index] = nil continue } var err error // Intentionally ignore disk not found errors. XL is designed // to handle these errors internally. storageDisks[index], err = newStorageAPI(disk) if err != nil && err != errDiskNotFound { switch diskType := storageDisks[index].(type) { case networkStorage: diskType.rpcClient.Close() } return nil, err } } // Fix format files in case of fresh or corrupted disks repairDiskMetadata(storageDisks) // Runs house keeping code, like t, cleaning up tmp files etc. if err := xlHouseKeeping(storageDisks); err != nil { return nil, err } // Load saved XL format.json and validate. newPosixDisks, err := loadFormatXL(storageDisks) if err != nil { // errCorruptedDisk - healing failed return nil, fmt.Errorf("Unable to recognize backend format, %s", err) } // Calculate data and parity blocks. dataBlocks, parityBlocks := len(newPosixDisks)/2, len(newPosixDisks)/2 // Initialize object cache. objCache := objcache.New(globalMaxCacheSize, globalCacheExpiry) // Initialize list pool. listPool := newTreeWalkPool(globalLookupTimeout) // Initialize xl objects. xl := xlObjects{ storageDisks: newPosixDisks, dataBlocks: dataBlocks, parityBlocks: parityBlocks, listPool: listPool, objCache: objCache, objCacheEnabled: globalMaxCacheSize > 0, } // Figure out read and write quorum based on number of storage disks. // READ and WRITE quorum is always set to (N/2) number of disks. xl.readQuorum = len(xl.storageDisks) / 2 xl.writeQuorum = len(xl.storageDisks)/2 + 1 // Return successfully initialized object layer. return xl, nil }