refactored printStackTrace(), now logging set to INFO
[profile/ivi/layer-management.git] / LayerManagerService / src / main.cpp
1 /***************************************************************************
2  *
3  * Copyright 2010,2011 BMW Car IT GmbH
4  *
5  *
6  * Licensed under the Apache License, Version 2.0 (the "License");
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  *        http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  *
18  ****************************************************************************/
19
20 #include "Layermanager.h"
21 #include "config.h"
22 #include "IRenderer.h"
23 #include "ICommunicator.h"
24 #include "ISceneProvider.h"
25 #include "ICommandExecutor.h"
26 #include <iostream>
27 #include <sys/types.h>
28 #include <dirent.h>
29 #include <errno.h>
30 #include <dlfcn.h>
31 #include "Log.h"
32 #include <getopt.h>
33 #include <libgen.h> // basename
34 #include <signal.h>
35 #include <execinfo.h> // for stacktrace
36
37 #include <list>
38 using std::list;
39
40 #include <string.h>
41 using std::string;
42
43 typedef list<string> tFileList;
44 typedef list<string>::iterator tFileListIterator;
45
46
47 const char* displayName = ":0";
48 const char* gPluginLookupPath = "/usr/lib/layermanager";
49 int displayWidth = 1280; // default value, override with -w argument
50 int displayHeight = 480; // default value, override with -h argument
51
52 const char* gRendererPluginDirectories[] = { "/renderer" };
53
54 uint gRendererPluginDirectoriesCount = sizeof(gRendererPluginDirectories) / sizeof(gRendererPluginDirectories[0]);
55
56 const char* gCommunicatorPluginDirectories[] = { "/communicator" };
57
58 uint gCommunicatorPluginDirectoriesCount = sizeof(gCommunicatorPluginDirectories) / sizeof(gCommunicatorPluginDirectories[0]);
59                                                  
60 const char* gScenePluginDirectories[] = { "" };
61
62 uint gScenePluginDirectoriesCount = sizeof(gScenePluginDirectories) / sizeof(gScenePluginDirectories[0]);                                                 
63                                                  
64 const char* USAGE_DESCRIPTION = "Usage:\t LayerManagerService [options]\n"
65                                 "options:\t\n\n"
66                                 "\t-w: Window Width\t\n"
67                                 "\t-h: Window Height\t\n"
68                                 "\t-d: displayName \t\n"
69                                 "\t-f: loglevel file \t 0 [default] \n\t\t\t\t[0=disabled,1=error,2=info,3=warning,4=debug]\n"
70                                 "\t-c: loglevel console \t 2 [default] \n\t\t\t\t[0=disabled,1=error,2=info,3=warning,4=debug]\n"
71                                 "\t-v: show version info\t\n"
72                                 "\nexample: LayerManagerService -w800 -h480 -d:0\n";
73
74 bool g_LayerManagerRunning;
75
76 template<class T>
77 T* getCreateFunction(string libname)
78 {
79     // cut off directories
80     char* fileWithPath = const_cast<char*>(libname.c_str());
81     string libFileName = basename(fileWithPath);
82     LOG_DEBUG("LayerManagerService", "lib name without directory: " << libFileName);
83
84     // cut off "lib" in front and cut off .so end"
85     string createFunctionName = "create" + libFileName.substr(3, libFileName.length() - 6);
86     LOG_DEBUG("LayerManagerService", "lib entry point name: " << createFunctionName);
87
88     // open library
89     void *libraryHandle;
90     dlerror(); // Clear any existing error
91     libraryHandle = dlopen(libname.c_str(), RTLD_NOW /*LAZY*/);
92     const char* dlopen_error = dlerror();
93     if (!libraryHandle || dlopen_error)
94     {
95         LOG_ERROR("LayerManagerService", "dlopen failed: " << dlopen_error);
96         return 0;
97     }
98
99     // get entry point from shared lib
100     dlerror(); // Clear any existing error
101     LOG_DEBUG("LayerManagerService", "loading external function with name: " << createFunctionName);
102
103     union
104     {
105         void* voidPointer;
106         T* typedPointer;
107     } functionPointer;
108
109     // Note: direct cast is not allowed by ISO C++. e.g.
110     // T* createFunction = reinterpret_cast<T*>(dlsym(libraryHandle, createFunctionName.c_str()));
111     // compiler warning: "forbids casting between pointer-to-function and pointer-to-object"
112
113     functionPointer.voidPointer = dlsym(libraryHandle, createFunctionName.c_str());
114     T* createFunction = functionPointer.typedPointer;
115
116     const char* dlsym_error = dlerror();
117     if (!createFunction || dlsym_error)
118     {
119         LOG_ERROR("LayerManagerService", "Failed to load shared lib entry point: " << dlsym_error);
120     }
121
122     return createFunction;
123 }
124
125 void parseCommandLine(int argc, char **argv)
126 {
127     while (optind < argc)
128     {
129         int option = getopt(argc, argv, "w::h::d::?::c::f::v::");
130         switch (option)
131         {
132         case 'd':
133             displayName = optarg;
134             break;
135         case 'w':
136             displayWidth = atoi(optarg);
137             break;
138         case 'h':
139             displayHeight = atoi(optarg);
140             break;
141         case 'c':
142             if ( atoi(optarg) < LOG_MAX_LEVEL ) 
143             {
144                 Log::consoleLogLevel = (LOG_MODES) atoi(optarg);
145             }
146             break;
147         case 'f':
148             if ( atoi(optarg) < LOG_MAX_LEVEL ) 
149             {
150                 Log::fileLogLevel = (LOG_MODES) atoi(optarg);
151             }
152             break;
153         case 'v':
154             printf("LayerManagerService\nVersion: %s\n", ILM_VERSION);
155             exit(-1);
156             break;
157         case '?':   
158         default:
159             printf("LayerManagerService\nVersion: %s\n", ILM_VERSION);
160             puts(USAGE_DESCRIPTION);
161             exit(-1);
162         }
163     }
164 }
165
166 void getSharedLibrariesFromDirectory(tFileList& fileList, string dirName)
167 {
168     // open directory
169     DIR *directory = opendir(dirName.c_str());
170     if (!directory)
171     {
172         LOG_ERROR("LayerManagerService", "Error(" << errno << ") opening " << dirName);
173         return;
174     }
175
176     // iterate content of directory
177     struct dirent *itemInDirectory = 0;
178     while ((itemInDirectory = readdir(directory)))
179     {
180         unsigned char entryType = itemInDirectory->d_type;
181         string entryName = itemInDirectory->d_name;
182
183         bool regularFile = (entryType == DT_REG);
184         bool sharedLibExtension = ("so" == entryName.substr(entryName.find_last_of(".") + 1));
185
186         if (regularFile && sharedLibExtension)
187         {
188             LOG_DEBUG("LayerManagerService", "adding file " << entryName);
189             fileList.push_back(dirName + "/" + entryName);
190         }
191         else
192         {
193             LOG_DEBUG("LayerManagerService", "ignoring file " << entryName);
194         }
195     }
196
197     closedir(directory);
198 }
199
200 void loadScenePlugins(SceneProviderList& sceneProviderList, ICommandExecutor* executor)
201 {
202     tFileList sharedLibraryNameList;
203
204     // search sceneprovider plugins in configured directories
205     for (uint dirIndex = 0; dirIndex < gScenePluginDirectoriesCount; ++dirIndex)
206     {
207         char directoryName[1024];
208         strcpy(directoryName,gPluginLookupPath);
209         strcat(directoryName,gScenePluginDirectories[dirIndex]);
210         LOG_DEBUG("LayerManagerService", "Searching for SceneProviders in: " << directoryName);
211         getSharedLibrariesFromDirectory(sharedLibraryNameList, directoryName);
212     }
213
214     LOG_DEBUG("LayerManagerService", sharedLibraryNameList.size() << " SceneProvider plugins found");
215
216     // iterate all communicator plugins and start them
217     tFileListIterator iter = sharedLibraryNameList.begin();
218     tFileListIterator iterEnd = sharedLibraryNameList.end();
219
220     for (; iter != iterEnd; ++iter)
221     {
222         LOG_INFO("LayerManagerService", "Loading SceneProvider plugin " << *iter);
223
224         ISceneProvider* (*createFunc)(ICommandExecutor*);
225         createFunc = getCreateFunction<ISceneProvider*(ICommandExecutor*)>(*iter);
226
227         if (!createFunc)
228         {
229             LOG_DEBUG("LayerManagerService", "Entry point of SceneProvider not found");
230             continue;
231         }
232
233         LOG_DEBUG("LayerManagerService", "Creating SceneProvider instance");
234         ISceneProvider* newSceneProvider = createFunc(executor);
235
236         if (!newSceneProvider)
237         {
238             LOG_ERROR("LayerManagerService","SceneProvider initialization failed. Entry Function not callable");
239             continue;
240         }
241
242         sceneProviderList.push_back(newSceneProvider);
243     }
244 }
245
246
247 void loadCommunicatorPlugins(CommunicatorList& communicatorList, ICommandExecutor* executor)
248 {
249     tFileList sharedLibraryNameList;
250
251     // search communicator plugins in configured directories
252     for (uint dirIndex = 0; dirIndex < gCommunicatorPluginDirectoriesCount; ++dirIndex)
253     {
254         char directoryName[1024];
255         strcpy(directoryName,gPluginLookupPath);
256         strcat(directoryName,gCommunicatorPluginDirectories[dirIndex]);
257         LOG_DEBUG("LayerManagerService", "Searching for communicator in: " << directoryName);
258         getSharedLibrariesFromDirectory(sharedLibraryNameList, directoryName);
259     }
260
261     LOG_DEBUG("LayerManagerService", sharedLibraryNameList.size() << " Communicator plugins found");
262
263     // iterate all communicator plugins and start them
264     tFileListIterator iter = sharedLibraryNameList.begin();
265     tFileListIterator iterEnd = sharedLibraryNameList.end();
266
267     for (; iter != iterEnd; ++iter)
268     {
269         LOG_INFO("LayerManagerService", "Loading Communicator plugin " << *iter);
270
271         ICommunicator* (*createFunc)(ICommandExecutor*);
272         createFunc = getCreateFunction<ICommunicator*(ICommandExecutor*)>(*iter);
273
274         if (!createFunc)
275         {
276             LOG_DEBUG("LayerManagerService", "Entry point of Communicator not found");
277             continue;
278         }
279
280         LOG_DEBUG("LayerManagerService", "Creating Communicator instance");
281         ICommunicator* newCommunicator = createFunc(executor);
282
283         if (!newCommunicator)
284         {
285             LOG_ERROR("LayerManagerService","Communicator initialization failed. Entry Function not callable");
286             continue;
287         }
288
289         communicatorList.push_back(newCommunicator);
290     }
291 }
292
293 void loadRendererPlugins(RendererList& rendererList, IScene* pScene)
294 {
295     tFileList sharedLibraryNameList;
296
297     // search communicator plugins in configured directories
298     for (uint dirIndex = 0; dirIndex < gRendererPluginDirectoriesCount; ++dirIndex)
299     {
300         char directoryName[1024];
301         strcpy(directoryName,gPluginLookupPath);
302         strcat(directoryName,gRendererPluginDirectories[dirIndex]);        
303         LOG_DEBUG("LayerManagerService", "Searching for renderer in: " << directoryName);
304         getSharedLibrariesFromDirectory(sharedLibraryNameList, directoryName);
305     }
306
307     LOG_DEBUG("LayerManagerService", sharedLibraryNameList.size() << " Renderer plugins found");
308
309     // currently the use of only one renderer is enforced
310     if (sharedLibraryNameList.size() > 1)
311     {
312         LOG_WARNING("LayerManagerService", "more than 1 Renderer plugin found. using only " << sharedLibraryNameList.front());
313         while (sharedLibraryNameList.size() > 1)
314         {
315             sharedLibraryNameList.pop_back();
316         }
317     }
318
319     // iterate all renderer plugins and start them
320     tFileListIterator iter = sharedLibraryNameList.begin();
321     tFileListIterator iterEnd = sharedLibraryNameList.end();
322
323     for (; iter != iterEnd; ++iter)
324     {
325         LOG_INFO("LayerManagerService", "Loading Renderer plugin " << *iter);
326         IRenderer* (*createFunc)(IScene*);
327         createFunc = getCreateFunction<IRenderer*(IScene*)>(*iter);
328         if (!createFunc)
329         {
330             LOG_DEBUG("LayerManagerService", "Entry point of Renderer not found");
331             continue;
332         }
333
334         LOG_DEBUG("LayerManagerService", "Creating Renderer instance");
335         IRenderer* newRenderer = createFunc(pScene);
336         if (!newRenderer)
337         {
338             LOG_ERROR("LayerManagerService","Renderer initialization failed. Entry Function not callable");
339             continue;
340         }
341
342         rendererList.push_back(newRenderer);
343     }
344 }
345
346 void printStackTrace()
347 {
348     const int maxStackSize = 64;
349     void* stack[maxStackSize];
350
351     size_t count = backtrace(stack, maxStackSize);
352     char **lines = backtrace_symbols(stack, count);
353
354     LOG_INFO("LayerManagerService", "--------------------------------------------------");
355     for (unsigned int i = 0; i < count; ++i)
356     {
357         LOG_INFO("LayerManagerService", "Stack-Trace [" << i << "]: " << lines[i]);
358     }
359     LOG_INFO("LayerManagerService", "--------------------------------------------------");
360
361     LOG_INFO("LayerManagerService", "Exiting application.")
362     exit(-1);
363 }
364
365 void signalHandler(int sig)
366 {
367     switch (sig)
368     {
369     case SIGTERM:
370         g_LayerManagerRunning = false;
371         LOG_INFO("LayerManagerService", "Signal SIGTERM received. Shutting down.");
372         break;
373
374     case SIGINT:
375         g_LayerManagerRunning = false;
376         LOG_INFO("LayerManagerService", "Signal SIGINT received. Shutting down.");
377         break;
378
379     case SIGBUS:
380         g_LayerManagerRunning = false;
381         LOG_ERROR("LayerManagerService", "Signal SIGBUS received. Shutting down.");
382         printStackTrace();
383         break;
384
385     case SIGSEGV:
386         g_LayerManagerRunning = false;
387         LOG_ERROR("LayerManagerService", "Signal SIGSEGV received. Shutting down.");
388         printStackTrace();
389         break;
390
391     default:
392         LOG_INFO("LayerManagerService", "Signal " << sig << " received.");
393     }
394 }
395
396 int main(int argc, char **argv)
397 {
398     // setup signal handler and global flag to handle shutdown
399     g_LayerManagerRunning = true;
400     signal(SIGBUS, signalHandler);
401     signal(SIGSEGV, signalHandler);
402     signal(SIGTERM, signalHandler);
403     signal(SIGINT, signalHandler);
404
405     parseCommandLine(argc, (char**) argv);
406     char* pluginLookupPath = getenv("LM_PLUGIN_PATH");
407     LOG_INFO("LayerManagerService", "Starting Layermanager.");
408
409     printConfiguration();
410
411     if  (pluginLookupPath != NULL ) 
412     {
413         gPluginLookupPath = pluginLookupPath;
414     }
415     LOG_INFO("LayerManagerService", "Used plugin directory is " << gPluginLookupPath);
416
417     LOG_DEBUG("LayerManagerService", "Creating Layermanager.");
418     ICommandExecutor* pManager = new Layermanager();
419     IScene* pScene = pManager->getScene();
420
421     // Create and load Renderer plugins
422     LOG_DEBUG("LayerManagerService", "Loading renderer plugins.");
423     RendererList rendererList;
424     loadRendererPlugins(rendererList, pScene);
425
426     // register renderer plugins at layermanager
427     LOG_DEBUG("LayerManagerService", "Using " << rendererList.size() << " Renderer plugins");
428     RendererListIterator rendererIter = rendererList.begin();
429     RendererListIterator rendererIterEnd = rendererList.end();
430     for (; rendererIter != rendererIterEnd; ++rendererIter)
431     {
432         pManager->addRenderer(*rendererIter);
433     }
434
435     // Create and load communicator plugins
436     LOG_DEBUG("LayerManagerService", "Loading communicator plugins.");
437     CommunicatorList communicatorList;
438     loadCommunicatorPlugins(communicatorList, pManager);
439
440     // register communicator plugins at layermanager
441     LOG_DEBUG("LayerManagerService", "Using " << communicatorList.size() << " Communicator plugins");
442     CommunicatorListIterator commIter = communicatorList.begin();
443     CommunicatorListIterator commIterEnd = communicatorList.end();
444     for (; commIter != commIterEnd; ++commIter)
445     {
446         pManager->addCommunicator(*commIter);
447     }
448     LOG_DEBUG("LayerManagerService", "Loading scene provider plugins.");
449     SceneProviderList sceneProviderList;
450     loadScenePlugins(sceneProviderList, pManager);
451
452     // register communicator plugins at layermanager
453     LOG_DEBUG("LayerManagerService", "Using " << sceneProviderList.size() << " SceneProvider plugins");
454     SceneProviderListIterator sceneProviderIter = sceneProviderList.begin();
455     SceneProviderListIterator sceneProviderIterEnd = sceneProviderList.end();
456     for (; sceneProviderIter != sceneProviderIterEnd; ++sceneProviderIter)
457     {
458         pManager->addSceneProvider(*sceneProviderIter);
459     }
460     bool started = pManager->startManagement(displayWidth, displayHeight, displayName);
461
462     if (!started)
463     {
464         goto cleanup;
465     }
466
467     // must stay within main method or else application would completely exit
468     LOG_INFO("LayerManagerService", "Startup complete. EnterMainloop");
469
470     while (g_LayerManagerRunning)
471     {
472         CommunicatorListIterator commIter = communicatorList.begin();
473         CommunicatorListIterator commIterEnd = communicatorList.end();
474         for (; commIter != commIterEnd; ++commIter)
475         {
476             (*commIter)->process(100);
477         }
478     }
479
480
481     // cleanup
482     cleanup:
483
484     LOG_INFO("LayerManagerService", "Exiting Application.");
485     pManager->stopManagement();
486     //delete pRenderer; TODO
487     //delete pCommunicator; TODO
488     delete pManager;
489
490     // reset signal handling to default
491     signal(SIGBUS, SIG_DFL);
492     signal(SIGSEGV, SIG_DFL);
493     signal(SIGTERM, SIG_DFL);
494     signal(SIGINT, SIG_DFL);
495
496     return (int)started - 1;
497 }