xl: Move format detection inside xl objects. (#1515)

Fixes #1449
master
Harshavardhana 9 years ago committed by Anand Babu (AB) Periasamy
parent a20ccb1e83
commit 434423de89
  1. 23
      config.go
  2. 115
      format-config-v1.go
  3. 13
      globals.go
  4. 22
      routers.go
  5. 52
      xl-objects.go

@ -86,26 +86,3 @@ func getConfigFile() (string, error) {
}
return filepath.Join(configPath, globalMinioConfigFile), nil
}
// isFormatConfigFileExists - returns true if format config file exists.
func isFormatConfigFileExists() bool {
st, err := os.Stat(mustGetFormatConfigFile())
return (err == nil && st.Mode().IsRegular())
}
// mustGetFormatConfigFile must get format config file.
func mustGetFormatConfigFile() string {
configFile, err := getFormatConfigFile()
fatalIf(err, "Unable to get format config file.", nil)
return configFile
}
// getFormatConfigFile get format config file.
func getFormatConfigFile() (string, error) {
configPath, err := getConfigPath()
if err != nil {
return "", err
}
return filepath.Join(configPath, globalMinioFormatConfigFile), nil
}

@ -16,7 +16,10 @@
package main
import "github.com/minio/minio/pkg/quick"
import (
"encoding/json"
"fmt"
)
type fsFormat struct {
Version string `json:"version"`
@ -28,84 +31,72 @@ type xlFormat struct {
}
type formatConfigV1 struct {
// must have "Version" to "quick" to work
Version string `json:"version"`
Format string `json:"format"`
FS fsFormat `json:"fs,omitempty"`
XL xlFormat `json:"xl,omitempty"`
Version string `json:"version"`
Format string `json:"format"`
FS *fsFormat `json:"fs,omitempty"`
XL *xlFormat `json:"xl,omitempty"`
}
func (f formatConfigV1) Save() error {
configFile, err := getFormatConfigFile()
if err != nil {
return err
}
// FIXME: currently we don't check single exportPath which uses FS layer.
// initialize quick.
qc, err := quick.New(&f)
// loadFormatXL - load XL format.json.
func loadFormatXL(storage StorageAPI) (xl *xlFormat, err error) {
offset := int64(0)
r, err := storage.ReadFile(minioMetaBucket, formatConfigFile, offset)
if err != nil {
return err
return nil, err
}
// Save config file.
return qc.Save(configFile)
}
func (f *formatConfigV1) Load() error {
configFile, err := getFormatConfigFile()
decoder := json.NewDecoder(r)
formatXL := formatConfigV1{}
err = decoder.Decode(&formatXL)
if err != nil {
return err
return nil, err
}
if err = r.Close(); err != nil {
return nil, err
}
if formatXL.Version != "1" {
return nil, fmt.Errorf("Unsupported version of backend format [%s] found.", formatXL.Version)
}
if formatXL.Format != "xl" {
return nil, fmt.Errorf("Unsupported backend format [%s] found.", formatXL.Format)
}
return formatXL.XL, nil
}
f.Version = globalMinioConfigVersion
qc, err := quick.New(f)
// checkFormat - validates if format.json file exists.
func checkFormat(storage StorageAPI) error {
_, err := storage.StatFile(minioMetaBucket, formatConfigFile)
if err != nil {
return err
}
if err := qc.Load(configFile); err != nil {
return err
}
return nil
}
// saveFormatFS - save FS format configuration
func saveFormatFS(fs fsFormat) error {
config := formatConfigV1{Version: globalMinioConfigVersion, Format: "fs", FS: fs}
return config.Save()
}
// saveFormatXL - save XL format configuration
func saveFormatXL(xl xlFormat) error {
config := formatConfigV1{Version: globalMinioConfigVersion, Format: "xl", XL: xl}
return config.Save()
}
// getSavedFormatConfig - get saved format configuration
func getSavedFormatConfig() (formatConfigV1, error) {
config := formatConfigV1{Version: globalMinioConfigVersion}
if err := config.Load(); err != nil {
return config, err
}
return config, nil
}
// getFormatFS - get saved FS format configuration
func getFormatFS() (fsFormat, error) {
config, err := getSavedFormatConfig()
func saveFormatXL(storage StorageAPI, xl *xlFormat) error {
w, err := storage.CreateFile(minioMetaBucket, formatConfigFile)
if err != nil {
return fsFormat{}, err
return err
}
return config.FS, nil
}
// getFormatXL - get saved XL format configuration
func getFormatXL() (xlFormat, error) {
config, err := getSavedFormatConfig()
formatXL := formatConfigV1{
Version: "1",
Format: "xl",
XL: xl,
}
encoder := json.NewEncoder(w)
err = encoder.Encode(&formatXL)
if err != nil {
return xlFormat{}, err
if clErr := safeCloseAndRemove(w); clErr != nil {
return clErr
}
return err
}
if err = w.Close(); err != nil {
if clErr := safeCloseAndRemove(w); clErr != nil {
return clErr
}
return err
}
return config.XL, nil
return nil
}

@ -29,13 +29,12 @@ const (
// minio configuration related constants.
const (
globalMinioConfigVersion = "4"
globalMinioConfigDir = ".minio"
globalMinioCertsDir = ".minio/certs"
globalMinioCertFile = "public.crt"
globalMinioKeyFile = "private.key"
globalMinioConfigFile = "config.json"
globalMinioFormatConfigFile = "format.json"
globalMinioConfigVersion = "4"
globalMinioConfigDir = ".minio"
globalMinioCertsDir = ".minio/certs"
globalMinioCertFile = "public.crt"
globalMinioKeyFile = "private.key"
globalMinioConfigFile = "config.json"
)
var (

@ -17,9 +17,7 @@
package main
import (
"fmt"
"net/http"
"reflect"
router "github.com/gorilla/mux"
)
@ -38,26 +36,6 @@ func newObjectLayer(exportPaths ...string) (ObjectLayer, error) {
// configureServer handler returns final handler for the http server.
func configureServerHandler(srvCmdConfig serverCmdConfig) http.Handler {
// FIXME: currently we don't check single exportPath which uses FS layer.
if len(srvCmdConfig.exportPaths) > 1 {
if isFormatConfigFileExists() {
format, err := getFormatXL()
if err != nil {
fatalIf(err, "Failed to read format.json", nil)
}
if !reflect.DeepEqual(format.Disks, srvCmdConfig.exportPaths) {
err = fmt.Errorf("Number of export paths from command-line did not match the backend configuration. Backend is configured with [%s] exports.", format.Disks)
fatalIf(err, "", nil)
}
} else {
// First run: save disk configuration
if err := saveFormatXL(xlFormat{Version: "1", Disks: srvCmdConfig.exportPaths}); err != nil {
fatalIf(err, "Unable to save 'format.json'", nil)
}
}
}
objAPI, err := newObjectLayer(srvCmdConfig.exportPaths...)
fatalIf(err, "Initializing object layer failed.", nil)

@ -18,6 +18,7 @@ package main
import (
"encoding/json"
"fmt"
"io"
"path/filepath"
"strings"
@ -29,6 +30,7 @@ import (
const (
multipartSuffix = ".minio.multipart"
multipartMetaFile = "00000" + multipartSuffix
formatConfigFile = "format.json"
)
// xlObjects - Implements fs object layer.
@ -43,11 +45,37 @@ func isLeafDirectory(disk StorageAPI, volume, leafPath string) bool {
return err == nil
}
// isValidFormat - validates input arguments with backend 'format.json'
func isValidFormat(storage StorageAPI, exportPaths ...string) bool {
// Load saved XL format.json and validate.
xl, err := loadFormatXL(storage)
if err != nil {
log.Errorf("loadFormatXL failed with %s", err)
return false
}
if xl.Version != "1" {
log.Errorf("Unsupported XL backend format found [%s]", xl.Version)
return false
}
if len(exportPaths) != len(xl.Disks) {
log.Errorf("Number of disks %d passed at the command-line did not match the backend format %d", len(exportPaths), len(xl.Disks))
return false
}
for index, disk := range xl.Disks {
if exportPaths[index] != disk {
log.Errorf("Invalid order of disks detected %s. Required order is %s.", exportPaths, xl.Disks)
return false
}
}
return true
}
// FIXME: constructor should return a pointer.
// newXLObjects - initialize new xl object layer.
func newXLObjects(exportPaths ...string) (ObjectLayer, error) {
storage, err := newXL(exportPaths...)
if err != nil {
log.Errorf("newXL failed with %s", err)
return nil, err
}
@ -55,6 +83,30 @@ func newXLObjects(exportPaths ...string) (ObjectLayer, error) {
// cleaning up tmp files etc.
initObjectLayer(storage)
err = checkFormat(storage)
if err != nil {
if err == errFileNotFound {
// Save new XL format.
errSave := saveFormatXL(storage, &xlFormat{
Version: "1",
Disks: exportPaths,
})
if errSave != nil {
log.Errorf("saveFormatXL failed with %s", errSave)
return nil, errSave
}
} else {
log.Errorf("Unable to check backend format %s", err)
return nil, err
}
}
// Validate if format exists and input arguments are validated
// with backend format.
if !isValidFormat(storage, exportPaths...) {
return nil, fmt.Errorf("Command-line arguments %s is not valid.", exportPaths)
}
// Return successfully initialized object layer.
return xlObjects{
storage: storage,

Loading…
Cancel
Save