minio/pkg/server/server.go
Harshavardhana 8f61d6b6be Move memory code out, add it as layer on top of existing donut code
Just like how http.Handlers can be overlayed on top of each other
with each implementing ServeHTTP().

drivers.Driver can be overlayed on top of each other in similar manner
which would implement the drivers.Driver interface.

   API <----> cache <----> donut <----> donut(format)
2015-06-30 10:09:12 -07:00

130 lines
3.6 KiB
Go

/*
* Minimalist Object Storage, (C) 2014 Minio, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package server
import (
"errors"
"fmt"
"reflect"
"time"
"github.com/minio/minio/pkg/api"
"github.com/minio/minio/pkg/api/web"
"github.com/minio/minio/pkg/iodine"
"github.com/minio/minio/pkg/server/httpserver"
"github.com/minio/minio/pkg/storage/drivers"
"github.com/minio/minio/pkg/storage/drivers/cache"
"github.com/minio/minio/pkg/storage/drivers/donut"
"github.com/minio/minio/pkg/utils/log"
)
// WebFactory is used to build web cli server
type WebFactory struct {
httpserver.Config
}
// GetStartServerFunc builds web cli server
func (f WebFactory) GetStartServerFunc() StartServerFunc {
return func() (chan<- string, <-chan error) {
ctrl, status, _ := httpserver.Start(web.HTTPHandler(), f.Config)
return ctrl, status
}
}
// Factory is used to build api server
type Factory struct {
httpserver.Config
Paths []string
MaxMemory uint64
Expiration time.Duration
}
// GetStartServerFunc Factory builds api server
func (f Factory) GetStartServerFunc() StartServerFunc {
return func() (chan<- string, <-chan error) {
conf := api.Config{RateLimit: f.RateLimit}
var driver drivers.Driver
var err error
if len(f.Paths) != 0 {
driver, err = donut.NewDriver(f.Paths)
if err != nil {
log.Fatalln(err)
}
driver, err = cache.NewDriver(f.MaxMemory, f.Expiration, driver)
if err != nil {
log.Fatalln(err)
}
}
conf.SetDriver(driver)
ctrl, status, _ := httpserver.Start(api.HTTPHandler(conf), f.Config)
return ctrl, status
}
}
// StartServerFunc describes a function that can be used to start a server with StartMinio
type StartServerFunc func() (chan<- string, <-chan error)
// StartMinio starts minio server
func StartMinio(servers []StartServerFunc) {
var ctrlChannels []chan<- string
var errChannels []<-chan error
for _, server := range servers {
ctrlChannel, errChannel := server()
ctrlChannels = append(ctrlChannels, ctrlChannel)
errChannels = append(errChannels, errChannel)
}
cases := createSelectCases(errChannels)
for len(cases) > 0 {
chosen, value, recvOk := reflect.Select(cases)
switch recvOk {
case true:
// Status Message Received
switch true {
case value.Interface() != nil:
// For any error received cleanup all existing channels and fail
for _, ch := range ctrlChannels {
close(ch)
}
msg := fmt.Sprintf("%q", value.Interface())
log.Fatal(iodine.New(errors.New(msg), nil))
}
case false:
// Channel closed, remove from list
var aliveStatusChans []<-chan error
for i, ch := range errChannels {
if i != chosen {
aliveStatusChans = append(aliveStatusChans, ch)
}
}
// create new select cases without defunct channel
errChannels = aliveStatusChans
cases = createSelectCases(errChannels)
}
}
}
func createSelectCases(channels []<-chan error) []reflect.SelectCase {
cases := make([]reflect.SelectCase, len(channels))
for i, ch := range channels {
cases[i] = reflect.SelectCase{
Dir: reflect.SelectRecv,
Chan: reflect.ValueOf(ch),
}
}
return cases
}