Add to search download id from history db
[profile/ivi/download-provider.git] / src / download-provider-receiver.c
index 452ab69..a2146b5 100644 (file)
@@ -9,8 +9,6 @@
 
 #include <glib.h>
 
-#include <net_connection.h>
-
 #include "download-provider-config.h"
 #include "download-provider-log.h"
 #include "download-provider-pthread.h"
@@ -38,6 +36,17 @@ pthread_attr_t g_download_provider_thread_attr;
 fd_set g_download_provider_socket_readset;
 fd_set g_download_provider_socket_exceptset;
 
+int _change_pended_download(download_clientinfo *clientinfo)
+{
+       if (!clientinfo)
+               return -1;
+       clientinfo->state = DOWNLOAD_STATE_PENDED;
+       clientinfo->err = DOWNLOAD_ERROR_TOO_MANY_DOWNLOADS;
+       download_provider_db_requestinfo_update_column(clientinfo, DOWNLOAD_DB_STATE);
+       ipc_send_request_stateinfo(clientinfo);
+       return 0;
+}
+
 void *_start_download(void *args)
 {
        int da_ret = -1;
@@ -168,19 +177,16 @@ void *_start_download(void *args)
                }
        }
 
-       // if start_download() return error cause of maximun download limitation, set state to DOWNLOAD_STATE_PENDED.
+       // if start_download() return error cause of maximun download limitation,
+       // set state to DOWNLOAD_STATE_PENDED.
        if (da_ret == DA_ERR_ALREADY_MAX_DOWNLOAD) {
-               TRACE_DEBUG_MSG("change to pended request [%d]", da_ret);
+               TRACE_DEBUG_INFO_MSG("change to pended request [%d]", da_ret);
                CLIENT_MUTEX_LOCK(&(clientinfo->client_mutex));
-               clientinfo->state = DOWNLOAD_STATE_PENDED;
-               clientinfo->err = DOWNLOAD_ERROR_TOO_MANY_DOWNLOADS;
-               download_provider_db_requestinfo_update_column(clientinfo,
-                                                                       DOWNLOAD_DB_STATE);
-               ipc_send_request_stateinfo(clientinfo);
+               _change_pended_download(clientinfo);
                CLIENT_MUTEX_UNLOCK(&(clientinfo->client_mutex));
                return 0;
        } else if (da_ret != DA_RESULT_OK) {
-               TRACE_DEBUG_MSG("Fail to request start [%d]", da_ret);
+               TRACE_DEBUG_INFO_MSG("Fail to request start [%d]", da_ret);
                /* FIXME : need to seperate in detail according to error return values */
                CLIENT_MUTEX_LOCK(&(clientinfo->client_mutex));
                clientinfo->state = DOWNLOAD_STATE_FAILED;
@@ -194,7 +200,7 @@ void *_start_download(void *args)
 
        CLIENT_MUTEX_LOCK(&(clientinfo->client_mutex));
 
-       TRACE_DEBUG_MSG("started download [%d]", da_ret);
+       TRACE_DEBUG_INFO_MSG("started download [%d]", da_ret);
 
        clientinfo->req_id = req_dl_id;
        clientinfo->state = DOWNLOAD_STATE_DOWNLOADING;
@@ -210,9 +216,31 @@ void *_start_download(void *args)
        return 0;
 }
 
+int _create_download_thread(download_clientinfo_slot *clientinfo_slot)
+{
+       if (!clientinfo_slot)
+               return -1;
+
+       // create thread for receiving the reqeust info from client.
+       // and if possible, it will create the thread for listening the event.
+       clientinfo_slot->clientinfo->state = DOWNLOAD_STATE_READY;
+       clientinfo_slot->clientinfo->err = DOWNLOAD_ERROR_NONE;
+       if (pthread_create
+               (&clientinfo_slot->clientinfo->thread_pid,
+               &g_download_provider_thread_attr, _start_download,
+               clientinfo_slot) != 0) {
+               TRACE_DEBUG_INFO_MSG("failed to call pthread_create for client");
+               TRACE_DEBUG_INFO_MSG("Change to pended job");
+               _change_pended_download(clientinfo_slot->clientinfo);
+               return -1;
+       }
+       return 0;
+}
+
 int _handle_new_connection(download_clientinfo_slot *clientinfo_list, download_clientinfo *request_clientinfo)
 {
-       uint searchslot = 0;
+       int searchslot = 0;
+       unsigned active_count = 0;
 
        // NULL - checking
        if (!clientinfo_list || !request_clientinfo ) {
@@ -229,7 +257,7 @@ int _handle_new_connection(download_clientinfo_slot *clientinfo_list, download_c
                (request_clientinfo->clientfd, SOL_SOCKET,
                SO_PEERCRED, &request_clientinfo->credentials,
                &cr_len) == 0) {
-               TRACE_DEBUG_MSG
+               TRACE_DEBUG_INFO_MSG
                        ("Client Info : pid=%d, uid=%d, gid=%d\n",
                        request_clientinfo->credentials.pid,
                        request_clientinfo->credentials.uid,
@@ -239,7 +267,7 @@ int _handle_new_connection(download_clientinfo_slot *clientinfo_list, download_c
 
        download_controls type =
                ipc_receive_header(request_clientinfo->clientfd);
-       TRACE_DEBUG_MSG("[ACCEPT] HEADER : [%d] ", type);
+       TRACE_DEBUG_INFO_MSG("[ACCEPT] HEADER : [%d] ", type);
        // first of all, receive requestinfo .
        if (type <= 0 || ipc_receive_request_msg(request_clientinfo) < 0) {
                TRACE_DEBUG_MSG("Ignore this connection, Invalid command");
@@ -248,7 +276,9 @@ int _handle_new_connection(download_clientinfo_slot *clientinfo_list, download_c
        }
 
        if (type == DOWNLOAD_CONTROL_STOP
-               || type == DOWNLOAD_CONTROL_GET_STATE_INFO) {
+               || type == DOWNLOAD_CONTROL_GET_STATE_INFO
+               || type == DOWNLOAD_CONTROL_RESUME
+               || type == DOWNLOAD_CONTROL_PAUSE) {
                // get requestid from socket.
                if (request_clientinfo->requestinfo
                        && request_clientinfo->requestinfo->requestid > 0) {
@@ -257,7 +287,7 @@ int _handle_new_connection(download_clientinfo_slot *clientinfo_list, download_c
                                                        (clientinfo_list,
                                                        request_clientinfo->requestinfo->requestid);
                        if (type == DOWNLOAD_CONTROL_STOP) {
-                               TRACE_DEBUG_MSG("Request : DOWNLOAD_CONTROL_STOP");
+                               TRACE_DEBUG_INFO_MSG("Request : DOWNLOAD_CONTROL_STOP");
                                if (searchindex >= 0) {
                                        if (da_cancel_download
                                                (clientinfo_list[searchindex].clientinfo->req_id)
@@ -304,10 +334,44 @@ int _handle_new_connection(download_clientinfo_slot *clientinfo_list, download_c
                                                }
                                        }
                                        download_provider_db_info_free(dbinfo);
+                                       free(dbinfo);
                                }
                                ipc_send_stateinfo(request_clientinfo);
                                // estabilish the spec of return value.
+                       } else if (type == DOWNLOAD_CONTROL_PAUSE) {
+                               if (searchindex >= 0) {
+                                       if (da_suspend_download
+                                               (clientinfo_list[searchindex].clientinfo->req_id)
+                                               == DA_RESULT_OK) {
+                                               request_clientinfo->state = DOWNLOAD_STATE_PAUSE_REQUESTED;
+                                               request_clientinfo->err = DOWNLOAD_ERROR_NONE;
+                                       } else {
+                                               request_clientinfo->state = DOWNLOAD_STATE_FAILED;
+                                               request_clientinfo->err = DOWNLOAD_ERROR_INVALID_PARAMETER;
+                                       }
+                               } else { // no found
+                                       request_clientinfo->state = DOWNLOAD_STATE_NONE;
+                                       request_clientinfo->err = DOWNLOAD_ERROR_NONE;
+                               }
+                               ipc_send_stateinfo(request_clientinfo);
+                       } else if (type == DOWNLOAD_CONTROL_RESUME) {
+                               if (searchindex >= 0) {
+                                       if (da_resume_download
+                                               (clientinfo_list[searchindex].clientinfo->req_id)
+                                               == DA_RESULT_OK) {
+                                               request_clientinfo->state = DOWNLOAD_STATE_DOWNLOADING;
+                                               request_clientinfo->err = DOWNLOAD_ERROR_NONE;
+                                       } else {
+                                               request_clientinfo->state = DOWNLOAD_STATE_FAILED;
+                                               request_clientinfo->err = DOWNLOAD_ERROR_INVALID_PARAMETER;
+                                       }
+                               } else { // no found
+                                       request_clientinfo->state = DOWNLOAD_STATE_NONE;
+                                       request_clientinfo->err = DOWNLOAD_ERROR_NONE;
+                               }
+                               ipc_send_stateinfo(request_clientinfo);
                        }
+                       ipc_receive_header(request_clientinfo->clientfd);
                }
                clear_clientinfo(request_clientinfo);
                return 0;
@@ -327,16 +391,28 @@ int _handle_new_connection(download_clientinfo_slot *clientinfo_list, download_c
                int searchindex = get_same_request_slot_index(clientinfo_list,
                                                request_clientinfo->requestinfo->requestid);
                if (searchindex < 0) {
-                       TRACE_DEBUG_MSG("Not Found Same Request ID");
-                       // Invalid id
-                       request_clientinfo->state = DOWNLOAD_STATE_FAILED;
-                       request_clientinfo->err = DOWNLOAD_ERROR_INVALID_PARAMETER;
-                       ipc_send_request_stateinfo(request_clientinfo);
-                       clear_clientinfo(request_clientinfo);
-                       return 0;
+                       TRACE_DEBUG_INFO_MSG("Not Found Same Request ID");
+                       /* Try to search history db */
+                       download_dbinfo *dbinfo = download_provider_db_history_get_info(
+                                       request_clientinfo->requestinfo->requestid);
+                       if (dbinfo == NULL) {
+                               /* Try to serach downloading db. The crashed job can not be uploaded to memory */
+                               dbinfo = download_provider_db_get_info(
+                                               request_clientinfo->requestinfo->requestid);
+                               if (dbinfo == NULL) {
+                                       /* Invalid id */
+                                       request_clientinfo->state = DOWNLOAD_STATE_FAILED;
+                                       request_clientinfo->err = DOWNLOAD_ERROR_INVALID_PARAMETER;
+                                       ipc_send_request_stateinfo(request_clientinfo);
+                                       clear_clientinfo(request_clientinfo);
+                                       return 0;
+                               }
+                       }
+                       download_provider_db_info_free(dbinfo);
+                       free(dbinfo);
                } else {        // found request id. // how to deal etag ?
                        // connect to slot.
-                       TRACE_DEBUG_MSG("Found Same Request ID slot[%d]", searchindex);
+                       TRACE_DEBUG_INFO_MSG("Found Same Request ID slot[%d]", searchindex);
                        CLIENT_MUTEX_LOCK(&(request_clientinfo->client_mutex));
                        // close previous socket.
                        if (clientinfo_list[searchindex].clientinfo->clientfd > 0)
@@ -344,7 +420,6 @@ int _handle_new_connection(download_clientinfo_slot *clientinfo_list, download_c
                        // change to new socket.
                        clientinfo_list[searchindex].clientinfo->clientfd =
                                request_clientinfo->clientfd;
-                       ipc_send_request_stateinfo(clientinfo_list[searchindex].clientinfo);
                        // update some info.
                        clientinfo_list[searchindex].clientinfo->requestinfo->callbackinfo =
                                request_clientinfo->requestinfo->callbackinfo;
@@ -353,6 +428,21 @@ int _handle_new_connection(download_clientinfo_slot *clientinfo_list, download_c
                        request_clientinfo->clientfd = 0;       // prevent to not be disconnected.
                        CLIENT_MUTEX_UNLOCK(&(request_clientinfo->client_mutex));
                        clear_clientinfo(request_clientinfo);
+
+                       if (clientinfo_list[searchindex].clientinfo->state
+                               == DOWNLOAD_STATE_READY
+                               || clientinfo_list[searchindex].clientinfo->state
+                               >= DOWNLOAD_STATE_FINISHED) {
+                               active_count = get_downloading_count(clientinfo_list);
+                               if (active_count >= DA_MAX_DOWNLOAD_REQ_AT_ONCE) {
+                                       // deal as pended job.
+                                       _change_pended_download(clientinfo_list[searchindex].clientinfo);
+                                       TRACE_DEBUG_INFO_MSG ("Pended Request is saved to [%d/%d]",
+                                       searchslot, MAX_CLIENT);
+                               } else
+                                       _create_download_thread(&clientinfo_list[searchindex]);
+                       } else
+                               ipc_send_request_stateinfo(clientinfo_list[searchindex].clientinfo);
                        return 0;
                }
        }
@@ -380,46 +470,40 @@ int _handle_new_connection(download_clientinfo_slot *clientinfo_list, download_c
 
        clientinfo_list[searchslot].clientinfo = request_clientinfo;
 
-       TRACE_DEBUG_MSG("New Connection slot [%d] max [%d] max once [%d]",
+       active_count = get_downloading_count(clientinfo_list);
+
+       TRACE_DEBUG_INFO_MSG("New Connection slot [%d/%d] active [%d/%d]",
                                                                                        searchslot,
                                                                                        MAX_CLIENT,
+                                                                                       active_count,
                                                                                        DA_MAX_DOWNLOAD_REQ_AT_ONCE);
 
-       if (get_downloading_count(clientinfo_list) >=
-               DA_MAX_DOWNLOAD_REQ_AT_ONCE) {
-               CLIENT_MUTEX_LOCK(&(clientinfo_list[searchslot].clientinfo->client_mutex));
+       if (active_count >= DA_MAX_DOWNLOAD_REQ_AT_ONCE) {
                // deal as pended job.
-               clientinfo_list[searchslot].clientinfo->state = DOWNLOAD_STATE_PENDED;
-               clientinfo_list[searchslot].clientinfo->err = DOWNLOAD_ERROR_TOO_MANY_DOWNLOADS;
-               download_provider_db_requestinfo_update_column
-                       (clientinfo_list[searchslot].clientinfo,
-                       DOWNLOAD_DB_STATE);
-               ipc_send_request_stateinfo(clientinfo_list[searchslot].clientinfo);
-               TRACE_DEBUG_MSG ("Pended Request is saved to [%d/%d]",
+               _change_pended_download(clientinfo_list[searchslot].clientinfo);
+               TRACE_DEBUG_INFO_MSG ("Pended Request is saved to [%d/%d]",
                        searchslot, MAX_CLIENT);
-               CLIENT_MUTEX_UNLOCK(&(clientinfo_list[searchslot].clientinfo->client_mutex));
-               sleep(5);       // provider need the time of refresh.
        } else {
-               // create thread for receiving the reqeust info from client.
-               // and if possible, it will create the thread for listening the event.
-               if (pthread_create
-                       (&clientinfo_list[searchslot].clientinfo->thread_pid,
-                       &g_download_provider_thread_attr, _start_download,
-                       &clientinfo_list[searchslot]) != 0) {
-                       TRACE_DEBUG_MSG("failed to call pthread_create for client");
-                       TRACE_DEBUG_MSG("Change to pended job");
-                       CLIENT_MUTEX_LOCK(&(clientinfo_list[searchslot].clientinfo->client_mutex));
-                       clientinfo_list[searchslot].clientinfo->state =
-                               DOWNLOAD_STATE_PENDED;
-                       clientinfo_list[searchslot].clientinfo->err =
-                               DOWNLOAD_ERROR_TOO_MANY_DOWNLOADS;
-                       download_provider_db_requestinfo_update_column
-                               (clientinfo_list[searchslot].clientinfo,
-                               DOWNLOAD_DB_STATE);
-                       ipc_send_request_stateinfo(clientinfo_list[searchslot].clientinfo);
-                       CLIENT_MUTEX_UNLOCK(&(clientinfo_list[searchslot].clientinfo->client_mutex));
-                       sleep(5);       // provider need the time of refresh.
+               // Pending First
+               unsigned free_slot_count
+                       = DA_MAX_DOWNLOAD_REQ_AT_ONCE - active_count;
+               int pendedslot = get_pended_slot_index(clientinfo_list);
+               if(pendedslot >= 0) {
+                       TRACE_DEBUG_INFO_MSG ("Free Space [%d]", free_slot_count);
+                       for (;free_slot_count > 0 && pendedslot >= 0; free_slot_count--) {
+                               TRACE_DEBUG_INFO_MSG ("Start pended job [%d]", pendedslot);
+                               _create_download_thread(&clientinfo_list[pendedslot]);
+                               pendedslot = get_pended_slot_index(clientinfo_list);
+                       }
                }
+
+               if (free_slot_count <= 0) { // change to PENDED
+                       // start pended job, deal this job to pended
+                       _change_pended_download(clientinfo_list[searchslot].clientinfo);
+                       TRACE_DEBUG_INFO_MSG ("Pended Request is saved to [%d/%d]",
+                               searchslot, MAX_CLIENT);
+               } else
+                       _create_download_thread(&clientinfo_list[searchslot]);
        }
        return 0;
 }
@@ -437,7 +521,13 @@ int _handle_client_request(download_clientinfo* clientinfo)
 
        switch (msgType = ipc_receive_header(clientinfo->clientfd)) {
        case DOWNLOAD_CONTROL_STOP:
-               TRACE_DEBUG_MSG("DOWNLOAD_CONTROL_STOP");
+               if (clientinfo->state >= DOWNLOAD_STATE_FINISHED) {
+                       // clear slot requested by client after finished download
+                       TRACE_DEBUG_INFO_MSG("request Free slot to main thread");
+                       clear_socket(clientinfo);
+                       break;
+               }
+               TRACE_DEBUG_INFO_MSG("DOWNLOAD_CONTROL_STOP");
                da_ret = da_cancel_download(clientinfo->req_id);
                CLIENT_MUTEX_LOCK(&(clientinfo->client_mutex));
                if (da_ret != DA_RESULT_OK) {
@@ -460,7 +550,7 @@ int _handle_client_request(download_clientinfo* clientinfo)
                CLIENT_MUTEX_UNLOCK(&(clientinfo->client_mutex));
                break;
        case DOWNLOAD_CONTROL_PAUSE:
-               TRACE_DEBUG_MSG("DOWNLOAD_CONTROL_PAUSE");
+               TRACE_DEBUG_INFO_MSG("DOWNLOAD_CONTROL_PAUSE");
                da_ret = da_suspend_download(clientinfo->req_id);
                CLIENT_MUTEX_LOCK(&(clientinfo->client_mutex));
                if (da_ret != DA_RESULT_OK) {
@@ -476,7 +566,7 @@ int _handle_client_request(download_clientinfo* clientinfo)
                CLIENT_MUTEX_UNLOCK(&(clientinfo->client_mutex));
                break;
        case DOWNLOAD_CONTROL_RESUME:
-               TRACE_DEBUG_MSG("DOWNLOAD_CONTROL_RESUME");
+               TRACE_DEBUG_INFO_MSG("DOWNLOAD_CONTROL_RESUME");
                da_ret = da_resume_download(clientinfo->req_id);
                CLIENT_MUTEX_LOCK(&(clientinfo->client_mutex));
                if (da_ret != DA_RESULT_OK) {
@@ -492,13 +582,13 @@ int _handle_client_request(download_clientinfo* clientinfo)
                CLIENT_MUTEX_UNLOCK(&(clientinfo->client_mutex));
                break;
        case DOWNLOAD_CONTROL_GET_STATE_INFO:   // sync call
-               TRACE_DEBUG_MSG("DOWNLOAD_CONTROL_GET_STATE_INFO");
+               TRACE_DEBUG_INFO_MSG("DOWNLOAD_CONTROL_GET_STATE_INFO");
                CLIENT_MUTEX_LOCK(&(clientinfo->client_mutex));
                ipc_send_stateinfo(clientinfo);
                CLIENT_MUTEX_UNLOCK(&(clientinfo->client_mutex));
                break;
        case DOWNLOAD_CONTROL_GET_DOWNLOAD_INFO:        // sync call
-               TRACE_DEBUG_MSG("DOWNLOAD_CONTROL_GET_DOWNLOAD_INFO");
+               TRACE_DEBUG_INFO_MSG("DOWNLOAD_CONTROL_GET_DOWNLOAD_INFO");
                CLIENT_MUTEX_LOCK(&(clientinfo->client_mutex));
                ipc_send_downloadinfo(clientinfo);
                CLIENT_MUTEX_UNLOCK(&(clientinfo->client_mutex));
@@ -527,11 +617,12 @@ void *run_manage_download_server(void *args)
        struct timeval timeout;
        long flexible_timeout;
        download_clientinfo_slot *clientinfo_list;
-       uint searchslot = 0;
-       uint count_downloading_threads = 0;
+       int searchslot = 0;
+       unsigned active_count = 0;
        download_clientinfo *request_clientinfo;
        int check_retry = 1;
        int i = 0;
+       int is_timeout = 0;
 
        socklen_t clientlen;
        struct sockaddr_un listenaddr, clientaddr;
@@ -577,7 +668,7 @@ void *run_manage_download_server(void *args)
        }
 
        maxfd = listenfd;
-       TRACE_DEBUG_MSG("Ready to listen IPC [%d][%s]", listenfd,
+       TRACE_DEBUG_INFO_MSG("Ready to listen IPC [%d][%s]", listenfd,
                        DOWNLOAD_PROVIDER_IPC);
 
        // allocation the array structure for managing the clients.
@@ -612,19 +703,22 @@ void *run_manage_download_server(void *args)
        while (g_main_loop_is_running(mainloop)) {
 
                // clean slots
-               for (i=0; i < MAX_CLIENT; i++) {
+               for (i = 0; i < MAX_CLIENT; i++) {
                        if (!clientinfo_list[i].clientinfo)
                                continue;
                        // clear slot.
                        if (clientinfo_list[i].clientinfo->state >= DOWNLOAD_STATE_FINISHED) {
-                               clear_clientinfoslot(&clientinfo_list[i]);
+                               if (clientinfo_list[i].clientinfo->clientfd <= 0)
+                                       clear_clientinfoslot(&clientinfo_list[i]);
                                continue;
                        }
                }
 
+               is_timeout = 1;
                rset = g_download_provider_socket_readset;
                exceptset = g_download_provider_socket_exceptset;
 
+               memset(&timeout, 0x00, sizeof(struct timeval));
                timeout.tv_sec = flexible_timeout;
 
                if (select((maxfd + 1), &rset, 0, &exceptset, &timeout) < 0) {
@@ -634,22 +728,21 @@ void *run_manage_download_server(void *args)
                        break;
                }
 
-               for (i=0; i < MAX_CLIENT; i++) {  // find the socket received the packet.
+               for (i = 0; i < MAX_CLIENT; i++) {  // find the socket received the packet.
                        if (!clientinfo_list[i].clientinfo)
                                continue;
-                       // ignore it is not started yet.
-                       if (clientinfo_list[i].clientinfo->state <= DOWNLOAD_STATE_READY)
-                               continue;
-                       // ignore if finished
-                       if (clientinfo_list[i].clientinfo->state >= DOWNLOAD_STATE_FINISHED)
-                               continue;
                        //Even if no socket, downloading should be progressed.
                        if (clientinfo_list[i].clientinfo->clientfd <= 0)
                                continue;
                        if (FD_ISSET(clientinfo_list[i].clientinfo->clientfd, &rset) > 0) {
-                               TRACE_DEBUG_MSG("FD_ISSET [%d] readset slot[%d]",
+                               // ignore it is not started yet.
+                               if (clientinfo_list[i].clientinfo->state <= DOWNLOAD_STATE_READY)
+                                       continue;
+                               TRACE_DEBUG_INFO_MSG("FD_ISSET [%d] readset slot[%d]",
                                        clientinfo_list[i].clientinfo->clientfd, i);
                                _handle_client_request(clientinfo_list[i].clientinfo);
+                               if (is_timeout)
+                                       is_timeout = 0;
                        } else if (FD_ISSET(clientinfo_list[i].clientinfo->clientfd, &exceptset) > 0) {
                                TRACE_DEBUG_MSG("FD_ISSET [%d] exceptset slot[%d]", clientinfo_list[i].clientinfo->clientfd, i);
                                clear_clientinfoslot(&clientinfo_list[i]);
@@ -661,7 +754,9 @@ void *run_manage_download_server(void *args)
                        TerminateDaemon(SIGTERM);
                        break;
                } else if (FD_ISSET(listenfd, &rset) > 0) { // new connection
-                       TRACE_DEBUG_MSG("FD_ISSET listenfd rset");
+                       TRACE_DEBUG_INFO_MSG("FD_ISSET listenfd rset");
+                       if (is_timeout)
+                               is_timeout = 0;
                        // reset timeout.
                        flexible_timeout =
                                DOWNLOAD_PROVIDER_CARE_CLIENT_MIN_INTERVAL;
@@ -702,81 +797,48 @@ void *run_manage_download_server(void *args)
                        }
                }
 
-               if (i >= MAX_CLIENT) { // timeout
+               if (is_timeout) { // timeout
                        // If there is better solution to be able to know
                        // the number of downloading threads, replace below rough codes.
-                       count_downloading_threads =
-                               get_downloading_count(clientinfo_list);
+                       active_count = get_downloading_count(clientinfo_list);
                        // check whether the number of downloading is already maximum.
-                       if (count_downloading_threads >=
-                               DA_MAX_DOWNLOAD_REQ_AT_ONCE)
+                       if (active_count >= DA_MAX_DOWNLOAD_REQ_AT_ONCE)
                                continue;
 
-                       // search pended request
-                       for (searchslot = 0; searchslot < MAX_CLIENT;
-                               searchslot++) {
-                               if (clientinfo_list[searchslot].clientinfo) {
-                                       if (clientinfo_list[searchslot].clientinfo->state ==
-                                               DOWNLOAD_STATE_PENDED) {
-                                               TRACE_DEBUG_MSG
-                                                       ("Retry Pended Request [%d/%d] state [%d/%d]",
-                                                       searchslot, MAX_CLIENT,
-                                                       count_downloading_threads,
-                                                       DA_MAX_DOWNLOAD_REQ_AT_ONCE);
-                                               // create thread for restarting the pended download.
-                                               if (pthread_create
-                                                       (&clientinfo_list[searchslot].clientinfo->thread_pid,
-                                                       &g_download_provider_thread_attr,
-                                                       _start_download,
-                                                       &clientinfo_list[searchslot]) != 0) {
-                                                       TRACE_DEBUG_MSG
-                                                               ("failed to call pthread_create for client");
-                                               }
-                                               count_downloading_threads++;
-                                               usleep(1000);   // sleep in busy state.
-                                               break;
-                                       }
+                       unsigned free_slot_count
+                                       = DA_MAX_DOWNLOAD_REQ_AT_ONCE - active_count;
+                       int pendedslot = get_pended_slot_index(clientinfo_list);
+                       if(pendedslot >= 0) {
+                               TRACE_DEBUG_INFO_MSG ("Free Space [%d]", free_slot_count);
+                               for (;free_slot_count > 0 && pendedslot >= 0; free_slot_count--) {
+                                       TRACE_DEBUG_INFO_MSG ("start pended job [%d]", pendedslot);
+                                       if (_create_download_thread(&clientinfo_list[pendedslot]) > 0)
+                                               active_count++;
+                                       pendedslot = get_pended_slot_index(clientinfo_list);
                                }
                        }
 
-                       if (check_retry
-                               && count_downloading_threads <
-                               DA_MAX_DOWNLOAD_REQ_AT_ONCE) {
-                               // Auto re-download feature. ethernet may be connected with other downloading items.
-                               connection_h network_handle = NULL;
-                               connection_ethernet_state_e system_network_state
-                                       = CONNECTION_ETHERNET_STATE_DISCONNECTED;
-                               if (connection_create(&network_handle) < 0) {
-                                       TRACE_DEBUG_MSG
-                                               ("Failed connection_create");
-                                       continue;
-                               }
-                               if (connection_get_ethernet_state(network_handle,
-                                                                                       &system_network_state) !=
-                                       CONNECTION_ERROR_NONE)
-                                       TRACE_DEBUG_MSG
-                                               ("Failed connection_get_ethernet_state");
-                               if (connection_destroy(network_handle) !=
-                                       CONNECTION_ERROR_NONE)
-                                       TRACE_DEBUG_MSG
-                                               ("Failed connection_destroy");
-                               if (system_network_state !=
-                                       CONNECTION_ETHERNET_STATE_CONNECTED)
+                       if (check_retry && free_slot_count > 0) {
+                               // Auto re-download feature. 
+                               // ethernet may be connected with other downloading items.
+                               if (get_network_status() < 0)
                                        continue;
+
                                // check auto-retrying list regardless state. pended state is also included to checking list.
                                int i = 0;
                                download_dbinfo_list *db_list =
                                        download_provider_db_get_list(DOWNLOAD_STATE_NONE);
                                if (!db_list || db_list->count <= 0) {
-                                       TRACE_DEBUG_MSG
+                                       TRACE_DEBUG_INFO_MSG
                                                ("provider does not need to check DB anymore. in this life.");
-                                       check_retry = 0;        // provider does not need to check DB anymore. in this life.
+                                       // provider does not need to check DB anymore. in this life.
+                                       check_retry = 0;
                                        if (db_list)
                                                download_provider_db_list_free(db_list);
                                        continue;
                                }
                                for (i = 0;
-                                       count_downloading_threads <
+                                       active_count <
                                        DA_MAX_DOWNLOAD_REQ_AT_ONCE
                                        && i < db_list->count; i++) {
                                        if (db_list->item[i].requestid <= 0)
@@ -784,14 +846,14 @@ void *run_manage_download_server(void *args)
                                        if (get_same_request_slot_index
                                                (clientinfo_list,db_list->item[i].requestid) < 0) {
                                                // not found requestid in memory
-                                               TRACE_DEBUG_MSG
+                                               TRACE_DEBUG_INFO_MSG
                                                        ("Retry download [%d]",
                                                        db_list->item[i].requestid);
                                                //search empty slot. copy db info to slot.
                                                searchslot =
                                                        get_empty_slot_index(clientinfo_list);
                                                if (searchslot < 0) {
-                                                       TRACE_DEBUG_MSG
+                                                       TRACE_DEBUG_INFO_MSG
                                                                ("download-provider is busy, try later");
                                                        flexible_timeout =
                                                                flexible_timeout * 2;
@@ -813,30 +875,18 @@ void *run_manage_download_server(void *args)
                                                        continue;
                                                }
 
+                                               CLIENT_MUTEX_INIT(&(request_clientinfo->client_mutex), NULL);
+                                               request_clientinfo->state = DOWNLOAD_STATE_READY;
                                                clientinfo_list[searchslot].clientinfo =
                                                        request_clientinfo;
 
-                                               TRACE_DEBUG_MSG
+                                               TRACE_DEBUG_INFO_MSG
                                                        ("Retry download [%d/%d][%d/%d]",
                                                        searchslot, MAX_CLIENT,
-                                                       count_downloading_threads,
+                                                       active_count,
                                                        DA_MAX_DOWNLOAD_REQ_AT_ONCE);
-                                               if (pthread_create
-                                                       (&clientinfo_list[searchslot].clientinfo->thread_pid,
-                                                       &g_download_provider_thread_attr,
-                                                       _start_download,
-                                                       &clientinfo_list[searchslot])
-                                                       != 0) {
-                                                       TRACE_DEBUG_MSG
-                                                               ("failed to call pthread_create for client");
-                                                       clientinfo_list[searchslot].clientinfo->state =
-                                                               DOWNLOAD_STATE_PENDED;
-                                                       clientinfo_list[searchslot].clientinfo->err =
-                                                               DOWNLOAD_ERROR_TOO_MANY_DOWNLOADS;
-                                                       sleep(5);
-                                               }
-                                               count_downloading_threads++;
-                                               usleep(1000);   // sleep in busy state.
+                                               if (_create_download_thread(&clientinfo_list[searchslot]) > 0)
+                                                       active_count++;
                                        }
                                }
                                if (i >= db_list->count)        // do not search anymore.
@@ -845,7 +895,7 @@ void *run_manage_download_server(void *args)
                        }
 
                        // save system resource (CPU)
-                       if (check_retry == 0 && count_downloading_threads == 0
+                       if (check_retry == 0 && active_count == 0
                                && flexible_timeout <
                                DOWNLOAD_PROVIDER_CARE_CLIENT_MAX_INTERVAL)
                                flexible_timeout = flexible_timeout * 2;
@@ -853,7 +903,7 @@ void *run_manage_download_server(void *args)
                                DOWNLOAD_PROVIDER_CARE_CLIENT_MAX_INTERVAL)
                                flexible_timeout =
                                        DOWNLOAD_PROVIDER_CARE_CLIENT_MAX_INTERVAL;
-                       TRACE_DEBUG_MSG("Next Timeout after [%ld] sec",
+                       TRACE_DEBUG_INFO_MSG("Next Timeout after [%ld] sec",
                                        flexible_timeout);
 
                } // if (i >= MAX_CLIENT) { // timeout
@@ -898,8 +948,8 @@ void __download_info_cb(user_download_info_t *download_info, void *user_data)
                TRACE_DEBUG_MSG("[CRITICAL] clientinfo is NULL");
                return;
        }
-       TRACE_DEBUG_MSG("id[%d],size[%lu]",
-                       download_info->da_dl_req_id, download_info->file_size)
+       TRACE_DEBUG_INFO_MSG("id[%d],size[%lu]",
+                       download_info->da_dl_req_id, download_info->file_size);
 
        if (clientinfo->req_id != download_info->da_dl_req_id) {
                TRACE_DEBUG_MSG("[CRITICAL] req_id[%d] da_dl_req_id[%d}",
@@ -914,7 +964,7 @@ void __download_info_cb(user_download_info_t *download_info, void *user_data)
        if (clientinfo->downloadinfo)
                clientinfo->downloadinfo->file_size = download_info->file_size;
        if (download_info->file_type) {
-               TRACE_DEBUG_MSG("mime[%s]", download_info->file_type);
+               TRACE_DEBUG_INFO_MSG("mime[%s]", download_info->file_type);
 
                len = strlen(download_info->file_type);
                if (len > (DP_MAX_STR_LEN - 1))
@@ -928,7 +978,7 @@ void __download_info_cb(user_download_info_t *download_info, void *user_data)
        }
        if (download_info->tmp_saved_path) {
                char *str = NULL;
-               TRACE_DEBUG_MSG("tmp path[%s]", download_info->tmp_saved_path);
+               TRACE_DEBUG_INFO_MSG("tmp path[%s]", download_info->tmp_saved_path);
                clientinfo->tmp_saved_path =
                        strdup(download_info->tmp_saved_path);
                download_provider_db_requestinfo_update_column(clientinfo,
@@ -944,7 +994,7 @@ void __download_info_cb(user_download_info_t *download_info, void *user_data)
                                        str, len);
                                download_provider_db_requestinfo_update_column
                                        (clientinfo, DOWNLOAD_DB_FILENAME);
-                               TRACE_DEBUG_MSG("content_name[%s]",
+                               TRACE_DEBUG_INFO_MSG("content_name[%s]",
                                                clientinfo->downloadinfo->
                                                content_name);
                        }
@@ -988,13 +1038,18 @@ void __downloading_info_cb(user_downloading_info_t *download_info,
                clientinfo->downloadinginfo->received_size =
                        download_info->total_received_size;
        if (download_info->saved_path) {
-               TRACE_DEBUG_MSG("tmp path[%s]", download_info->saved_path);
+               TRACE_DEBUG_INFO_MSG("tmp path[%s]", download_info->saved_path);
                len = strlen(download_info->saved_path);
                if (len > (DP_MAX_PATH_LEN - 1))
                        len = DP_MAX_PATH_LEN - 1;
                if (clientinfo->downloadinginfo)
                        strncpy(clientinfo->downloadinginfo->saved_path,
                                download_info->saved_path, len);
+               /* FIXME : This should be reviewd again after smack rules is applied */
+               if (chown(clientinfo->downloadinginfo->saved_path,
+                               clientinfo->credentials.uid,
+                               clientinfo->credentials.gid) < 0)
+                       TRACE_DEBUG_INFO_MSG("Fail to chown [%s]", strerror(errno));
        }
 
        static size_t updated_second;
@@ -1027,7 +1082,7 @@ void __notify_cb(user_notify_info_t *notify_info, void *user_data)
                return;
        }
 
-       TRACE_DEBUG_MSG("id[%d],state[%d],err[%d]",
+       TRACE_DEBUG_INFO_MSG("id[%d],state[%d],err[%d]",
                        notify_info->da_dl_req_id,
                        notify_info->state, notify_info->err);
        if (clientinfo->req_id != notify_info->da_dl_req_id) {
@@ -1049,11 +1104,11 @@ void __notify_cb(user_notify_info_t *notify_info, void *user_data)
                                requestinfo->requestid);
                }
                download_provider_db_history_new(clientinfo);
-               TRACE_DEBUG_MSG("[TEST]Finish clientinfo[%p],fd[%d]",
+               TRACE_DEBUG_INFO_MSG("[TEST]Finish clientinfo[%p], fd[%d]",
                        clientinfo, clientinfo->clientfd);
        }
 
-       TRACE_DEBUG_MSG("state[%d]", clientinfo->state);
+       TRACE_DEBUG_INFO_MSG("state[%d]", clientinfo->state);
        ipc_send_stateinfo(clientinfo);
 
        CLIENT_MUTEX_UNLOCK(&(clientinfo->client_mutex));
@@ -1065,44 +1120,44 @@ int __change_state(da_state state)
        switch (state) {
        case DA_STATE_WAITING:
        case DA_STATE_DOWNLOAD_STARTED:
-               TRACE_DEBUG_MSG("DA_STATE_DOWNLOAD_STARTED");
+               TRACE_DEBUG_INFO_MSG("DA_STATE_DOWNLOAD_STARTED");
                ret = DOWNLOAD_STATE_READY;
                break;
        case DA_STATE_DOWNLOADING:
-               TRACE_DEBUG_MSG("DA_STATE_DOWNLOADING");
+               TRACE_DEBUG_INFO_MSG("DA_STATE_DOWNLOADING");
                ret = DOWNLOAD_STATE_DOWNLOADING;
                break;
        case DA_STATE_DOWNLOAD_COMPLETE:
-               TRACE_DEBUG_MSG("DA_STATE_COMPLETE");
+               TRACE_DEBUG_INFO_MSG("DA_STATE_COMPLETE");
                ret = DOWNLOAD_STATE_INSTALLING;
                break;
        case DA_STATE_CANCELED:
-               TRACE_DEBUG_MSG("DA_STATE_CANCELED");
+               TRACE_DEBUG_INFO_MSG("DA_STATE_CANCELED");
                ret = DOWNLOAD_STATE_STOPPED;
                break;
        case DA_STATE_CANCELED_ALL:
-               TRACE_DEBUG_MSG("DA_STATE_CANCELED_ALL");
+               TRACE_DEBUG_INFO_MSG("DA_STATE_CANCELED_ALL");
                break;
        case DA_STATE_SUSPENDED:
-               TRACE_DEBUG_MSG("DA_STATE_SUSPENDED");
+               TRACE_DEBUG_INFO_MSG("DA_STATE_SUSPENDED");
                ret = DOWNLOAD_STATE_PAUSED;
                break;
        case DA_STATE_SUSPENDED_ALL:
-               TRACE_DEBUG_MSG("DA_STATE_SUSPENDED_ALL");
+               TRACE_DEBUG_INFO_MSG("DA_STATE_SUSPENDED_ALL");
                break;
        case DA_STATE_RESUMED:
-               TRACE_DEBUG_MSG("DA_STATE_RESUMED");
+               TRACE_DEBUG_INFO_MSG("DA_STATE_RESUMED");
                ret = DOWNLOAD_STATE_DOWNLOADING;
                break;
        case DA_STATE_RESUMED_ALL:
-               TRACE_DEBUG_MSG("DA_STATE_RESUMED_ALL");
+               TRACE_DEBUG_INFO_MSG("DA_STATE_RESUMED_ALL");
                break;
        case DA_STATE_FINISHED:
-               TRACE_DEBUG_MSG("DA_STATE_FINISHED");
+               TRACE_DEBUG_INFO_MSG("DA_STATE_FINISHED");
                ret = DOWNLOAD_STATE_FINISHED;
                break;
        case DA_STATE_FAILED:
-               TRACE_DEBUG_MSG("DA_STATE_FAILED");
+               TRACE_DEBUG_INFO_MSG("DA_STATE_FAILED");
                ret = DOWNLOAD_STATE_FAILED;
                break;
        default: