4 * Copyright (c) 2014 Samsung Electronics Co., Ltd. All rights reserved.
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
10 * http://www.apache.org/licenses/LICENSE-2.0
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.
24 * @desc application statistics entity helper functions
32 #include "net-cls-cgroup.h"
38 static void free_app(gpointer data)
40 struct application_stat *app_stat = (struct application_stat *)data;
44 if (app_stat->application_id)
45 free(app_stat->application_id);
50 static gint compare_classid(gconstpointer a, gconstpointer b,
51 gpointer __attribute__((__unused__)) userdata)
53 const struct classid_iftype_key *a_key = (struct classid_iftype_key*)a;
54 const struct classid_iftype_key *b_key = (struct classid_iftype_key*)b;
57 ret = a_key->classid - b_key->classid;
61 ret = a_key->iftype - b_key->iftype;
65 return strcmp(a_key->ifname, b_key->ifname);
68 static void free_stat(gpointer data)
73 struct application_stat_tree *create_app_stat_tree(void)
77 struct application_stat_tree *app_stat_tree;
79 (struct application_stat_tree *) malloc
80 (sizeof(struct application_stat_tree));
82 _E("Malloc of create_app_stat_tree failed\n");
87 (GTree *)g_tree_new_full(compare_classid,
90 app_stat_tree->last_touch_time = time(0);
91 ret = pthread_rwlock_init(&app_stat_tree->guard, NULL);
93 strerror_r(ret, buf, sizeof(buf));
94 _E("Could not initialize tree guard %s.", buf);
101 void free_app_stat_tree(struct application_stat_tree *app_stat_tree)
103 /* do not check null pointer because it makes g_tree_destroy */
104 ret_msg_if(app_stat_tree == NULL,
105 "Please provide valid app_stat_tree!");
106 g_tree_destroy((GTree *)app_stat_tree->tree);
109 void nulify_app_stat_tree(struct application_stat_tree **app_stat_tree)
111 free_app_stat_tree(*app_stat_tree);
112 free(*app_stat_tree);
113 *app_stat_tree = NULL;
116 traffic_stat_tree *create_traffic_stat_tree(void)
118 return g_tree_new_full(compare_classid, NULL, NULL, free_stat);
121 void free_traffic_stat_tree(traffic_stat_tree *tree)
123 g_tree_destroy((GTree *) tree);
126 static gboolean set_app_id(gpointer key, gpointer value,
127 void __attribute__((__unused__)) *data)
129 /* Open closed principle would be better here */
130 struct application_stat *stat = (struct application_stat *)value;
131 u_int32_t classid = ((struct classid_iftype_key*)key)->classid;
133 /* No need to request update classid table per each app entry */
134 stat->application_id = get_app_id_by_classid(classid, false);
138 static inline void identify_application(
139 struct application_stat_tree *app_stat_tree)
141 g_tree_foreach(app_stat_tree->tree, (GTraverseFunc)set_app_id, NULL);
144 static gboolean fill_incomming(gpointer key,
145 gpointer value, gpointer data)
147 struct application_stat_tree *app_tree =
148 (struct application_stat_tree *)data;
149 struct traffic_stat *in_event = (struct traffic_stat *)value;
151 struct application_stat *app_stat = NULL;
152 if (!is_allowed_ifindex(in_event->ifindex))
155 app_stat = (struct application_stat *)
156 g_tree_lookup((GTree *)app_tree->tree, key);
158 app_stat->rcv_count += in_event->bytes;
160 app_stat = g_new(struct application_stat, 1);
161 memset(app_stat, 0, sizeof(struct application_stat));
162 app_stat->rcv_count = in_event->bytes;
163 g_tree_insert((GTree *)app_tree->tree, key, app_stat);
165 app_stat->delta_rcv += in_event->bytes;
167 /*only for debug purpose*/
168 if (!app_stat->ifindex)
169 app_stat->ifindex = in_event->ifindex;
171 app_stat->is_roaming = get_roaming();
175 static gboolean fill_outgoing(gpointer key,
176 gpointer value, gpointer data)
178 struct application_stat_tree *app_tree =
179 (struct application_stat_tree *)data;
180 struct traffic_stat *out_event = (struct traffic_stat *)value;
182 struct application_stat *app_stat = (struct application_stat *)
183 g_tree_lookup((GTree *)app_tree->tree, key);
185 app_stat->snd_count += out_event->bytes;
187 app_stat = g_new(struct application_stat, 1);
188 memset(app_stat, 0, sizeof(struct application_stat));
189 app_stat->snd_count = out_event->bytes;
190 g_tree_insert((GTree *)app_tree->tree, key, app_stat);
192 app_stat->delta_snd += out_event->bytes;
194 if (!app_stat->ifindex)
195 app_stat->ifindex = out_event->ifindex;
197 if (!app_stat->is_roaming)
198 app_stat->is_roaming = get_roaming();
203 static void fill_result(traffic_stat_tree *tree_in,
204 traffic_stat_tree *tree_out,
205 struct application_stat_tree *result)
208 g_tree_foreach(tree_in, (GTraverseFunc)fill_incomming, result);
209 g_tree_foreach(tree_out, (GTraverseFunc)fill_outgoing, result);
212 resourced_ret_c prepare_application_stat(traffic_stat_tree *tree_in,
213 traffic_stat_tree *tree_out,
214 struct application_stat_tree *result,
215 volatile struct daemon_opts *opts)
217 fill_result(tree_in, tree_out, result);
218 identify_application(result);
220 return RESOURCED_ERROR_NONE;