2 * Copyright (c) 2012 Samsung Electronics Co., Ltd All Rights Reserved
4 * Licensed under the Apache License, Version 2.0 (the License);
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an AS IS BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
21 #include <glib-object.h>
24 #ifdef DP_SUPPORT_DBUS_ACTIVATION
25 #include <dbus/dbus.h>
28 #include "download-provider-config.h"
29 #include "download-provider-log.h"
30 #include "download-provider-socket.h"
31 #include "download-provider-pthread.h"
32 #include "download-provider-slots.h"
33 #include "download-provider-db.h"
34 #include "download-provider-network.h"
35 #include "download-provider-queue.h"
36 #include "download-provider-notification.h"
37 #include "download-provider-da-interface.h"
40 int dp_lock_pid(char *path);
41 void *dp_thread_requests_manager(void *arg);
43 // declare global variables
44 // need for libsoup, decided the life-time by mainloop.
45 GMainLoop *g_main_loop_handle = 0;
47 #ifdef DP_SUPPORT_DBUS_ACTIVATION
48 static int __register_dbus_service(void)
51 DBusConnection *dp_dbus_connection = NULL;
53 dbus_error_init(&dbus_error);
55 dp_dbus_connection = dbus_bus_get(DBUS_BUS_SYSTEM, &dbus_error);
56 if (dp_dbus_connection == NULL) {
57 TRACE_ERROR("[DBUS] dbus_bus_get: %s", dbus_error.message);
58 dbus_error_free(&dbus_error);
62 if (dbus_bus_request_name
63 (dp_dbus_connection, DP_DBUS_SERVICE_DBUS, 0, &dbus_error) < 0 ||
64 dbus_error_is_set(&dbus_error)) {
65 TRACE_ERROR("[DBUS] request_name %s", dbus_error.message);
66 dbus_error_free(&dbus_error);
67 dbus_connection_unref(dp_dbus_connection);
68 dp_dbus_connection = NULL;
71 dbus_connection_unref(dp_dbus_connection);
72 dp_dbus_connection = NULL;
78 void dp_terminate(int signo)
80 TRACE_INFO("Received SIGTERM");
81 if (g_main_loop_is_running(g_main_loop_handle))
82 g_main_loop_quit(g_main_loop_handle);
85 static gboolean __dp_idle_start_service(void *data)
87 TRACE_INFO("Launch threads .....");
89 // declare all resources
91 pthread_attr_t thread_attr;
94 if (pthread_attr_init(&thread_attr) != 0) {
95 TRACE_STRERROR("failed to init pthread attr");
96 dp_terminate(SIGTERM);
99 if (pthread_attr_setdetachstate(&thread_attr,
100 PTHREAD_CREATE_DETACHED) != 0) {
101 TRACE_STRERROR("failed to set detach option");
102 dp_terminate(SIGTERM);
106 // create thread for managing QUEUEs
108 (&thread_pid, &thread_attr, dp_thread_queue_manager,
111 ("failed to create pthread for run_manage_download_server");
112 dp_terminate(SIGTERM);
115 // start service, accept url-download ( client package )
117 (&thread_pid, &thread_attr, dp_thread_requests_manager,
120 ("failed to create pthread for run_manage_download_server");
121 dp_terminate(SIGTERM);
126 int main(int argc, char **argv)
128 dp_privates *privates = NULL;
131 if (chdir("/") < 0) {
132 TRACE_STRERROR("failed to call setsid or chdir");
137 // close all console I/O
139 close(STDOUT_FILENO);
140 close(STDERR_FILENO);
143 if (signal(SIGTERM, dp_terminate) == SIG_ERR) {
144 TRACE_ERROR("failed to register signal callback");
147 // write IPC_FD_PATH. and lock
148 if ((lock_fd = dp_lock_pid(DP_LOCK_PID)) < 0) {
150 ("It need to check download-provider is already alive");
151 TRACE_ERROR("Or fail to create pid file in (%s)",
155 // if exit socket file, delete it
156 if (access(DP_IPC, F_OK) == 0) {
162 privates = (dp_privates *) calloc(1, sizeof(dp_privates));
164 TRACE_ERROR("[CRITICAL] failed to alloc for private info");
167 privates->groups = dp_client_group_slots_new(DP_MAX_GROUP);
168 if (privates->groups == NULL) {
169 TRACE_ERROR("[CRITICAL] failed to alloc for groups");
172 privates->requests = dp_request_slots_new(DP_MAX_REQUEST);
173 if (privates->requests == NULL) {
174 TRACE_ERROR("[CRITICAL] failed to alloc for requests");
178 // ready socket ( listen )
179 privates->listen_fd = dp_accept_socket_new();
180 if (privates->listen_fd < 0) {
181 TRACE_ERROR("[CRITICAL] failed to bind SOCKET");
185 #ifdef DP_SUPPORT_DBUS_ACTIVATION
186 TRACE_INFO("SUPPORT DBUS-ACTIVATION");
187 if (__register_dbus_service() < 0) {
188 TRACE_ERROR("[LAUNCH ERROR] __register_dbus_service");
192 TRACE_INFO("Not SUPPORT DBUS-ACTIVATION");
197 // convert to request type, insert all to privates->requests
198 // timeout of request thread will start these jobs by queue thread
199 // load all list from (queue table)
200 if (dp_db_crashed_list(privates->requests, DP_MAX_REQUEST) > 0) {
202 for (i = 0; i < DP_MAX_REQUEST; i++) {
203 if (!privates->requests[i].request)
205 dp_request *request = privates->requests[i].request;
207 ("ID [%d] state[%d]", request->id, request->state);
209 // load to memory, Can be started automatically.
210 if (request->state == DP_STATE_DOWNLOADING ||
211 request->state == DP_STATE_CONNECTING) {
212 request->state = DP_STATE_QUEUED;
214 (request->id, DP_DB_TABLE_LOG, DP_DB_COL_STATE,
215 DP_DB_COL_TYPE_INT, &request->state) < 0) {
216 TRACE_ERROR("[CHECK SQL]");
220 if (request->state == DP_STATE_QUEUED) {
221 int auto_download = dp_db_get_int_column(request->id,
222 DP_DB_TABLE_REQUEST_INFO,
223 DP_DB_COL_AUTO_DOWNLOAD);
224 if (auto_download == 1) {
225 // auto retry... defaultly, show notification
226 request->auto_notification = 1;
227 request->start_time = (int)time(NULL);
230 // do not retry this request
231 request->state = DP_STATE_FAILED;
232 request->error = DP_ERROR_SYSTEM_DOWN;
234 (request->id, DP_DB_TABLE_LOG, DP_DB_COL_STATE,
235 DP_DB_COL_TYPE_INT, &request->state) < 0) {
236 TRACE_ERROR("[CHECK SQL]");
239 (request->id, DP_DB_TABLE_LOG,
240 DP_DB_COL_ERRORCODE, DP_DB_COL_TYPE_INT,
241 &request->error) < 0) {
242 TRACE_ERROR("[CHECK SQL]");
246 // if wanna restart, call continue before this line.
247 // default. update state/error. move to history. unload memory
248 // remove from memory
249 dp_request_free(request);
250 privates->requests[i].request = NULL;
252 } // query crashed_list
254 if (argc != 2 || memcmp(argv[1], "service", 7) != 0) {
255 // in first launch in booting time, not request. terminate by self
256 if (dp_get_request_count(privates->requests) <= 0) {
257 TRACE_INFO("First Boot, No Request");
262 dp_clear_downloadinginfo_notification();
264 if (dp_init_agent() != DP_ERROR_NONE) {
265 TRACE_ERROR("[CRITICAL] failed to init agent");
269 privates->connection = 0;
270 privates->network_status = DP_NETWORK_TYPE_OFF;
271 if (dp_network_connection_init(privates) < 0) {
272 TRACE_INFO("use instant network check");
273 privates->connection = 0;
276 // libsoup need mainloop.
277 g_main_loop_handle = g_main_loop_new(NULL, 0);
279 g_idle_add(__dp_idle_start_service, privates);
281 g_main_loop_run(g_main_loop_handle);
285 TRACE_INFO("Download-Provider will be terminated.");
289 if (privates != NULL) {
291 if (privates->connection)
292 dp_network_connection_destroy(privates->connection);
294 if (privates->listen_fd >= 0) {
295 dp_socket_free(privates->listen_fd);
296 privates->listen_fd = -1;
298 dp_request_slots_free(privates->requests, DP_MAX_REQUEST);
299 privates->requests = NULL;
300 dp_client_group_slots_free(privates->groups, DP_MAX_GROUP);
301 privates->groups = NULL;
307 //send signal to queue thread
308 dp_thread_queue_manager_wake_up();
310 // if exit socket file, delete it
311 if (access(DP_IPC, F_OK) == 0) {
315 if (access(DP_LOCK_PID, F_OK) == 0) {