func (e *Engine) Open() error {
	return e.cluster.Open(e.driver)
}
Open will open all database nodes in cluster
package shorm
import (
	"encoding/json"
	"encoding/xml"
	"fmt"
	"log"
	"os"
	"strings"
	"sync"
)
var sqlGenDict = map[string]SqlGenerator{
	"mssql":    NewMSSqlGenerator(),
	"mysql":    newBaseGenerator(),
	"mymysql":  newBaseGenerator(),
	"postgres": newBaseGenerator(),
	"sqlite":   newBaseGenerator(),
}
type emptyLogger struct {
}
func (e *emptyLogger) Write(b []byte) (n int, err error) {
	return
}
type Engine struct {
	cluster *Cluster
	Logger  *log.Logger
	pool    *sync.Pool
	driver  string
}
func NewEngine(driver string, cluster *Cluster) *Engine {
	e := &Engine{
		cluster: cluster,
		pool:    &sync.Pool{},
		driver:  driver,
		Logger:  log.New(&emptyLogger{}, "", 0),
	}
	e.cluster.RealGroups = len(e.cluster.Groups)
	e.pool.New = func() interface{} { return &Session{} }
	return e
}
func NewEngineV2(driver, connstr string) *Engine {
	cluster := &Cluster{TotalGroups: 1}
	cluster.Groups = append(cluster.Groups, &DbGroup{
		Nodes: []*DbNode{
			{
				Name:    "master",
				ConnStr: connstr,
				Type:    NodeType_Master,
			}},
	})
	return NewEngine(driver, cluster)
}
type clusterConfig struct {
	XMLName xml.Name `json:"-" xml:"ClusterConfig"`
	Driver  string   `json:"driver"`
	Cluster *Cluster `json:"cluster"`
}
func NewEngineFromConfig(config string) (*Engine, error) {
	var cluster clusterConfig
	file, err := os.Open(config)
	if err != nil {
		return nil, err
	}
	defer file.Close()
	config = strings.ToLower(config)
	if strings.HasSuffix(config, ".json") {
		d := json.NewDecoder(file)
		if err = d.Decode(&cluster); err != nil {
			return nil, err
		}
	} else if strings.HasSuffix(config, ".xml") {
		d := xml.NewDecoder(file)
		if err = d.Decode(&cluster); err != nil {
			return nil, err
		}
	} else {
		return nil, fmt.Errorf("the file format of config file is not be supported.")
	}
	return NewEngine(cluster.Driver, cluster.Cluster), nil
}
func (e *Engine) BeginTrans(shardValue int64) (*DbTrans, error) {
	return newDbTrans(e, shardValue)
}
func (e *Engine) StartSession() *Session {
	s := e.pool.Get().(*Session)
	s.logger = e.Logger
	s.sqlGen = sqlGenDict[e.driver]
	s.engine = e
	return s
}
func (e *Engine) EndSession(s *Session) {
	s.reset()
	e.pool.Put(s)
}