Example #1
0
// InitConfig init configuration file.
func InitConfig() error {
	gconf := goconf.New()
	if err := gconf.Parse(confFile); err != nil {
		glog.Errorf("goconf.Parse(\"%s\") error(%v)", confFile, err)
		return err
	}
	// Default config
	Conf = &Config{
		HttpBind:             []string{"localhost:80"},
		AdminBind:            []string{"localhost:81"},
		MaxProc:              runtime.NumCPU(),
		PprofBind:            []string{"localhost:8190"},
		User:                 "******",
		PidFile:              "/tmp/gopush-cluster-web.pid",
		Dir:                  "./",
		Router:               "",
		QQWryPath:            "/tmp/QQWry.dat",
		ZookeeperAddr:        []string{":2181"},
		ZookeeperTimeout:     30 * time.Second,
		ZookeeperCometPath:   "/gopush-cluster-comet",
		ZookeeperMessagePath: "/gopush-cluster-message",
		RPCRetry:             3 * time.Second,
		RPCPing:              1 * time.Second,
	}
	if err := gconf.Unmarshal(Conf); err != nil {
		glog.Errorf("goconf.Unmarshall() error(%v)", err)
		return err
	}
	return nil
}
Example #2
0
// InitConfig init configuration file.
func InitConfig() error {
	gconf := goconf.New()
	if err := gconf.Parse(confFile); err != nil {
		return err
	}
	// Default config
	Conf = &Config{
		HttpBind:             []string{"localhost:80"},
		AdminBind:            []string{"localhost:81"},
		HttpServerTimeout:    10 * time.Second,
		MaxProc:              runtime.NumCPU(),
		PprofBind:            []string{"localhost:8190"},
		User:                 "******",
		PidFile:              "/tmp/gopush-cluster-web.pid",
		Dir:                  "./",
		Log:                  "./log/xml",
		ZookeeperAddr:        []string{":2181"},
		ZookeeperTimeout:     30 * time.Second,
		ZookeeperCometPath:   "/gopush-cluster-comet",
		ZookeeperMessagePath: "/gopush-cluster-message",
		ZookeeperMigratePath: "/gopush-migrate-lock",
		RPCRetry:             3 * time.Second,
		RPCPing:              1 * time.Second,
	}
	if err := gconf.Unmarshal(Conf); err != nil {
		return err
	}
	return nil
}
Example #3
0
// InitConfig init the global config.
func InitConfig() (err error) {
	Conf = NewConfig()
	gconf = goconf.New()
	if err = gconf.Parse(confFile); err != nil {
		return err
	}
	if err = gconf.Unmarshal(Conf); err != nil {
		return err
	}
	var serverIDi int64
	for _, serverID := range gconf.Get("comets").Keys() {
		addr, err := gconf.Get("comets").String(serverID)
		if err != nil {
			return err
		}
		serverIDi, err = strconv.ParseInt(serverID, 10, 32)
		if err != nil {
			return err
		}

		Conf.Comets[int32(serverIDi)] = addr
	}
	for _, serverID := range gconf.Get("router.addrs").Keys() {
		addr, err := gconf.Get("router.addrs").String(serverID)
		if err != nil {
			return err
		}
		Conf.RouterRPCAddrs[serverID] = addr
	}
	return nil
}
Example #4
0
// Initialize config
func NewConfig(file string) (*Config, error) {
	gconf := goconf.New()
	if err := gconf.Parse(file); err != nil {
		return nil, err
	}

	// Default config
	conf := &Config{
		Addr:        ":80",
		AdminAddr:   ":81",
		MaxProc:     runtime.NumCPU(),
		PprofBind:   []string{"localhost:8190"},
		User:        "******",
		PidFile:     "/tmp/gopush-cluster-web.pid",
		Dir:         "./",
		LogPath:     "./web.log",
		LogLevel:    "DEBUG",
		ZKAddr:      []string{":2181"},
		ZKTimeout:   30 * time.Second,
		ZKCometPath: "/gopush-cluster",
		ZKPIDPath:   "/gopush-pid",
		MsgAddr:     ":8070",
		MsgPing:     1 * time.Second,
		MsgRetry:    3 * time.Second,
	}

	if err := gconf.Unmarshal(conf); err != nil {
		return nil, err
	}

	return conf, nil
}
Example #5
0
// Initialize config
func NewConfig(file string) (*Config, error) {
	gconf := goconf.New()
	if err := gconf.Parse(file); err != nil {
		return nil, err
	}

	// Default config
	conf := &Config{
		Addr:        ":80",
		AdminAddr:   ":81",
		MaxProc:     runtime.NumCPU(),
		LogPath:     "./web.log",
		LogLevel:    "DEBUG",
		ZKAddr:      ":2181",
		ZKTimeout:   8 * time.Hour,
		ZKCometPath: "/gopush-cluster",
		ZKPIDPath:   "/gopush-pid",
		MsgAddr:     ":8070",
		MsgPing:     1 * time.Second,
		MsgRetry:    3 * time.Second,
	}

	if err := gconf.Unmarshal(conf); err != nil {
		return nil, err
	}

	return conf, nil
}
Example #6
0
// NewConfig parse config file into Config.
func InitConfig() error {
	gconf := goconf.New()
	if err := gconf.Parse(confFile); err != nil {
		glog.Errorf("goconf.Parse(\"%s\") error(%v)", confFile, err)
		return err
	}
	Conf = &Config{
		// base
		RPCBind:   []string{"localhost:8070"},
		User:      "******",
		PidFile:   "/tmp/gopush-cluster-message.pid",
		Dir:       "./",
		MaxProc:   runtime.NumCPU(),
		PprofBind: []string{"localhost:8170"},
		// storage
		StorageType: "redis",
		// redis
		RedisIdleTimeout: 28800 * time.Second,
		RedisMaxIdle:     50,
		RedisMaxActive:   1000,
		RedisMaxStore:    20,
		RedisSource:      make(map[string]string),
		// mysql
		MySQLSource: make(map[string]string),
		MySQLClean:  1 * time.Hour,
		// zookeeper
		ZookeeperAddr:    []string{"localhost:2181"},
		ZookeeperTimeout: 30 * time.Second,
		ZookeeperPath:    "/gopush-cluster-message",
	}
	if err := gconf.Unmarshal(Conf); err != nil {
		glog.Errorf("goconf.Unmarshal() error(%v)", err)
		return err
	}
	// redis section
	redisAddrsSec := gconf.Get("redis.source")
	if redisAddrsSec != nil {
		for _, key := range redisAddrsSec.Keys() {
			addr, err := redisAddrsSec.String(key)
			if err != nil {
				return fmt.Errorf("config section: \"redis.addrs\" key: \"%s\" error(%v)", key, err)
			}
			Conf.RedisSource[key] = addr
		}
	}
	// mysql section
	dbSource := gconf.Get("mysql.source")
	if dbSource != nil {
		for _, key := range dbSource.Keys() {
			source, err := dbSource.String(key)
			if err != nil {
				return fmt.Errorf("config section: \"mysql.source\" key: \"%s\" error(%v)", key, err)
			}
			Conf.MySQLSource[key] = source
		}
	}
	return nil
}
Example #7
0
// Initialize config
func NewConfig(fileName string) (*Config, error) {
	gconf := goconf.New()
	if err := gconf.Parse(fileName); err != nil {
		Log.Error("goconf.Parse(\"%s\") error(%v)", fileName, err)
		return nil, err
	}

	conf := &Config{
		Addr:             ":8070",
		PKey:             "gopushpkey",
		User:             "******",
		PidFile:          "/tmp/gopush-cluster-message.pid",
		Dir:              "./",
		MaxProc:          runtime.NumCPU(),
		LogFile:          "./message.log",
		LogLevel:         "DEBUG",
		PprofBind:        []string{"localhost:8170"},
		StorageType:      "redis",
		RedisIdleTimeout: 28800 * time.Second,
		RedisMaxIdle:     50,
		RedisMaxActive:   1000,
		RedisMaxStore:    20,
		RedisAddrs:       make(map[string]string),
		MYSQLDelLoopTime: 1 * time.Hour,
		DBSource:         make(map[string]string),
	}
	if err := gconf.Unmarshal(conf); err != nil {
		Log.Error("goconf.Unmarshal() error(%v)", err)
		return nil, err
	}

	//Load redis addresses
	redisAddrsSec := gconf.Get("redis.addr")
	if redisAddrsSec != nil {
		for _, key := range redisAddrsSec.Keys() {
			addr, err := redisAddrsSec.String(key)
			if err != nil {
				return nil, fmt.Errorf("config section:\"redis.addrs\" key:\"%s\" error(%v)", key, err)
			}
			conf.RedisAddrs[key] = addr
		}
	}

	//Load mysql sources
	dbSource := gconf.Get("mysql.source")
	if dbSource != nil {
		for _, key := range redisAddrsSec.Keys() {
			source, err := redisAddrsSec.String(key)
			if err != nil {
				return nil, fmt.Errorf("config section:\"mysql.source\" key:\"%s\" error(%v)", key, err)
			}
			conf.DBSource[key] = source
		}
	}

	return conf, nil
}
Example #8
0
// InitConfig init the global config.
func InitConfig() (err error) {
	Conf = NewConfig()
	gconf = goconf.New()
	if err = gconf.Parse(confFile); err != nil {
		return err
	}
	if err := gconf.Unmarshal(Conf); err != nil {
		return err
	}
	return nil
}
Example #9
0
func parseArgs() *goconf.Config {
	flag.Parse()
	args := flag.Args()
	if len(args) <= 0 {
		usage(errors.New("not found config file"))
	}
	conf := goconf.New()
	if err := conf.Parse(args[0]); err != nil {
		usage(err)
	}
	return conf
}
Example #10
0
// NewConfig new a config.
func NewConfig(file string) (c *Config, err error) {
	var gconf = goconf.New()
	c = &Config{}
	if err = gconf.Parse(file); err != nil {
		return
	}
	if err = gconf.Unmarshal(c); err != nil {
		return
	}
	c.setDefault()
	return
}
Example #11
0
// InitConfig init the global config.
func InitConfig() (err error) {

	defer func() {
		Conf.CheckPointThreshold = power2(Conf.CheckPointThreshold)
	}()

	Conf = NewConfig()
	gconf = goconf.New()
	if err = gconf.Parse(confFile); err != nil {
		return err
	}
	if err := gconf.Unmarshal(Conf); err != nil {
		return err
	}
	return nil
}
Example #12
0
func InitConfig(configFile string) *Config {
	conf := goconf.New()

	if err := conf.Parse(configFile); err != nil {
		panic(err)
	}

	myConfig := &Config{}

	if err := conf.Unmarshal(myConfig); err != nil {
		panic(err)
	}

	fmt.Printf("config is: %#v\n", myConfig)
	return myConfig
}
Example #13
0
// InitConfig init configuration file.
func InitConfig() error {

	gconf := goconf.New()
	if err := gconf.Parse(confFile); err != nil {
		fmt.Println("confFile", confFile)
		logger.Errorf("goconf.Parse(\"%s\") error(%v)", confFile, err)
		return err
	}
	Conf = &Config{}
	if err := gconf.Unmarshal(Conf); err != nil {
		logger.Errorf("goconf.Unmarshall() error(%v)", err)
		return err
	}

	return nil
}
Example #14
0
// initConfig parse config file into Config.
func initConfig() error {
	gconf = goconf.New()
	if err := gconf.Parse(confFile); err != nil {
		return err
	}
	conf = &Config{
		// base
		Log:    "./log/xml",
		ZK:     []string{},
		ZKPath: "/redis-cluster/service_name",
	}
	if err := gconf.Unmarshal(conf); err != nil {
		return err
	}
	return nil
}
Example #15
0
// InitConfig get a new Config struct.
func InitConfig() error {
	Conf = &Config{
		// base
		User:          "******",
		PidFile:       "/tmp/gopush-cluster-comet.pid",
		Dir:           "./",
		MaxProc:       runtime.NumCPU(),
		WebsocketBind: []string{"localhost:6968"},
		TCPBind:       []string{"localhost:6969"},
		RPCBind:       []string{"localhost:6970"},
		PprofBind:     []string{"localhost:6971"},
		StatBind:      []string{"localhost:6972"},
		KetamaBase:    255,
		// zookeeper
		ZookeeperAddr:        []string{"localhost:2181"},
		ZookeeperTimeout:     30 * time.Second,
		ZookeeperCometPath:   "/gopush-cluster-comet",
		ZookeeperCometNode:   "node1",
		ZookeeperCometWeight: "1",
		ZookeeperMessagePath: "/gopush-cluster-message",
		// rpc
		RPCPing:  1 * time.Second,
		RPCRetry: 1 * time.Second,
		// channel
		SndbufSize:              2048,
		RcvbufSize:              256,
		Proto:                   []string{"tcp", "websocket"},
		BufioInstance:           runtime.NumCPU(),
		BufioNum:                128,
		TCPKeepalive:            false,
		TokenExpire:             30 * 24 * time.Hour,
		MaxSubscriberPerChannel: 64,
		ChannelBucket:           runtime.NumCPU(),
		Auth:                    false,
		MsgBufNum:               30,
	}
	c := goconf.New()
	if err := c.Parse(confFile); err != nil {
		glog.Errorf("goconf.Parse(\"%s\") error(%v)", confFile, err)
		return err
	}
	if err := c.Unmarshal(Conf); err != nil {
		glog.Errorf("goconf.Unmarshall() error(%v)", err)
		return err
	}
	return nil
}
Example #16
0
func NewConfig(confFile string) *Config {
	temp := &ConfigTemp{}

	conf := goconf.New()
	if err := conf.Parse(confFile); err != nil {
		glog.Error(err.Error())
		return temp.Parse()
	}

	// temp := &ConfigTemp{}
	if err := conf.Unmarshal(temp); err != nil {
		glog.Error(err.Error())
		return temp.Parse()
	}

	return temp.Parse()
}
Example #17
0
// InitConfig get a new Config struct.
func InitConfig(file string) (*Config, error) {
	cf := &Config{
		// base
		User:          "******",
		PidFile:       "/tmp/gopush-cluster-comet.pid",
		Dir:           "./",
		MaxProc:       runtime.NumCPU(),
		LogFile:       "./comet.log",
		LogLevel:      "ERROR",
		WebsocketBind: []string{"localhost:6968"},
		TCPBind:       []string{"localhost:6969"},
		RPCBind:       []string{"localhost:6970"},
		PprofBind:     []string{"localhost:6971"},
		StatBind:      []string{"localhost:6972"},
		// zookeeper
		ZookeeperAddr:    []string{"localhost:2181"},
		ZookeeperTimeout: 30 * time.Second,
		ZookeeperPath:    "/gopush-cluster",
		ZookeeperNode:    "node1",
		// rpc
		RPCMessageAddr: "localhost:6972",
		RPCPing:        1 * time.Second,
		RPCRetry:       1 * time.Second,
		// channel
		SndbufSize:              2048,
		RcvbufSize:              256,
		Proto:                   []string{"tcp", "websocket"},
		BufioInstance:           runtime.NumCPU(),
		BufioNum:                128,
		TCPKeepalive:            false,
		TokenExpire:             30 * 24 * time.Hour,
		MaxSubscriberPerChannel: 64,
		ChannelBucket:           runtime.NumCPU(),
		Auth:                    false,
	}
	c := goconf.New()
	if err := c.Parse(file); err != nil {
		Log.Error("goconf.Parse(\"%s\") error(%v)", file, err)
		return nil, err
	}
	if err := c.Unmarshal(cf); err != nil {
		Log.Error("goconf.Unmarshall() error(%v)", err)
		return nil, err
	}
	return cf, nil
}
Example #18
0
// InitConfig init the global config.
func InitConfig() (err error) {
	Conf = NewConfig()
	gconf = goconf.New()
	if err = gconf.Parse(confFile); err != nil {
		return err
	}
	if err := gconf.Unmarshal(Conf); err != nil {
		return err
	}
	for _, serverID := range gconf.Get("router.addrs").Keys() {
		addr, err := gconf.Get("router.addrs").String(serverID)
		if err != nil {
			return err
		}
		Conf.RouterRPCAddrs[serverID] = addr
	}
	return nil
}
Example #19
0
// InitConfig get a new Config struct.
func InitConfig(file string) (*Config, error) {
	cf := &Config{
		// base
		Addr:      "localhost:6969",
		Key:       "Terry-Mao",
		Heartbeat: 30,
	}
	c := goconf.New()
	if err := c.Parse(file); err != nil {
		glog.Errorf("goconf.Parse(\"%s\") failed (%s)", file, err.Error())
		return nil, err
	}
	if err := c.Unmarshal(cf); err != nil {
		glog.Errorf("goconf.Unmarshal() failed (%s)", err.Error())
		return nil, err
	}
	return cf, nil
}
Example #20
0
// InitConfig init configuration file.
func InitConfig() error {
	gconf := goconf.New()
	if err := gconf.Parse(confFile); err != nil {
		logger.Errorf("goconf.Parse(\"%s\") error(%v)", confFile, err)
		return err
	}
	// Default config
	Conf = &Config{
		HttpBind:             []string{"localhost:80"},
		AdminBind:            []string{"localhost:81"},
		MaxProc:              runtime.NumCPU(),
		PprofBind:            []string{"localhost:8190"},
		User:                 "******",
		PidFile:              "/tmp/gopush-cluster-web.pid",
		Dir:                  "./",
		Router:               "",
		QQWryPath:            "/tmp/QQWry.dat",
		ZookeeperAddr:        []string{":2181"},
		ZookeeperTimeout:     30 * time.Second,
		ZookeeperCometPath:   "/gopush-cluster-comet",
		ZookeeperMessagePath: "/gopush-cluster-message",
		RPCRetry:             3 * time.Second,
		RPCPing:              1 * time.Second,
		RedisSource:          make(map[string]string),
	}

	if err := gconf.Unmarshal(Conf); err != nil {
		logger.Errorf("goconf.Unmarshall() error(%v)", err)
		return err
	}

	redisAddrsSec := gconf.Get("redis.source")
	if redisAddrsSec != nil {
		for _, key := range redisAddrsSec.Keys() {
			addr, err := redisAddrsSec.String(key)
			if err != nil {
				return fmt.Errorf("config section: \"redis.addrs\" key: \"%s\" error(%v)", key, err)
			}
			Conf.RedisSource[key] = addr
		}
	}
	return nil
}
Example #21
0
// InitConfig get a new Config struct.
func InitConfig(file string) (*Config, error) {
	cf := &Config{
		// base
		LogFile:   "./comet-test.log",
		LogLevel:  "ERROR",
		Addr:      "localhost:6969",
		Key:       "Terry-Mao",
		Heartbeat: 30,
	}
	c := goconf.New()
	if err := c.Parse(file); err != nil {
		Log.Error("goconf.Parse(\"%s\") failed (%s)", file, err.Error())
		return nil, err
	}
	if err := c.Unmarshal(cf); err != nil {
		Log.Error("goconf.Unmarshal() failed (%s)", err.Error())
		return nil, err
	}
	return cf, nil
}
Example #22
0
// initConfig parse config file into Config.
func initConfig() error {
	gconf = goconf.New()
	if err := gconf.Parse(confFile); err != nil {
		return err
	}
	conf = &Config{
		// base
		Log:      "./log/xml",
		Master:   "mymaster",
		Sentinel: []string{},
		ZK:       []string{},
		ZKPath:   "/redis-cluster/service_name",
		Node:     "node1",
		Weight:   100,
		TpYml:    "./twemproxy.yml",
	}
	if err := gconf.Unmarshal(conf); err != nil {
		return err
	}
	return nil
}
Example #23
0
// Initialize config
func NewConfig(fileName string) (*Config, error) {
	gconf := goconf.New()
	if err := gconf.Parse(fileName); err != nil {
		Log.Error("goconf.Parse(\"%s\") error(%v)", fileName, err)
		return nil, err
	}

	conf := &Config{
		Addr:             ":8070",
		PKey:             "gopushpkey",
		User:             "******",
		PidFile:          "/tmp/gopush-cluster-message.pid",
		Dir:              "./",
		MaxProc:          runtime.NumCPU(),
		LogFile:          "./message.log",
		LogLevel:         "DEBUG",
		RedisIdleTimeout: 28800 * time.Second,
		RedisMaxIdle:     50,
		RedisMaxActive:   1000,
		RedisMaxStore:    20,
		RedisAddrs:       make(map[string]string),
	}
	if err := gconf.Unmarshal(conf); err != nil {
		Log.Error("goconf.Unmarshal() error(%v)", err)
		return nil, err
	}

	redisAddrsSec := gconf.Get("redis.addr")
	if redisAddrsSec != nil {
		for _, key := range redisAddrsSec.Keys() {
			addr, err := redisAddrsSec.String(key)
			if err != nil {
				return nil, fmt.Errorf("config section:\"redis.addrs\" key:\"%s\" error(%v)", key, err)
			}
			conf.RedisAddrs[key] = addr
		}
	}

	return conf, nil
}
Example #24
0
func InitConfig() error {
	conf := goconf.New()
	if err := conf.Parse("config.conf"); err != nil {
		return err
	}
	mysql := new(muconfig.MySql)
	redis := new(muconfig.Redis)
	base := new(muconfig.Base)
	if err := conf.Unmarshal(mysql); err != nil {
		return err
	}
	if err := conf.Unmarshal(redis); err != nil {
		return err
	}

	if err := conf.Unmarshal(base); err != nil {
		return err
	}
	Log.Info(mysql, redis)
	muconfig.Conf.SetMysql(mysql)
	muconfig.Conf.SetRedis(redis)
	muconfig.Conf.SetBase(base)
	return nil
}
Example #25
0
// InitConfig get a new Config struct.
func InitConfig() error {
	Conf = &Config{
		// base
		User:          "******",
		PidFile:       "/tmp/gopush-cluster-comet.pid",
		Dir:           "./",
		Log:           "./log/xml",
		MaxProc:       runtime.NumCPU(),
		WebsocketBind: []string{"localhost:6968"},
		TCPBind:       []string{"localhost:6969"},
		RPCBind:       []string{"localhost:6970"},
		PprofBind:     []string{"localhost:6971"},
		StatBind:      []string{"localhost:6972"},
		// zookeeper
		ZookeeperAddr:        []string{"120.26.78.119:2181"},
		ZookeeperTimeout:     30 * time.Second,
		ZookeeperCometPath:   "/gopush-cluster-comet",
		ZookeeperCometNode:   "node1",
		ZookeeperCometWeight: 1,
		ZookeeperMessagePath: "/gopush-cluster-message",
		// rpc
		RPCPing:  1 * time.Second,
		RPCRetry: 1 * time.Second,
		// channel
		SndbufSize:              2048,
		RcvbufSize:              256,
		Proto:                   []string{"tcp", "websocket"},
		BufioInstance:           runtime.NumCPU(),
		BufioNum:                128,
		TCPKeepalive:            false,
		TokenExpire:             30 * 24 * time.Hour,
		MaxSubscriberPerChannel: 64,
		ChannelBucket:           runtime.NumCPU(),
		Auth:                    false,
		MsgBufNum:               30,
	}
	//生成对应的消费的queue名字,node名字,
	interfaces, err := net.Interfaces()
	if err != nil {
		panic("Failed to get mac , here is what you got: " + err.Error())
	}
	mac := ""
	for _, inter := range interfaces {
		//fmt.Println(inter.Name)
		if inter.Name == "en0" {
			mac = inter.HardwareAddr.String() //获取本机MAC地址
		}

		log.Debug("MAC = %s", inter.HardwareAddr.String())
	}
	pid := os.Getpid()
	log.Info("MAC = %s", mac)
	log.Info("pid = %d", pid)

	Conf.NodeName = fmt.Sprintf("%s-%d", mac, pid)
	Conf.ConsumerQueue = Conf.NodeName
	Conf.ConsumerQueuePartition = 20
	log.Info("NodeName=%s,ConsumeQueue=%s", Conf.NodeName, Conf.ConsumerQueue)
	c := goconf.New()
	if err := c.Parse(confFile); err != nil {
		return err
	}
	if err := c.Unmarshal(Conf); err != nil {
		return err
	}
	log.Info("NodeName=%s,ConsumeQueue=%s", Conf.NodeName, Conf.ConsumerQueue)
	return nil
}
Example #26
0
package main

import (
	"flag"
	"github.com/Terry-Mao/goconf"
	"github.com/golang/glog"
)

var (
	// global config object
	goConf   = goconf.New()
	MyConf   *Config
	confPath string
)

type Config struct {
	RPCAddr  string `goconf:"base:rpc.addr:,"`
	WorkerId int64  `goconf:"base:worker"`
}

func init() {
	flag.StringVar(&confPath, "conf", "./test.conf", " set gosnowflake config file path")
}

// Init init the configuration file.
func InitConfig() error {
	MyConf = &Config{
		RPCAddr:  "localhost:8080",
		WorkerId: int64(0),
	}
	if err := goConf.Parse(confPath); err != nil {