1 /*
2 	category_store.c
3 
4 
5 
6 	2003  Plus Huang
7  */
8 
9 #include <stdlib.h>
10 #include "category_store.h"
11 #include "download_thread.h"
12 
category_store_init(CategoryStore * cs)13 void category_store_init (CategoryStore* cs)
14 {
15 	g_static_rec_mutex_init (&cs->mutex);
16 	cs->n_thread = 0;
17 	cs->n_thread_limit = 1;
18 
19 	cs->list_store = gtk_list_store_new (CATEGORY_N_COL,
20 	                                     G_TYPE_POINTER,
21 	                                     G_TYPE_POINTER,
22 	                                     G_TYPE_POINTER);
23 
24 	cs->tree_store = gtk_tree_store_new (CATEGORY_N_COL,
25 	                                     G_TYPE_POINTER,
26 	                                     G_TYPE_POINTER,
27 	                                     G_TYPE_POINTER);
28 }
29 
category_store_clear(CategoryStore * cs)30 void category_store_clear (CategoryStore* cs)
31 {
32 	g_object_unref (cs->list_store);
33 	g_object_unref (cs->tree_store);
34 }
35 
category_store_append(CategoryStore * cs,Category * cate)36 void category_store_append (CategoryStore* cs,
37                             Category* cate)
38 {
39 	GtkTreeIter iter_child;
40 
41 	category_store_lock (cs);
42 
43 	cate->category_store = cs;
44 	cate->valid = TRUE;
45 
46 	// append data to GtkListStore
47 	gtk_list_store_append (cs->list_store,
48 	                       &cate->iter_list_store);
49 	gtk_list_store_set (cs->list_store,
50 	                    &cate->iter_list_store,
51 	                    CATEGORY_COL_DATA, cate,
52 	                    CATEGORY_COL_DOWNLOAD_STORE, &cate->waiting_store,
53 	                    CATEGORY_COL_DOWNLOAD_VIEW,  &cate->waiting_view,
54 	                    -1);
55 
56 	// append data to GtkTreeStore
57 	gtk_tree_store_append (cs->tree_store,
58 	                       &cate->iter_tree_store, NULL);
59 	gtk_tree_store_set (cs->tree_store,
60 	                    &cate->iter_tree_store,
61 	                    CATEGORY_COL_DATA, cate,
62 	                    CATEGORY_COL_DOWNLOAD_STORE, &cate->waiting_store,
63 	                    CATEGORY_COL_DOWNLOAD_VIEW,  &cate->waiting_view,
64 	                    -1);
65 	gtk_tree_store_append (cs->tree_store,
66 	                       &iter_child,
67 	                       &cate->iter_tree_store);
68 	gtk_tree_store_set (cs->tree_store,
69 	                    &iter_child,
70 	                    CATEGORY_COL_DATA, cate,
71 	                    CATEGORY_COL_DOWNLOAD_STORE, &cate->completed_store,
72 	                    CATEGORY_COL_DOWNLOAD_VIEW,  &cate->completed_view,
73 	                    -1);
74 	gtk_tree_store_append (cs->tree_store,
75 	                       &iter_child,
76 	                       &cate->iter_tree_store);
77 	gtk_tree_store_set (cs->tree_store,
78                         &iter_child,
79 	                    CATEGORY_COL_DATA, cate,
80 	                    CATEGORY_COL_DOWNLOAD_STORE, &cate->recycled_store,
81 	                    CATEGORY_COL_DOWNLOAD_VIEW,  &cate->recycled_view,
82 	                    -1);
83 
84 	category_store_unlock (cs);
85 }
86 
category_store_erase(CategoryStore * cs,Category * category)87 void category_store_erase (CategoryStore* cs,
88                            Category* category)
89 {
90 	category_store_lock (cs);
91 
92 	category->valid = FALSE;
93 	category_thread_destroy (category);
94 	category_unref (category);
95 
96 	gtk_list_store_remove (cs->list_store, &category->iter_list_store);
97 	gtk_tree_store_remove (cs->tree_store, &category->iter_tree_store);
98 
99 	category_store_unlock (cs);
100 }
101 
category_store_get_next(CategoryStore * cs,Category * category)102 Category* category_store_get_next (CategoryStore* cs,
103                                    Category* category)
104 {
105 	GtkTreeIter iter;
106 	gboolean    valid = FALSE;
107 	Category*   next_category = NULL;
108 
109 	if (category == NULL || category->valid==FALSE ) {
110 		valid = gtk_tree_model_get_iter_first (GTK_TREE_MODEL (cs->list_store),
111 		                                       &iter);
112 	}
113 	else {
114 		iter = category->iter_list_store;
115 		valid = gtk_tree_model_iter_next (GTK_TREE_MODEL (cs->list_store),
116 		                                  &iter);
117 		if (valid==FALSE) {
118 			valid = gtk_tree_model_get_iter_first (GTK_TREE_MODEL (cs->list_store),
119 			                                       &iter);
120 		}
121 	}
122 
123 	if (valid) {
124 		gtk_tree_model_get (GTK_TREE_MODEL (cs->list_store), &iter,
125 		                    CATEGORY_COL_DATA, &next_category, -1);
126 		if (next_category == category)
127 			return NULL;
128 	}
129 
130 	return next_category;
131 }
132 
133 // thread operate for CategoryStore
category_store_thread_count_request(CategoryStore * cs)134 gint category_store_thread_count_request (CategoryStore* cs)
135 {
136 	return cs->n_thread_limit - cs->n_thread;
137 }
138 
category_store_thread_ref(CategoryStore * cs)139 void category_store_thread_ref (CategoryStore* cs)
140 {
141 	category_store_lock (cs);
142 	cs->n_thread++;
143 	printf ("active category %d\n", cs->n_thread);
144 	category_store_unlock (cs);
145 }
146 
category_store_thread_unref(CategoryStore * cs)147 void category_store_thread_unref (CategoryStore* cs)
148 {
149 	category_store_lock (cs);
150 	cs->n_thread--;
151 	printf ("active category %d\n", cs->n_thread);
152 	category_store_unlock (cs);
153 }
154 
category_store_thread_activate_1(CategoryStore * cs,Category * category)155 void category_store_thread_activate_1 (CategoryStore* cs,
156                                        Category* category)
157 {
158 	category_lock (category);
159 	category_store_lock (cs);
160 
161 	// try to activate another download thread in category until limit
162 	if (category_thread_is_active (category) ||
163 	    category_store_thread_count_request (cs) > 0)
164 	{
165 		category_thread_activate (category);
166 	}
167 
168 	category_store_unlock (cs);
169 	category_unlock (category);
170 }
171 
172 /*
173 void category_store_thread_stop_1 (CategoryStore* cs,
174                                    Category* category)
175 {
176 	Category*    first_category;
177 	Category*    next_category;
178 
179 	category_lock (category);
180 	category_store_lock (cs);
181 
182 	category_thread_destroy (category);
183 	cs->n_thread--;
184 
185 	category_store_unlock (cs);
186 	category_unlock (category);
187 
188 	category_store_thread_activate_next (cs, category);
189 }
190 */
191 
category_store_thread_activate_next(CategoryStore * cs,Category * category)192 void category_store_thread_activate_next (CategoryStore* cs,
193                                           Category* category)
194 {
195 	Category*    first_category;
196 	Category*    next_category;
197 
198 	category_store_lock (cs);
199 
200 	next_category = first_category = category_store_get_next (cs, category);
201 
202 	while (next_category) {
203 		if (category_store_thread_count_request (cs) < 1)
204 			break;
205 
206 		category_thread_activate (next_category);
207 
208 		next_category = category_store_get_next (cs, next_category);
209 
210 		if (next_category==first_category || next_category==category)
211 			break;
212 	}
213 
214 	category_store_unlock (cs);
215 }
216 
category_store_thread_activate(CategoryStore * cs)217 void category_store_thread_activate (CategoryStore* cs)
218 {
219 	Category* category;
220 	GtkTreeIter iter;
221 	gboolean valid;
222 
223 	category_store_lock (cs);
224 
225 	valid = gtk_tree_model_get_iter_first (GTK_TREE_MODEL (cs->list_store),
226 	                                       &iter);
227 	while (valid) {
228 		gtk_tree_model_get ( (GtkTreeModel*)cs->list_store,
229 		                    &iter,
230 		                    CATEGORY_COL_DATA, &category,
231 		                    -1);
232 		category_store_thread_activate_1 (cs, category);
233 		valid = gtk_tree_model_iter_next ( (GtkTreeModel*)cs->list_store,
234 		                                  &iter);
235 	}
236 
237 	category_store_unlock (cs);
238 }
239 
category_store_thread_stop(CategoryStore * cs)240 void category_store_thread_stop (CategoryStore* cs)
241 {
242 	Category* category;
243 	GtkTreeIter iter;
244 	gboolean valid;
245 
246 	valid = gtk_tree_model_get_iter_first (GTK_TREE_MODEL (cs->list_store),
247 	                                       &iter);
248 	while (valid) {
249 		gtk_tree_model_get ( (GtkTreeModel*)cs->list_store,
250 		                    &iter,
251 		                    CATEGORY_COL_DATA, &category,
252 		                    -1);
253 		category_thread_stop (category);
254 		valid = gtk_tree_model_iter_next ( (GtkTreeModel*)cs->list_store,
255 		                                  &iter);
256 	}
257 }
258 
category_store_thread_destroy(CategoryStore * cs)259 void category_store_thread_destroy (CategoryStore* cs)
260 {
261 	Category* category;
262 	GtkTreeIter iter;
263 	gboolean valid;
264 
265 	valid = gtk_tree_model_get_iter_first (GTK_TREE_MODEL (cs->list_store),
266 	                                       &iter);
267 	while (valid) {
268 		gtk_tree_model_get ( (GtkTreeModel*)cs->list_store,
269 		                    &iter,
270 		                    CATEGORY_COL_DATA, &category,
271 		                    -1);
272 		category_thread_destroy (category);
273 		valid = gtk_tree_model_iter_next ( (GtkTreeModel*)cs->list_store,
274 		                                  &iter);
275 	}
276 }
277 
278