Example #1
0
// 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
}
Example #2
0
// 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
}