00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #include
00020 #include
00021 #include
00022 #include
00023 #include
00024
00025 #include "configuration.h"
00026 #include "schedular.h"
00027 #include "plugin_schedular.h"
00028 #include "nntpgrab_plugin_schedular.h"
00029 #include "nntpconnection.h"
00030 #include "decoder.h"
00031 #include "nntpgrab_internal.h"
00032
00033 static PluginSchedularExportedFuncs plugin_funcs;
00034 static GModule *plugin = NULL;
00035 static Schedular *schedular = NULL;
00036
00037 typedef struct SchedularClass SchedularClass;
00038
00039 static GType schedular_get_type (void);
00040
00041 static void task_added_callback(const NNTPCollection *collection, const NNTPFile *file);
00042 static void task_removed_callback(const char *collection_name, const char *subject, guint64 total_file_size, guint64 total_file_size_remaining);
00043 static void task_state_changed_callback(const char *collection_name, const char *subject, TaskState old_state, TaskState new_state);
00044 static void collection_added_callback(const char *collection_name);
00045 static void collection_removed_callback(const char *collection_name);
00046 static GList *config_get_avail_servers(void);
00047 static ConfigServer *config_get_server_info(const char *servername);
00048 static ConfigOpts config_get_opts (void);
00049 static gpointer nntp_connection_initialize (const char *servername, NNTPGrabErrCode *err);
00050 static void nntp_connection_destroy (gpointer obj);
00051 static NNTPGrabErrCode nntp_connection_get_part (gpointer obj, const char *collection_name, const NNTPFile *file, const NNTPPart *part, char **reason);
00052 static gboolean decode_file (const char *collection_name, const NNTPFile *file, int *saved_errno);
00053 static void notify_schedular_state_changed (SchedularState new_state, const char *reason);
00054 static void emit_fatal_error (const char *errmsg);
00055 static void emit_part_download_complete (const char *servername, gpointer connection, const char *collection_name, const char *subject, int partnum, int size);
00056 static void emit_part_download_failed (const char *servername, gpointer connection, const char *collection_name, const char *subject, int partnum, int size, gboolean all_servers_tried);
00057 static void emit_task_moved (const char *orig_collection_name, const char *subject, const char *new_collection_name, int old_position, int new_position);
00058 static void emit_collection_moved (const char *collection_name, int old_position, int new_position);
00059 static void emit_file_download_state_update (const char *collection_name, const char *subject, int num_parts_total, int num_parts_done, int num_parts_failed, guint64 file_size, guint64 file_size_remaining, guint64 total_file_size, guint64 total_file_size_remaining);
00060 static void config_changed_callback(Configuration *config, ConfigChangedFlag flag, gpointer data);
00061
00062 struct Schedular
00063 {
00064 GObject parent;
00065
00066 GStaticRWLock rwlock;
00067 Configuration *config;
00068 ConfigOpts opts;
00069 Decoder *decoder;
00070 };
00071
00072 struct SchedularClass
00073 {
00074 GObjectClass parent;
00075 };
00076
00077 G_DEFINE_TYPE(Schedular, schedular, G_TYPE_OBJECT);
00078
00079 static void
00080 schedular_init (Schedular *obj)
00081 {
00082 g_static_rw_lock_init(&obj->rwlock);
00083 }
00084
00085 static void
00086 schedular_finalize (GObject *obj)
00087 {
00088 Schedular *schedular = SCHEDULAR(obj);
00089
00090 if (plugin_funcs.destroy) {
00091 plugin_funcs.destroy();
00092 }
00093
00094 g_module_close(plugin);
00095
00096 g_static_rw_lock_writer_lock(&schedular->rwlock);
00097
00098 g_object_unref(schedular->config);
00099 decoder_destroy(schedular->decoder);
00100
00101 g_static_rw_lock_writer_unlock(&schedular->rwlock);
00102
00103 g_static_rw_lock_free(&schedular->rwlock);
00104 }
00105
00106 static void
00107 schedular_class_init (SchedularClass *klass)
00108 {
00109 GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
00110
00111 gobject_class->finalize = schedular_finalize;
00112 }
00113
00114 Schedular *
00115 schedular_new(Configuration *config, char **errmsg)
00116 {
00117 static GStaticMutex mutex = G_STATIC_MUTEX_INIT;
00118
00119 g_static_mutex_lock(&mutex);
00120
00121 g_assert(schedular == NULL);
00122
00123 if (!plugin) {
00124 char *msg;
00125 PluginSchedularImportedFuncs imported_funcs;
00126 plugin_schedular_init_func init_func;
00127 char *filename;
00128
00129 #ifdef WIN32
00130 #define EXT "-0.dll"
00131 #else
00132 #define EXT ".so"
00133 #endif
00134
00135 if (g_getenv("NNTPGRAB_LIBDIR")) {
00136 filename = g_strdup_printf("%s/libnntpgrab_plugin_schedular%s", g_getenv("NNTPGRAB_LIBDIR"), EXT);
00137 } else {
00138 filename = g_strdup_printf("%s/libnntpgrab_plugin_schedular%s", PLUGIN_DIR, EXT);
00139 }
00140
00141 plugin = g_module_open(filename, G_MODULE_BIND_LOCAL);
00142
00143 g_free(filename);
00144
00145 if (!plugin) {
00146 if (errmsg) {
00147 *errmsg = g_strdup(g_module_error());
00148 }
00149
00150 return NULL;
00151 }
00152
00153 imported_funcs.version = NNTPGRAB_PLUGIN_API_VERSION;
00154 imported_funcs.task_added = task_added_callback;
00155 imported_funcs.task_removed = task_removed_callback;
00156 imported_funcs.task_state_changed = task_state_changed_callback;
00157 imported_funcs.collection_added = collection_added_callback;
00158 imported_funcs.collection_removed = collection_removed_callback;
00159 imported_funcs.config_get_avail_servers = config_get_avail_servers;
00160 imported_funcs.config_get_server_info = config_get_server_info;
00161 imported_funcs.config_get_opts = config_get_opts;
00162 imported_funcs.nntp_connection_initialize = nntp_connection_initialize;
00163 imported_funcs.nntp_connection_destroy = nntp_connection_destroy;
00164 imported_funcs.nntp_connection_get_part = nntp_connection_get_part;
00165 imported_funcs.decode_file = decode_file;
00166 imported_funcs.notify_schedular_state_changed = notify_schedular_state_changed;
00167 imported_funcs.emit_fatal_error = emit_fatal_error;
00168 imported_funcs.emit_part_download_complete = emit_part_download_complete;
00169 imported_funcs.emit_part_download_failed = emit_part_download_failed;
00170 imported_funcs.emit_task_moved = emit_task_moved;
00171 imported_funcs.emit_collection_moved = emit_collection_moved;
00172 imported_funcs.emit_file_download_state_update = emit_file_download_state_update;
00173
00174 if (!g_module_symbol(plugin, "nntpgrab_plugin_schedular_get_version", (gpointer *) &plugin_funcs.get_version)) {
00175 if (errmsg) {
00176 *errmsg = g_strdup(g_module_error());
00177 }
00178
00179 return NULL;
00180 }
00181
00182
00183 if (plugin_funcs.get_version() != NNTPGRAB_PLUGIN_API_VERSION) {
00184 if (errmsg) {
00185 *errmsg = g_strdup_printf(_("Schedular Plugin API mismatch (Plugin API version = %i, expected = %i)"), plugin_funcs.get_version(), NNTPGRAB_PLUGIN_API_VERSION);
00186 }
00187
00188 return NULL;
00189 }
00190
00191 if (!g_module_symbol(plugin, "nntpgrab_plugin_schedular_initialize", (gpointer *) &init_func)) {
00192 if (errmsg) {
00193 *errmsg = g_strdup(g_module_error());
00194 }
00195
00196 return NULL;
00197 }
00198
00199 if (!g_module_symbol(plugin, "nntpgrab_plugin_schedular_destroy", (gpointer *) &plugin_funcs.destroy)) {
00200 if (errmsg) {
00201 *errmsg = g_strdup(g_module_error());
00202 }
00203
00204 return NULL;
00205 }
00206
00207 if (!g_module_symbol(plugin, "nntpgrab_plugin_schedular_start", (gpointer *) &plugin_funcs.start)) {
00208 if (errmsg) {
00209 *errmsg = g_strdup(g_module_error());
00210 }
00211
00212 return NULL;
00213 }
00214
00215 if (!g_module_symbol(plugin, "nntpgrab_plugin_schedular_stop", (gpointer *) &plugin_funcs.stop)) {
00216 if (errmsg) {
00217 *errmsg = g_strdup(g_module_error());
00218 }
00219
00220 return NULL;
00221 }
00222
00223 if (!g_module_symbol(plugin, "nntpgrab_plugin_schedular_get_state", (gpointer *) &plugin_funcs.get_state)) {
00224 if (errmsg) {
00225 *errmsg = g_strdup(g_module_error());
00226 }
00227
00228 return NULL;
00229 }
00230
00231 if (!g_module_symbol(plugin, "nntpgrab_plugin_schedular_add_task_to_queue", (gpointer *) &plugin_funcs.add_task_to_queue)) {
00232 if (errmsg) {
00233 *errmsg = g_strdup(g_module_error());
00234 }
00235
00236 return NULL;
00237 }
00238
00239 if (!g_module_symbol(plugin, "nntpgrab_plugin_schedular_del_task_from_queue", (gpointer *) &plugin_funcs.del_task_from_queue)) {
00240 if (errmsg) {
00241 *errmsg = g_strdup(g_module_error());
00242 }
00243
00244 return NULL;
00245 }
00246
00247 if (!g_module_symbol(plugin, "nntpgrab_plugin_schedular_restart_task", (gpointer *) &plugin_funcs.restart_task)) {
00248 if (errmsg) {
00249 *errmsg = g_strdup(g_module_error());
00250 }
00251
00252 return NULL;
00253 }
00254
00255 if (!g_module_symbol(plugin, "nntpgrab_plugin_schedular_save_queue", (gpointer *) &plugin_funcs.save_queue)) {
00256 if (errmsg) {
00257 *errmsg = g_strdup(g_module_error());
00258 }
00259
00260 return NULL;
00261 }
00262
00263 if (!g_module_symbol(plugin, "nntpgrab_plugin_schedular_foreach_task", (gpointer *) &plugin_funcs.foreach_task)) {
00264 if (errmsg) {
00265 *errmsg = g_strdup(g_module_error());
00266 }
00267
00268 return NULL;
00269 }
00270
00271 if (!g_module_symbol(plugin, "nntpgrab_plugin_schedular_move_task", (gpointer *) &plugin_funcs.move_task)) {
00272 if (errmsg) {
00273 *errmsg = g_strdup(g_module_error());
00274 }
00275
00276 return NULL;
00277 }
00278
00279 if (!g_module_symbol(plugin, "nntpgrab_plugin_schedular_move_collection", (gpointer *) &plugin_funcs.move_collection)) {
00280 if (errmsg) {
00281 *errmsg = g_strdup(g_module_error());
00282 }
00283
00284 return NULL;
00285 }
00286
00287
00288 if (!init_func(imported_funcs, &msg)) {
00289 if (errmsg) {
00290 *errmsg = g_strdup_printf(_("Schedular Plugin initialization failed!\n%s"), msg);
00291 }
00292
00293 g_free(msg);
00294
00295 return NULL;
00296 }
00297
00298 nntpgrab_core_emit_debug_message(_("Schedular plugin initialized"));
00299 }
00300
00301 g_object_ref(config);
00302
00303 schedular = g_object_new(SCHEDULAR_TYPE_OBJECT, NULL);
00304 schedular->config = config;
00305 schedular->decoder = decoder_new(config);
00306 schedular->opts = configuration_get_opts(schedular->config);
00307
00308 g_signal_connect(config, "config_changed", G_CALLBACK(config_changed_callback), NULL);
00309
00310 g_static_mutex_unlock(&mutex);
00311
00312 return schedular;
00313 }
00314
00315 void
00316 schedular_destroy(Schedular *obj)
00317 {
00318 g_object_unref(obj);
00319 }
00320
00321 gboolean
00322 schedular_start(Schedular *obj)
00323 {
00324 g_assert(plugin_funcs.start);
00325
00326 return plugin_funcs.start();
00327 }
00328
00329 gboolean
00330 schedular_stop(Schedular *obj)
00331 {
00332 g_assert(plugin_funcs.stop);
00333
00334 return plugin_funcs.stop(NULL);
00335 }
00336
00337 SchedularState
00338 schedular_get_state (Schedular *obj)
00339 {
00340 g_assert(plugin_funcs.get_state);
00341
00342 return plugin_funcs.get_state();
00343 }
00344
00345 gboolean
00346 schedular_add_task_to_queue(Schedular *obj, const char *collection_name, const NNTPFile *file, char **errmsg)
00347 {
00348 char *msg;
00349
00350 g_assert(plugin_funcs.add_task_to_queue);
00351
00352 msg = g_strdup_printf(_("New task added to queue, collection_name = '%s', subject = '%s'"), collection_name, file->subject);
00353 nntpgrab_core_emit_debug_message(msg);
00354 g_free(msg);
00355
00356 return plugin_funcs.add_task_to_queue(collection_name, file, errmsg);
00357 }
00358
00359 gboolean
00360 schedular_del_task_from_queue(Schedular *obj, const char *collection_name, const char *subject, char **errmsg)
00361 {
00362 char *msg;
00363
00364 g_assert(plugin_funcs.del_task_from_queue);
00365
00366 if (!subject) {
00367 msg = g_strdup_printf(_("Entire collection removed from queue, collection_name = '%s'"), collection_name);
00368 } else {
00369 msg = g_strdup_printf(_("Task removed from queue, collection_name = '%s', subject = '%s'"), collection_name, subject);
00370 }
00371 nntpgrab_core_emit_debug_message(msg);
00372 g_free(msg);
00373
00374 return plugin_funcs.del_task_from_queue(collection_name, subject, errmsg);
00375 }
00376
00377 gboolean
00378 schedular_restart_task(Schedular *obj, const char *collection_name, const char *subject, char **errmsg)
00379 {
00380 char *msg;
00381
00382 g_assert(plugin_funcs.restart_task);
00383
00384 if (!subject) {
00385 msg = g_strdup_printf(_("Entire collection restarted, collection_name = '%s'"), collection_name);
00386 } else {
00387 msg = g_strdup_printf(_("Task restarted, collection_name = '%s', subject = '%s'"), collection_name, subject);
00388 }
00389 nntpgrab_core_emit_debug_message(msg);
00390 g_free(msg);
00391
00392 return plugin_funcs.restart_task(collection_name, subject, errmsg);
00393 }
00394
00395 gboolean
00396 schedular_save_queue(Schedular *obj, char **errmsg)
00397 {
00398 g_assert(plugin_funcs.save_queue);
00399
00400 return plugin_funcs.save_queue(errmsg);
00401 }
00402
00403 struct _foreach_data
00404 {
00405 ForeachCollectionFunc collection_func;
00406 ForeachFileFunc file_func;
00407 ForeachGroupFunc group_func;
00408 gpointer data;
00409 };
00410
00411 static void
00412 foreach_func(gpointer data, gpointer user_data)
00413 {
00414 struct _foreach_data *foreach_data = (struct _foreach_data *) user_data;
00415 NNTPCollection *collection = (NNTPCollection *) data;
00416 GList *list, *list2;
00417
00418 if (foreach_data->collection_func) {
00419 foreach_data->collection_func(collection->collection_name, collection->total_size, collection->total_size_remaining, collection->position, foreach_data->data);
00420 }
00421
00422 if (!foreach_data->group_func && !foreach_data->file_func) {
00423 return;
00424 }
00425
00426 list = collection->files;
00427 while (list) {
00428 NNTPFile *file = (NNTPFile *) list->data;
00429
00430 if (foreach_data->file_func) {
00431 foreach_data->file_func(collection->collection_name, file->subject, file->poster, (gint64) file->stamp, file->file_size, file->file_size_remaining, file->position, g_list_length(file->parts), file->num_parts_downloaded, file->num_parts_failed, file->status, file->real_filename, foreach_data->data);
00432 }
00433
00434 if (foreach_data->group_func) {
00435 list2 = file->groups;
00436 while (list2) {
00437 const char *group = (const char *) list2->data;
00438
00439 foreach_data->group_func(collection->collection_name, file->subject, group, foreach_data->data);
00440
00441 list2 = g_list_next(list2);
00442 }
00443 }
00444
00445 list = g_list_next(list);
00446 }
00447 }
00448
00449 void
00450 schedular_foreach_task(Schedular *obj, ForeachCollectionFunc collection_func, ForeachFileFunc file_func, ForeachGroupFunc group_func, gpointer data)
00451 {
00452 struct _foreach_data foreach_data;
00453
00454 g_assert(plugin_funcs.foreach_task);
00455
00456 foreach_data.collection_func = collection_func;
00457 foreach_data.file_func = file_func;
00458 foreach_data.group_func = group_func;
00459 foreach_data.data = data;
00460
00461 plugin_funcs.foreach_task(foreach_func, &foreach_data);
00462 }
00463
00464 gboolean
00465 schedular_move_task(Schedular *obj, const char *collection_name_src, const char *subject_src, const char *collection_name_dest, int position_dest)
00466 {
00467 return plugin_funcs.move_task(collection_name_src, subject_src, collection_name_dest, position_dest);
00468 }
00469
00470 gboolean
00471 schedular_move_collection(Schedular *obj, const char *collection_name, int new_position)
00472 {
00473 return plugin_funcs.move_collection(collection_name, new_position);
00474 }
00475
00476 static void
00477 task_added_callback(const NNTPCollection *collection, const NNTPFile *file)
00478 {
00479 nntpgrab_core_emit_file_added(collection, file);
00480 }
00481
00482 static void
00483 task_removed_callback(const char *collection_name, const char *subject, guint64 total_file_size, guint64 total_file_size_remaining)
00484 {
00485 nntpgrab_core_emit_file_removed(collection_name, subject, total_file_size, total_file_size_remaining);
00486 }
00487
00488 static void
00489 task_state_changed_callback(const char *collection_name, const char *subject, TaskState old_state, TaskState new_state)
00490 {
00491 nntpgrab_core_emit_file_state_changed(collection_name, subject, old_state, new_state);
00492 }
00493
00494 static void
00495 collection_added_callback(const char *collection_name)
00496 {
00497 nntpgrab_core_emit_collection_added(collection_name);
00498 }
00499
00500 static void
00501 collection_removed_callback(const char *collection_name)
00502 {
00503 nntpgrab_core_emit_collection_removed(collection_name);
00504 }
00505
00506 static GList *
00507 config_get_avail_servers(void)
00508 {
00509 g_assert(schedular);
00510
00511 return configuration_get_avail_servers(schedular->config);
00512 }
00513
00514 static ConfigServer *
00515 config_get_server_info(const char *servername)
00516 {
00517 g_assert(schedular);
00518
00519 return configuration_get_server_info(schedular->config, servername);
00520 }
00521
00522 static ConfigOpts
00523 config_get_opts (void)
00524 {
00525 g_assert(schedular);
00526
00527 return configuration_get_opts(schedular->config);
00528 }
00529
00530 static gpointer
00531 nntp_connection_initialize (const char *servername, NNTPGrabErrCode *err)
00532 {
00533 NNTPConnection *conn;
00534 ConfigServer *server;
00535
00536 server = configuration_get_server_info(schedular->config, servername);
00537 if (!server) {
00538 return NULL;
00539 }
00540
00541 conn = nntpconnection_new(schedular->config, *server);
00542 g_slice_free(ConfigServer, server);
00543
00544 if ((*err = nntpconnection_connect(conn)) != NNTP_ERROR_NONE) {
00545 nntpconnection_destroy(conn);
00546 return NULL;
00547 }
00548
00549 return (gpointer) conn;
00550 }
00551
00552 static void
00553 nntp_connection_destroy (gpointer obj)
00554 {
00555 g_assert(obj != NULL);
00556
00557 if (nntpconnection_get_is_connected(obj)) {
00558 nntpconnection_disconnect(obj);
00559 }
00560
00561 nntpconnection_destroy(obj);
00562 }
00563
00564 static NNTPGrabErrCode
00565 nntp_connection_get_part (gpointer obj, const char *collection_name, const NNTPFile *file, const NNTPPart *part, char **reason)
00566 {
00567 char *filename;
00568 NNTPGrabErrCode ret;
00569
00570 g_assert(obj != NULL);
00571 g_assert(schedular != NULL);
00572
00573
00574 if (!nntpconnection_get_is_connected(obj)) {
00575
00576 nntpgrab_core_emit_debug_message(_("Connection lost. Trying to reconnect"));
00577 if ((ret = nntpconnection_connect(obj)) != NNTP_ERROR_NONE) {
00578 nntpgrab_core_emit_debug_message(_("Reconnect failed"));
00579 nntpconnection_disconnect(obj);
00580 return ret;
00581 }
00582 }
00583
00584 g_static_rw_lock_reader_lock(&schedular->rwlock);
00585 filename = g_strdup_printf("%s%s%s.%i", schedular->opts.temp_directory, G_DIR_SEPARATOR_S, file->tmp_filename, part->partnum);
00586 g_static_rw_lock_reader_unlock(&schedular->rwlock);
00587
00588 if ((ret = nntpconnection_get_part(obj, collection_name, file->subject, part, filename)) != NNTP_ERROR_NONE) {
00589 if (reason) {
00590 switch (ret) {
00591 case NNTP_ERROR_UNABLE_TO_SAVE_PART:
00592 *reason = g_strdup_printf(_("Unable to save part to file '%s'"), filename);
00593 break;
00594 default:
00595 *reason = NULL;
00596 }
00597 }
00598
00599 g_free(filename);
00600 return ret;
00601 }
00602
00603 g_free(filename);
00604
00605 nntpgrab_core_emit_debug_message(_("Saving of part SUCCEEDED"));
00606
00607 return NNTP_ERROR_NONE;
00608 }
00609
00610 static gboolean
00611 decode_file (const char *collection_name, const NNTPFile *file, int *saved_errno)
00612 {
00613 return decoder_decode_file(schedular->decoder, collection_name, file, saved_errno);
00614 }
00615
00616 static void
00617 notify_schedular_state_changed (SchedularState new_state, const char *reason)
00618 {
00619 nntpgrab_core_emit_schedular_state_changed(new_state, reason);
00620 }
00621
00622 static void
00623 emit_fatal_error (const char *errmsg)
00624 {
00625 nntpgrab_core_emit_fatal_error(errmsg);
00626 }
00627
00628 static void
00629 emit_part_download_complete (const char *servername, gpointer connection, const char *collection_name, const char *subject, int partnum, int size)
00630 {
00631 int conn_id = -1;
00632
00633 if (connection) {
00634 conn_id = nntpconnection_get_conn_id((NNTPConnection*) connection);
00635 }
00636
00637 nntpgrab_core_emit_part_done(servername, conn_id, collection_name, subject, partnum, size);
00638 }
00639
00640 static void
00641 emit_part_download_failed (const char *servername, gpointer connection, const char *collection_name, const char *subject, int partnum, int size, gboolean all_servers_tried)
00642 {
00643 int conn_id = -1;
00644
00645 if (connection) {
00646 conn_id = nntpconnection_get_conn_id((NNTPConnection*) connection);
00647 }
00648
00649 nntpgrab_core_emit_part_failed(servername, conn_id, collection_name, subject, partnum, size, all_servers_tried);
00650 }
00651
00652 static void
00653 emit_task_moved (const char *orig_collection_name, const char *subject, const char *new_collection_name, int old_position, int new_position)
00654 {
00655 nntpgrab_core_emit_task_moved(orig_collection_name, subject, new_collection_name, old_position, new_position);
00656 }
00657
00658 static void
00659 emit_collection_moved (const char *collection_name, int old_position, int new_position)
00660 {
00661 nntpgrab_core_emit_collection_moved(collection_name, old_position, new_position);
00662 }
00663
00664 static void
00665 emit_file_download_state_update (const char *collection_name, const char *subject, int num_parts_total, int num_parts_done, int num_parts_failed, guint64 file_size, guint64 file_size_remaining, guint64 total_file_size, guint64 total_file_size_remaining)
00666 {
00667 nntpgrab_core_emit_file_download_state_update(collection_name, subject, num_parts_total, num_parts_done, num_parts_failed, file_size, file_size_remaining, total_file_size, total_file_size_remaining);
00668 }
00669
00670 static void
00671 config_changed_callback (Configuration *config, ConfigChangedFlag flag, gpointer data)
00672 {
00673 g_assert(schedular);
00674
00675 nntpgrab_core_emit_debug_message(_("Schedular: Received config changed signal"));
00676
00677 if (flag == CONFIG_CHANGED_OPTS_CHANGED) {
00678 g_static_rw_lock_writer_lock(&schedular->rwlock);
00679 schedular->opts = configuration_get_opts(config);
00680 g_static_rw_lock_writer_unlock(&schedular->rwlock);
00681 }
00682
00683 if (flag == CONFIG_CHANGED_SERVER_ADDED || flag == CONFIG_CHANGED_SERVER_DELETED) {
00684 if (schedular_get_state(schedular) == SCHEDULAR_STATE_RUNNING) {
00685
00686 schedular_stop(schedular);
00687 schedular_start(schedular);
00688 }
00689 }
00690 }