merge upstream
[odoo/odoo.git] / openerp / service / __init__.py
1 # -*- coding: utf-8 -*-
2 ##############################################################################
3 #
4 #    OpenERP, Open Source Management Solution
5 #    Copyright (C) 2004-2009 Tiny SPRL (<http://tiny.be>).
6 #
7 #    This program is free software: you can redistribute it and/or modify
8 #    it under the terms of the GNU Affero General Public License as
9 #    published by the Free Software Foundation, either version 3 of the
10 #    License, or (at your option) any later version.
11 #
12 #    This program is distributed in the hope that it will be useful,
13 #    but WITHOUT ANY WARRANTY; without even the implied warranty of
14 #    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 #    GNU Affero General Public License for more details.
16 #
17 #    You should have received a copy of the GNU Affero General Public License
18 #    along with this program.  If not, see <http://www.gnu.org/licenses/>.
19 #
20 ##############################################################################
21
22 import logging
23 import os
24 import signal
25 import sys
26 import threading
27 import time
28
29 import http_server
30 import netrpc_server
31 import web_services
32 import websrv_lib
33
34 import openerp.cron
35 import openerp.modules
36 import openerp.netsvc
37 import openerp.osv
38 import openerp.tools
39 import openerp.service.wsgi_server
40 import openerp.service.workers
41
42 #.apidoc title: RPC Services
43
44 """ Classes of this module implement the network protocols that the
45     OpenERP server uses to communicate with remote clients.
46
47     Some classes are mostly utilities, whose API need not be visible to
48     the average user/developer. Study them only if you are about to
49     implement an extension to the network protocols, or need to debug some
50     low-level behavior of the wire.
51 """
52
53 _logger = logging.getLogger(__name__)
54
55 def load_server_wide_modules():
56     for m in openerp.conf.server_wide_modules:
57         try:
58             openerp.modules.module.load_openerp_module(m)
59         except Exception:
60             msg = ''
61             if m == 'web':
62                 msg = """
63 The `web` module is provided by the addons found in the `openerp-web` project.
64 Maybe you forgot to add those addons in your addons_path configuration."""
65             _logger.exception('Failed to load server-wide module `%s`.%s', m, msg)
66
67 start_internal_done = False
68
69 def start_internal():
70     global start_internal_done
71     if start_internal_done:
72         return
73     openerp.netsvc.init_logger()
74     openerp.modules.loading.open_openerp_namespace()
75     # Instantiate local services (this is a legacy design).
76     openerp.osv.osv.start_object_proxy()
77     # Export (for RPC) services.
78     web_services.start_web_services()
79     load_server_wide_modules()
80     start_internal_done = True
81
82 def start_services():
83     """ Start all services including http, netrpc and cron """
84     start_internal()
85
86     # Initialize the HTTP stack.
87     netrpc_server.init_servers()
88
89     # Start the main cron thread.
90     if openerp.conf.max_cron_threads:
91         openerp.cron.start_master_thread()
92
93     # Start the top-level servers threads (normally HTTP, HTTPS, and NETRPC).
94     openerp.netsvc.Server.startAll()
95
96     # Start the WSGI server.
97     openerp.service.wsgi_server.start_server()
98
99 def stop_services():
100     """ Stop all services. """
101     # stop scheduling new jobs; we will have to wait for the jobs to complete below
102     openerp.cron.cancel_all()
103
104     openerp.netsvc.Server.quitAll()
105     openerp.service.wsgi_server.stop_server()
106     _logger.info("Initiating shutdown")
107     _logger.info("Hit CTRL-C again or send a second signal to force the shutdown.")
108
109     # Manually join() all threads before calling sys.exit() to allow a second signal
110     # to trigger _force_quit() in case some non-daemon threads won't exit cleanly.
111     # threading.Thread.join() should not mask signals (at least in python 2.5).
112     me = threading.currentThread()
113     _logger.debug('current thread: %r', me)
114     for thread in threading.enumerate():
115         _logger.debug('process %r (%r)', thread, thread.isDaemon())
116         if thread != me and not thread.isDaemon():
117             while thread.isAlive():
118                 _logger.debug('join and sleep')
119                 # Need a busyloop here as thread.join() masks signals
120                 # and would prevent the forced shutdown.
121                 thread.join(0.05)
122                 time.sleep(0.05)
123
124     _logger.debug('--')
125     openerp.modules.registry.RegistryManager.delete_all()
126     logging.shutdown()
127
128 def start_services_workers():
129     openerp.multi_process = True # Nah!
130
131     openerp.service.workers.Multicorn(openerp.service.wsgi_server.application).run()
132
133 def restart_server():
134     pid = openerp.wsgi.core.arbiter_pid
135     if pid:
136         os.kill(pid, signal.SIGHUP)
137     else:
138         openerp.phoenix = True
139         signame = 'CTRL_C_EVENT' if os.name == 'nt' else 'SIGINT'
140         sig = getattr(signal, signame)
141         os.kill(os.getpid(), sig)
142
143         #strip_args = ['-d', '-u']
144         #a = sys.argv[:]
145         #args = [x for i, x in enumerate(a) if x not in strip_args and a[max(i - 1, 0)] not in strip_args]
146
147         #stop_services()
148         #os.execv(sys.executable, [sys.executable] + args)
149
150 # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: