static void _wi_test_timer_function(wi_timer_t *timer) { wi_condition_lock_lock(_wi_test_timer_lock); if(++_wi_test_timer_hits == 5) { wi_timer_invalidate(timer); wi_condition_lock_unlock_with_condition(_wi_test_timer_lock, 1); } else { wi_timer_schedule(timer); wi_condition_lock_unlock_with_condition(_wi_test_timer_lock, 0); } }
void wd_transfer_loop(wd_transfer_t *transfer) { if(transfer->timer) wd_transfer_remove_timer(transfer); wi_condition_lock_lock(transfer->state_lock); if(transfer->state == WD_TRANSFER_WAITING) { transfer->state = WD_TRANSFER_RUNNING; wi_condition_lock_unlock_with_condition(transfer->state_lock, transfer->state); if(transfer->type == WD_TRANSFER_DOWNLOAD) wd_transfer_download(transfer); else wd_transfer_upload(transfer); } else { wi_condition_lock_unlock(transfer->state_lock); } wi_lock_lock(wd_transfers_update_queue_lock); wi_array_wrlock(wd_transfers); wi_mutable_array_remove_data(wd_transfers, transfer); wi_array_unlock(wd_transfers); wd_transfers_update_queue(); wi_lock_unlock(wd_transfers_update_queue_lock); }
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_apply_settings(wi_set_t *changes) { wd_transfers_total_downloads = wi_config_integer_for_name(wd_config, WI_STR("total downloads")); wd_transfers_total_uploads = wi_config_integer_for_name(wd_config, WI_STR("total uploads")); wd_transfers_total_download_speed = wi_config_integer_for_name(wd_config, WI_STR("total download speed")); wd_transfers_total_upload_speed = wi_config_integer_for_name(wd_config, WI_STR("total upload speed")); wi_condition_lock_lock(wd_transfers_queue_lock); wi_condition_lock_unlock_with_condition(wd_transfers_queue_lock, 1); }
static void _wi_test_filesystem_events_callback(wi_filesystem_events_t *filesystem_events, wi_string_t *path) { wi_condition_lock_lock(_wi_test_filesystem_events_lock); wi_mutable_set_add_data(_wi_test_filesystem_events_paths, path); wi_condition_lock_unlock_with_condition(_wi_test_filesystem_events_lock, 1); wi_filesystem_events_remove_path(filesystem_events, path); }
wi_boolean_t wd_transfers_run_transfer(wd_transfer_t *transfer, wd_user_t *user, wi_p7_message_t *message) { wi_boolean_t result = false; wi_array_wrlock(wd_transfers); wi_mutable_array_add_data(wd_transfers, transfer); wi_array_unlock(wd_transfers); wi_condition_lock_lock(wd_transfers_queue_lock); wi_condition_lock_unlock_with_condition(wd_transfers_queue_lock, 1); if(wd_transfers_wait_until_ready(transfer, user, message)) { wi_condition_lock_lock(transfer->queue_lock); transfer->state = WD_TRANSFER_RUNNING; wi_condition_lock_unlock(transfer->queue_lock); if(transfer->type == WD_TRANSFER_DOWNLOAD) result = wd_transfers_run_download(transfer, user, message); else result = wd_transfers_run_upload(transfer, user, message); wi_condition_lock_lock(transfer->finished_lock); wi_condition_lock_unlock_with_condition(transfer->finished_lock, 1); } else { wi_log_error(WI_STR("Could not process %@ for %@: %m"), (transfer->type == WD_TRANSFER_DOWNLOAD) ? WI_STR("download") : WI_STR("upload"), wd_user_identifier(user)); } if(transfer->queue == 0) wd_transfers_add_or_remove_transfer(transfer, false); wi_array_wrlock(wd_transfers); wi_mutable_array_remove_data(wd_transfers, transfer); wi_array_unlock(wd_transfers); wi_condition_lock_lock(wd_transfers_queue_lock); wi_condition_lock_unlock_with_condition(wd_transfers_queue_lock, 1); return result; }
void wi_timer_invalidate(wi_timer_t *timer) { if(timer->scheduled) { if(!timer->incallback) wi_condition_lock_lock(_wi_timer_lock); _wi_timer_invalidate(timer); if(!timer->incallback) wi_condition_lock_unlock_with_condition(_wi_timer_lock, 1); } }
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); }
static void wi_test_fsevents_thread(wi_runtime_instance_t *instance) { wi_pool_t *pool; pool = wi_pool_init(wi_pool_alloc()); if(!wi_fsevents_run_with_timeout(wi_test_fsevents_fsevents, 1.0)) wi_log_warn(WI_STR("wi_fsevents_run_with_timeout: %m")); wi_condition_lock_lock(wi_test_fsevents_lock); wi_condition_lock_unlock_with_condition(wi_test_fsevents_lock, 1); wi_release(pool); }
void wi_timer_schedule(wi_timer_t *timer) { if(!timer->scheduled) { pthread_once(&_wi_timer_once_control, _wi_timer_create_thread); if(!timer->incallback) wi_condition_lock_lock(_wi_timer_lock); _wi_timer_schedule(timer); if(!timer->incallback) wi_condition_lock_unlock_with_condition(_wi_timer_lock, 1); } }
void wi_timer_reschedule(wi_timer_t *timer, wi_time_interval_t interval) { timer->interval = WI_MAX(interval, _WI_TIMER_MINIMUM_INTERVAL); if(timer->scheduled) _wi_timer_invalidate(timer); if(!timer->incallback) wi_condition_lock_lock(_wi_timer_lock); _wi_timer_schedule(timer); if(!timer->incallback) wi_condition_lock_unlock_with_condition(_wi_timer_lock, 1); }
static void wd_transfer_set_state(wd_transfer_t *transfer, wd_transfer_state_t state) { wi_condition_lock_lock(transfer->state_lock); transfer->state = state; wi_condition_lock_unlock_with_condition(transfer->state_lock, transfer->state); }
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); }