Revise a print error for test_service script
[iec.git] / src / foundation / api / revel / server.go
1 // Copyright (c) 2012-2016 The Revel Framework Authors, All rights reserved.
2 // Revel Framework source code and usage is governed by a MIT style
3 // license that can be found in the LICENSE file.
4
5 package revel
6
7 import (
8         "fmt"
9         "github.com/revel/revel/session"
10         "os"
11         "strconv"
12         "strings"
13         "github.com/revel/revel/utils"
14 )
15
16 // Revel's variables server, router, etc
17 var (
18         MainRouter         *Router
19         MainTemplateLoader *TemplateLoader
20         MainWatcher        *Watcher
21         serverEngineMap    = map[string]func() ServerEngine{}
22         CurrentEngine      ServerEngine
23         ServerEngineInit   *EngineInit
24         serverLogger       = RevelLog.New("section", "server")
25 )
26
27 func RegisterServerEngine(name string, loader func() ServerEngine) {
28         serverLogger.Debug("RegisterServerEngine: Registered engine ", "name", name)
29         serverEngineMap[name] = loader
30 }
31
32 // InitServer initializes the server and returns the handler
33 // It can be used as an alternative entry-point if one needs the http handler
34 // to be exposed. E.g. to run on multiple addresses and ports or to set custom
35 // TLS options.
36 func InitServer() {
37         CurrentEngine.Init(ServerEngineInit)
38         initControllerStack()
39         startupHooks.Run()
40
41         // Load templates
42         MainTemplateLoader = NewTemplateLoader(TemplatePaths)
43         if err := MainTemplateLoader.Refresh(); err != nil {
44                 serverLogger.Debug("InitServer: Main template loader failed to refresh", "error", err)
45         }
46
47         // The "watch" config variable can turn on and off all watching.
48         // (As a convenient way to control it all together.)
49         if Config.BoolDefault("watch", true) {
50                 MainWatcher = NewWatcher()
51                 Filters = append([]Filter{WatchFilter}, Filters...)
52         }
53
54         // If desired (or by default), create a watcher for templates and routes.
55         // The watcher calls Refresh() on things on the first request.
56         if MainWatcher != nil && Config.BoolDefault("watch.templates", true) {
57                 MainWatcher.Listen(MainTemplateLoader, MainTemplateLoader.paths...)
58         }
59
60 }
61
62 // Run the server.
63 // This is called from the generated main file.
64 // If port is non-zero, use that.  Else, read the port from app.conf.
65 func Run(port int) {
66         defer func() {
67                 if r := recover(); r != nil {
68                         RevelLog.Crit("Recovered error in startup", "error", r)
69                         RaiseEvent(REVEL_FAILURE, r)
70                         panic("Fatal error in startup")
71                 }
72         }()
73
74         // Initialize the session logger, must be initiated from this app to avoid
75         // circular references
76         session.InitSession(RevelLog)
77
78         // Create the CurrentEngine instance from the application config
79         InitServerEngine(port, Config.StringDefault("server.engine", GO_NATIVE_SERVER_ENGINE))
80         RaiseEvent(ENGINE_BEFORE_INITIALIZED, nil)
81         InitServer()
82         RaiseEvent(ENGINE_STARTED, nil)
83         // This is needed for the harness to recognize that the server is started, it looks for the word
84         // "Listening" in the stdout stream
85
86         fmt.Fprintf(os.Stdout, "Revel engine is listening on.. %s\n", ServerEngineInit.Address)
87         // Start never returns,
88         CurrentEngine.Start()
89         fmt.Fprintf(os.Stdout, "Revel engine is NOT listening on.. %s\n", ServerEngineInit.Address)
90         RaiseEvent(ENGINE_SHUTDOWN, nil)
91         shutdownHooks.Run()
92         println("\nRevel exited normally\n")
93 }
94
95 // Build an engine initialization object and start the engine
96 func InitServerEngine(port int, serverEngine string) {
97         address := HTTPAddr
98         if address == "" {
99                 address = "localhost"
100         }
101         if port == 0 {
102                 port = HTTPPort
103         }
104
105         var network = "tcp"
106         var localAddress string
107
108         // If the port is zero, treat the address as a fully qualified local address.
109         // This address must be prefixed with the network type followed by a colon,
110         // e.g. unix:/tmp/app.socket or tcp6:::1 (equivalent to tcp6:0:0:0:0:0:0:0:1)
111         if port == 0 {
112                 parts := strings.SplitN(address, ":", 2)
113                 network = parts[0]
114                 localAddress = parts[1]
115         } else {
116                 localAddress = address + ":" + strconv.Itoa(port)
117         }
118
119         if engineLoader, ok := serverEngineMap[serverEngine]; !ok {
120                 panic("Server Engine " + serverEngine + " Not found")
121         } else {
122                 CurrentEngine = engineLoader()
123                 serverLogger.Debug("InitServerEngine: Found server engine and invoking", "name", CurrentEngine.Name())
124                 ServerEngineInit = &EngineInit{
125                         Address:  localAddress,
126                         Network:  network,
127                         Port:     port,
128                         Callback: handleInternal,
129                 }
130         }
131         AddInitEventHandler(CurrentEngine.Event)
132 }
133
134 // Initialize the controller stack for the application
135 func initControllerStack() {
136         RevelConfig.Controller.Reuse = Config.BoolDefault("revel.controller.reuse",true)
137
138         if RevelConfig.Controller.Reuse {
139                 RevelConfig.Controller.Stack = utils.NewStackLock(
140                         Config.IntDefault("revel.controller.stack", 10),
141                         Config.IntDefault("revel.controller.maxstack", 200), func() interface{} {
142                                 return NewControllerEmpty()
143                         })
144                 RevelConfig.Controller.CachedStackSize = Config.IntDefault("revel.cache.controller.stack", 10)
145                 RevelConfig.Controller.CachedStackMaxSize = Config.IntDefault("revel.cache.controller.maxstack", 100)
146                 RevelConfig.Controller.CachedMap = map[string]*utils.SimpleLockStack{}
147         }
148 }
149
150 // Called to stop the server
151 func StopServer(value interface{}) EventResponse {
152         return RaiseEvent(ENGINE_SHUTDOWN_REQUEST,value)
153 }