static void _wi_timer_thread(wi_runtime_instance_t *argument) { wi_pool_t *pool; wi_timer_t *timer, *fire_timer; wi_time_interval_t interval, diff; wi_boolean_t locked; pool = wi_pool_init(wi_pool_alloc()); while(true) { fire_timer = NULL; locked = true; interval = wi_time_interval(); timer = _wi_timer_first_timer(); if(!timer) { locked = wi_condition_lock_lock_when_condition(_wi_timer_lock, 1, 0.0); timer = _wi_timer_first_timer(); interval = wi_time_interval(); if(timer && timer->fire - interval <= _WI_TIMER_MINIMUM_INTERVAL) fire_timer = timer; } else { diff = timer->fire - interval; if(diff <= _WI_TIMER_MINIMUM_INTERVAL) { fire_timer = timer; locked = false; } else { locked = wi_condition_lock_lock_when_condition(_wi_timer_lock, 1, diff); if(!locked) fire_timer = _wi_timer_first_timer(); } } if(locked) wi_condition_lock_unlock_with_condition(_wi_timer_lock, 0); if(fire_timer) { _wi_timer_invalidate(fire_timer); wi_timer_fire(fire_timer); if(timer->repeats) _wi_timer_schedule(fire_timer); } wi_pool_drain(pool); } wi_release(pool); }
void wd_transfers_remove_client(wd_client_t *client) { wi_list_node_t *node, *next_node; wd_transfer_t *transfer; wi_boolean_t update = false; wi_list_wrlock(wd_transfers); for(node = wi_list_first_node(wd_transfers); node; node = next_node) { next_node = wi_list_node_next_node(node); transfer = wi_list_node_data(node); if(transfer->state <= WD_TRANSFER_RUNNING && transfer->client == client) { if(transfer->state == WD_TRANSFER_RUNNING) { wi_list_unlock(wd_transfers); wd_transfer_set_state(transfer, WD_TRANSFER_STOP); wi_condition_lock_lock_when_condition(transfer->state_lock, WD_TRANSFER_STOPPED, 5.0); wi_condition_lock_unlock(transfer->state_lock); wi_list_wrlock(wd_transfers); } else { wi_list_remove_node(wd_transfers, node); update = true; } } } wi_list_unlock(wd_transfers); if(update) wd_transfers_update_queue(); }
static wi_boolean_t wd_transfers_wait_until_ready(wd_transfer_t *transfer, wd_user_t *user, wi_p7_message_t *message) { wi_p7_message_t *reply; wi_uinteger_t queue; wi_p7_uint32_t transaction; while(true) { if(wi_condition_lock_lock_when_condition(transfer->queue_lock, 1, 1.0)) { queue = transfer->queue; wi_condition_lock_unlock_with_condition(transfer->queue_lock, 0); if(queue > 0) { reply = wi_p7_message_with_name(WI_STR("wired.transfer.queue"), wd_p7_spec); wi_p7_message_set_string_for_name(reply, transfer->path, WI_STR("wired.file.path")); wi_p7_message_set_uint32_for_name(reply, queue, WI_STR("wired.transfer.queue_position")); if(wi_p7_message_get_uint32_for_name(message, &transaction, WI_STR("wired.transaction"))) wi_p7_message_set_uint32_for_name(reply, transaction, WI_STR("wired.transaction")); if(!wd_user_write_message(user, 30.0, reply)) { wi_log_error(WI_STR("Could not write message \"%@\" to %@: %m"), wi_p7_message_name(reply), wd_user_identifier(user)); return false; } } if(queue == 0 || wd_user_state(user) != WD_USER_LOGGED_IN) return true; } } }
void wd_transfers_remove_user(wd_user_t *user) { wd_transfer_t *transfer; wi_boolean_t update = false; wi_uinteger_t i, count; wd_transfer_state_t state; wi_lock_lock(wd_transfers_update_queue_lock); wi_array_wrlock(wd_transfers); count = wi_array_count(wd_transfers); for(i = 0; i < count; i++) { transfer = WI_ARRAY(wd_transfers, i); if(transfer->user == user) { state = wd_transfer_state(transfer); if(state == WD_TRANSFER_RUNNING) { wi_array_unlock(wd_transfers); wd_transfer_set_state(transfer, WD_TRANSFER_STOP); wi_condition_lock_lock_when_condition(transfer->state_lock, WD_TRANSFER_STOPPED, 1.0); wi_condition_lock_unlock(transfer->state_lock); wi_array_wrlock(wd_transfers); } else if(state == WD_TRANSFER_QUEUED || state == WD_TRANSFER_WAITING) { if(transfer->timer) wd_transfer_remove_timer(transfer); wi_mutable_array_remove_data_at_index(wd_transfers, i); count--; i--; update = true; } } } wi_array_unlock(wd_transfers); if(update) wd_transfers_update_queue(); wi_lock_unlock(wd_transfers_update_queue_lock); }
void wi_test_fsevents(void) { #ifdef WI_PTHREADS wi_string_t *directory; wi_test_fsevents_fsevents = wi_fsevents_init(wi_fsevents_alloc()); if(!wi_test_fsevents_fsevents) { if(wi_error_domain() != WI_ERROR_DOMAIN_LIBWIRED && wi_error_code() != WI_ERROR_FSEVENTS_NOTSUPP) WI_TEST_ASSERT_NOT_NULL(wi_test_fsevents_fsevents, "%m"); return; } directory = wi_fs_temporary_path_with_template(WI_STR("/tmp/libwired-fsevents.XXXXXXXX")); wi_fs_create_directory(directory, 0700); wi_fsevents_add_path(wi_test_fsevents_fsevents, directory); wi_fsevents_set_callback(wi_test_fsevents_fsevents, wi_test_fsevents_callback); wi_test_fsevents_lock = wi_condition_lock_init_with_condition(wi_condition_lock_alloc(), 0); if(!wi_thread_create_thread(wi_test_fsevents_thread, NULL)) WI_TEST_FAIL("%m"); wi_thread_sleep(0.1); wi_string_write_to_file(WI_STR("foo"), wi_string_by_appending_path_component(directory, WI_STR("file"))); wi_condition_lock_lock_when_condition(wi_test_fsevents_lock, 1, 0.0); if(!wi_test_fsevents_path) WI_TEST_FAIL("No fsevents callback received"); else WI_TEST_ASSERT_EQUAL_INSTANCES(wi_test_fsevents_path, directory, ""); wi_condition_lock_unlock(wi_test_fsevents_lock); wi_fs_delete_path(directory); wi_release(wi_test_fsevents_lock); wi_release(wi_test_fsevents_fsevents); wi_release(wi_test_fsevents_path); #endif }
void wi_test_timer(void) { #ifdef WI_PTHREADS wi_timer_t *timer; _wi_test_timer_lock = wi_autorelease(wi_condition_lock_init_with_condition(wi_condition_lock_alloc(), 0)); timer = wi_autorelease(wi_timer_init_with_function(wi_timer_alloc(), _wi_test_timer_function, 0.001, false)); wi_timer_schedule(timer); if(wi_condition_lock_lock_when_condition(_wi_test_timer_lock, 1, 1.0)) { WI_TEST_ASSERT_EQUALS(_wi_test_timer_hits, 5U, ""); wi_condition_lock_unlock(_wi_test_timer_lock); } else { WI_TEST_FAIL("Timed out waiting for timer, currently at %u %s", _wi_test_timer_hits, _wi_test_timer_hits == 1 ? "hit" : "hits"); } #endif }
void wi_test_filesystem_events(void) { #if defined(WI_FILESYSTEM_EVENTS) wi_filesystem_events_t *filesystem_events; wi_string_t *path; wi_boolean_t result; _wi_test_filesystem_events_lock = wi_autorelease(wi_condition_lock_init_with_condition(wi_condition_lock_alloc(), 0)); _wi_test_filesystem_events_paths = wi_mutable_set(); path = wi_filesystem_temporary_path_with_template(WI_STR("/tmp/libwired-test-filesystem.XXXXXXX")); WI_TEST_ASSERT_NOT_NULL(path, ""); result = wi_filesystem_create_directory_at_path(path); WI_TEST_ASSERT_TRUE(result, ""); filesystem_events = wi_filesystem_events(); WI_TEST_ASSERT_NOT_NULL(filesystem_events, ""); result = wi_filesystem_events_add_path_with_callback(filesystem_events, path, _wi_test_filesystem_events_callback); WI_TEST_ASSERT_TRUE(result, ""); result = wi_string_write_utf8_string_to_path(WI_STR("hello world"), wi_string_by_appending_path_component(path, WI_STR("foobar"))); WI_TEST_ASSERT_TRUE(result, ""); if(!wi_condition_lock_lock_when_condition(_wi_test_filesystem_events_lock, 1, 1.0)) WI_TEST_FAIL("timed out waiting for filesystem events thread"); WI_TEST_ASSERT_EQUAL_INSTANCES(_wi_test_filesystem_events_paths, wi_set_with_data(path, NULL), ""); wi_condition_lock_unlock(_wi_test_filesystem_events_lock); #endif }
void wd_transfers_remove_user(wd_user_t *user, wi_boolean_t removingallusers) { wi_enumerator_t *enumerator; wi_string_t *key; wd_user_t *each_user; wd_transfer_t *transfer; wi_uinteger_t i, count; wi_boolean_t update = false, present = false; key = wd_transfers_transfer_key_for_user(user); if(!key) return; if(!removingallusers) { wi_dictionary_rdlock(wd_users); enumerator = wi_dictionary_data_enumerator(wd_users); while((each_user = wi_enumerator_next_data(enumerator))) { if(wd_user_state(each_user) == WD_USER_LOGGED_IN && wi_is_equal(wd_transfers_transfer_key_for_user(each_user), key)) { present = true; break; } } wi_dictionary_unlock(wd_users); } if(!present) { wi_array_wrlock(wd_transfers); count = wi_array_count(wd_transfers); for(i = 0; i < count; i++) { transfer = WI_ARRAY(wd_transfers, i); if(wi_is_equal(key, transfer->key)) { wd_user_set_state(transfer->user, WD_USER_DISCONNECTED); if(transfer->state == WD_TRANSFER_RUNNING) { if(wi_condition_lock_lock_when_condition(transfer->finished_lock, 1, 1.0)) wi_condition_lock_unlock(transfer->finished_lock); } else { wi_mutable_array_remove_data_at_index(wd_transfers, i); i--; count--; update = true; } } } if(update) { wi_condition_lock_lock(wd_transfers_queue_lock); wi_condition_lock_unlock_with_condition(wd_transfers_queue_lock, 1); } wi_array_unlock(wd_transfers); } }
static void wd_transfers_queue_thread(wi_runtime_instance_t *argument) { wi_pool_t *pool; wi_enumerator_t *enumerator; wi_mutable_dictionary_t *key_queues; wi_mutable_array_t *key_queue, *keys; wi_string_t *key; wd_transfer_t *transfer; wd_account_t *account; wi_uinteger_t user_downloads, user_uploads, user_transfers; wi_uinteger_t new_position, position, queue, i, count, longest_queue; pool = wi_pool_init(wi_pool_alloc()); key_queues = wi_dictionary_init(wi_mutable_dictionary_alloc()); while(true) { wi_mutable_dictionary_remove_all_data(key_queues); wi_condition_lock_lock_when_condition(wd_transfers_queue_lock, 1, 0.0); wi_array_rdlock(wd_transfers); longest_queue = 0; enumerator = wi_array_data_enumerator(wd_transfers); while((transfer = wi_enumerator_next_data(enumerator))) { wi_condition_lock_lock(transfer->queue_lock); if(transfer->state == WD_TRANSFER_QUEUED && transfer->queue != 0) { key_queue = wi_dictionary_data_for_key(key_queues, transfer->key); if(!key_queue) { key_queue = wi_mutable_array(); wi_mutable_dictionary_set_data_for_key(key_queues, key_queue, transfer->key); } wi_mutable_array_add_data(key_queue, transfer); if(wi_array_count(key_queue) > longest_queue) longest_queue = wi_array_count(key_queue); } wi_condition_lock_unlock(transfer->queue_lock); } keys = wi_autorelease(wi_mutable_copy(wi_dictionary_keys_sorted_by_value(key_queues, wd_transfers_queue_compare))); position = 1; count = wi_array_count(keys); while(longest_queue > 0) { for(i = 0; i < count; i++) { key = WI_ARRAY(keys, i); key_queue = wi_dictionary_data_for_key(key_queues, key); if(wi_array_count(key_queue) > 0) { transfer = WI_ARRAY(key_queue, 0); account = wd_user_account(transfer->user); wi_lock_lock(wd_transfers_status_lock); if(transfer->type == WD_TRANSFER_DOWNLOAD) { wi_dictionary_rdlock(wd_transfers_user_downloads); user_downloads = wd_account_transfer_download_limit(account); user_transfers = (wi_integer_t) wi_dictionary_data_for_key(wd_transfers_user_downloads, transfer->key); queue = ((wd_transfers_total_downloads > 0 && wd_transfers_active_downloads >= wd_transfers_total_downloads) || (user_downloads > 0 && user_transfers >= user_downloads)); wi_dictionary_unlock(wd_transfers_user_downloads); } else { wi_dictionary_rdlock(wd_transfers_user_uploads); user_uploads = wd_account_transfer_upload_limit(account); user_transfers = (wi_integer_t) wi_dictionary_data_for_key(wd_transfers_user_uploads, transfer->key); queue = ((wd_transfers_total_uploads > 0 && wd_transfers_active_uploads >= wd_transfers_total_uploads) || (user_uploads > 0 && user_transfers >= user_uploads)); wi_dictionary_unlock(wd_transfers_user_uploads); } wi_lock_unlock(wd_transfers_status_lock); if(queue) new_position = position++; else new_position = 0; if(new_position != (wi_uinteger_t) transfer->queue) { if(new_position == 0) wd_transfers_add_or_remove_transfer(transfer, true); wi_condition_lock_lock(transfer->queue_lock); transfer->queue = new_position; wi_condition_lock_unlock_with_condition(transfer->queue_lock, 1); } wi_mutable_array_remove_data_at_index(key_queue, 0); } } longest_queue--; } wi_array_unlock(wd_transfers); wi_condition_lock_unlock_with_condition(wd_transfers_queue_lock, 0); wi_pool_drain(pool); } wi_release(key_queues); wi_release(pool); }