void client_close(struct client *client) { client_list_remove(client); client_set_expired(client); g_timer_destroy(client->last_activity); if (client->cmd_list) { free_cmd_list(client->cmd_list); client->cmd_list = NULL; } g_queue_foreach(client->deferred_send, deferred_buffer_free, NULL); g_queue_free(client->deferred_send); fifo_buffer_free(client->input); g_log(G_LOG_DOMAIN, LOG_LEVEL_SECURE, "[%u] closed", client->num); g_free(client); }
/* Called with handle_hash lock held */ static void destroy_monitor_handle (GnomeVFSMonitorHandle *handle) { gboolean res; if (handle->pending_timeout) g_source_remove (handle->pending_timeout); g_queue_foreach (handle->pending_callbacks, (GFunc) free_callback_data, NULL); g_queue_free (handle->pending_callbacks); handle->pending_callbacks = NULL; res = g_hash_table_remove (handle_hash, handle->method_handle); if (!res) { g_warning ("gnome-vfs-monitor.c: A monitor handle was destroyed " "before it was added to the method hash table. This " "is a bug in the application and can cause crashes. " "It is probably a race-condition."); } gnome_vfs_uri_unref (handle->uri); g_free (handle); }
void gst_droidcamsrc_dev_stop (GstDroidCamSrcDev * dev) { g_rec_mutex_lock (dev->lock); GST_DEBUG ("dev stop"); if (dev->running) { GST_DEBUG ("stopping preview"); gst_buffer_pool_set_active (dev->pool, FALSE); droid_media_camera_stop_preview (dev->cam); dev->running = FALSE; GST_DEBUG ("stopped preview"); } /* Now we need to empty the queue */ g_mutex_lock (&dev->vfsrc->lock); g_queue_foreach (dev->vfsrc->queue, (GFunc) gst_buffer_unref, NULL); g_queue_clear (dev->vfsrc->queue); g_mutex_unlock (&dev->vfsrc->lock); g_rec_mutex_unlock (dev->lock); }
void passwd_authenticate (PasswdHandler *passwd_handler, const char *current_password, PasswdCallback cb, const gpointer user_data) { GError *error = NULL; /* Don't stop if we've already started chaging password */ if (passwd_handler->changing_password) return; /* Clear data from possible previous attempts to change password */ passwd_handler->new_password = NULL; passwd_handler->chpasswd_cb = NULL; passwd_handler->chpasswd_cb_data = NULL; g_queue_foreach (passwd_handler->backend_stdin_queue, (GFunc) g_free, NULL); g_queue_clear (passwd_handler->backend_stdin_queue); passwd_handler->current_password = current_password; passwd_handler->auth_cb = cb; passwd_handler->auth_cb_data = user_data; /* Spawn backend */ stop_passwd (passwd_handler); if (!spawn_passwd (passwd_handler, &error)) { g_warning ("%s", error->message); g_error_free (error); return; } authenticate (passwd_handler); /* Our IO watcher should now handle the rest */ }
void httpd_client_free(struct httpd_client *client) { assert(client != NULL); if (client->state == RESPONSE) { if (client->write_source_id != 0) g_source_remove(client->write_source_id); if (client->current_page != NULL) page_unref(client->current_page); g_queue_foreach(client->pages, httpd_client_unref_page, NULL); g_queue_free(client->pages); } else fifo_buffer_free(client->input); if (client->metadata) page_unref (client->metadata); g_source_remove(client->read_source_id); g_io_channel_unref(client->channel); g_free(client); }
void gdbmi_value_foreach (const GDBMIValue* val, GFunc func, gpointer user_data) { g_return_if_fail (val != NULL); g_return_if_fail (func != NULL); if (val->type == GDBMI_DATA_LIST) { g_queue_foreach (val->data.list, func, user_data); } else if (val->type == GDBMI_DATA_HASH) { struct _GDBMIForeachHashData hash_data = {NULL, NULL}; hash_data.user_callback = func; hash_data.user_data = user_data; g_hash_table_foreach (val->data.hash, (GHFunc)gdbmi_value_hash_foreach, &hash_data); } else { g_warning ("Can not do foreach for GDBMIValue this type"); } }
static gboolean src_activate_mode (GstPad * pad, GstObject * parent, GstPadMode mode, gboolean active) { GstDtlsEnc *self = GST_DTLS_ENC (parent); gboolean success = TRUE; g_return_val_if_fail (mode == GST_PAD_MODE_PUSH, FALSE); if (active) { GST_DEBUG_OBJECT (self, "src pad activating in push mode"); self->flushing = FALSE; self->send_initial_events = TRUE; success = gst_pad_start_task (pad, (GstTaskFunction) src_task_loop, self->src, NULL); if (!success) { GST_WARNING_OBJECT (self, "failed to activate pad task"); } } else { GST_DEBUG_OBJECT (self, "deactivating src pad"); g_mutex_lock (&self->queue_lock); g_queue_foreach (&self->queue, (GFunc) gst_buffer_unref, NULL); g_queue_clear (&self->queue); self->flushing = TRUE; g_cond_signal (&self->queue_cond_add); g_mutex_unlock (&self->queue_lock); success = gst_pad_stop_task (pad); if (!success) { GST_WARNING_OBJECT (self, "failed to deactivate pad task"); } } return success; }
void mex_proxy_stop (MexProxy *proxy) { MexProxyPrivate *priv; GController *controller; g_return_if_fail (MEX_IS_PROXY (proxy)); priv = proxy->priv; /* There's nothing to do if there's no model set */ if (!priv->model) { priv->started = FALSE; return; } if (!priv->started) return; controller = mex_model_get_controller (priv->model); g_signal_handlers_disconnect_by_func (controller, mex_proxy_controller_changed_cb, proxy); if (priv->timer_timeout) { g_source_remove (priv->timer_timeout); priv->timer_timeout = 0; } g_queue_foreach (priv->to_add, (GFunc)g_object_unref, NULL); g_queue_clear (priv->to_add); priv->started = FALSE; }
static void _master_registerHosts(Master* master) { MAGIC_ASSERT(master); GQueue* hosts = configuration_getHostElements(master->config); g_queue_foreach(hosts, (GFunc)_master_registerHostCallback, master); }
static void _master_registerHostCallback(ConfigurationHostElement* he, Master* master) { MAGIC_ASSERT(master); utility_assert(he); utility_assert(he->id.isSet && he->id.string); guint64 quantity = he->quantity.isSet ? he->quantity.integer : 1; for(guint64 i = 0; i < quantity; i++) { HostParameters* params = g_new0(HostParameters, 1); /* hostname and id params */ const gchar* hostNameBase = he->id.string->str; GString* hostnameBuffer = g_string_new(hostNameBase); if(quantity > 1) { g_string_append_printf(hostnameBuffer, "%"G_GUINT64_FORMAT, i+1); } params->hostname = hostnameBuffer->str; /* cpu params - if they didnt specify a CPU frequency, use the slave machine frequency */ gint slaveCPUFreq = slave_getRawCPUFrequency(master->slave); params->cpuFrequency = he->cpufrequency.isSet ? he->cpufrequency.integer : (slaveCPUFreq > 0) ? (guint64)slaveCPUFreq : 0; if(params->cpuFrequency == 0) { params->cpuFrequency = 2500000; // 2.5 GHz debug("both configured and raw slave cpu frequencies unavailable, using 2500000 KHz"); } gint defaultCPUThreshold = options_getCPUThreshold(master->options); params->cpuThreshold = defaultCPUThreshold > 0 ? defaultCPUThreshold : 0; gint defaultCPUPrecision = options_getCPUPrecision(master->options); params->cpuPrecision = defaultCPUPrecision > 0 ? defaultCPUPrecision : 0; params->logLevel = he->loglevel.isSet ? loglevel_fromStr(he->loglevel.string->str) : options_getLogLevel(master->options); params->heartbeatLogLevel = he->heartbeatloglevel.isSet ? loglevel_fromStr(he->heartbeatloglevel.string->str) : options_getHeartbeatLogLevel(master->options); params->heartbeatInterval = he->heartbeatfrequency.isSet ? (SimulationTime)(he->heartbeatfrequency.integer * SIMTIME_ONE_SECOND) : options_getHeartbeatInterval(master->options); params->heartbeatLogInfo = he->heartbeatloginfo.isSet ? options_toHeartbeatLogInfo(master->options, he->heartbeatloginfo.string->str) : options_getHeartbeatLogInfo(master->options); params->logPcap = (he->logpcap.isSet && !g_ascii_strcasecmp(he->logpcap.string->str, "true")) ? TRUE : FALSE; params->pcapDir = he->pcapdir.isSet ? he->pcapdir.string->str : NULL; /* socket buffer settings - if size is set manually, turn off autotuning */ params->recvBufSize = he->socketrecvbuffer.isSet ? he->socketrecvbuffer.integer : options_getSocketReceiveBufferSize(master->options); params->autotuneRecvBuf = he->socketrecvbuffer.isSet ? FALSE : options_doAutotuneReceiveBuffer(master->options); params->sendBufSize = he->socketsendbuffer.isSet ? he->socketsendbuffer.integer : options_getSocketSendBufferSize(master->options); params->autotuneSendBuf = he->socketsendbuffer.isSet ? FALSE : options_doAutotuneSendBuffer(master->options); params->interfaceBufSize = he->interfacebuffer.isSet ? he->interfacebuffer.integer : options_getInterfaceBufferSize(master->options); params->qdisc = options_getQueuingDiscipline(master->options); /* requested attributes from shadow config */ params->ipHint = he->ipHint.isSet ? he->ipHint.string->str : NULL; params->countrycodeHint = he->countrycodeHint.isSet ? he->countrycodeHint.string->str : NULL; params->citycodeHint = he->citycodeHint.isSet ? he->citycodeHint.string->str : NULL; params->geocodeHint = he->geocodeHint.isSet ? he->geocodeHint.string->str : NULL; params->typeHint = he->typeHint.isSet ? he->typeHint.string->str : NULL; params->requestedBWDownKiBps = he->bandwidthdown.isSet ? he->bandwidthdown.integer : 0; params->requestedBWUpKiBps = he->bandwidthup.isSet ? he->bandwidthup.integer : 0; slave_addNewVirtualHost(master->slave, params); ProcessCallbackArgs processArgs; processArgs.master = master; processArgs.hostParams = params; /* now handle each virtual process the host will run */ g_queue_foreach(he->processes, (GFunc)_master_registerProcessCallback, &processArgs); /* cleanup for next pass through the loop */ g_string_free(hostnameBuffer, TRUE); g_free(params); } }
static void _master_registerPlugins(Master* master) { MAGIC_ASSERT(master); GQueue* plugins = configuration_getPluginElements(master->config); g_queue_foreach(plugins, (GFunc)_master_registerPluginCallback, master); }
gboolean _gtk_source_language_file_parse_version2 (GtkSourceLanguage *language, GtkSourceContextData *ctx_data) { GHashTable *defined_regexes, *styles; gboolean success; GError *error = NULL; gchar *filename; GHashTable *loaded_lang_ids; GQueue *replacements; g_return_val_if_fail (ctx_data != NULL, FALSE); filename = language->priv->lang_file_name; /* TODO: as an optimization tell the parser to merge CDATA * as text nodes (XML_PARSE_NOCDATA), and to ignore blank * nodes (XML_PARSE_NOBLANKS), if it is possible with * xmlTextReader. */ xmlKeepBlanksDefault (0); xmlLineNumbersDefault (1); xmlSubstituteEntitiesDefault (1); DEBUG (xmlPedanticParserDefault (1)); defined_regexes = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free); styles = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, (GDestroyNotify) _gtk_source_style_info_free); loaded_lang_ids = g_hash_table_new_full (g_str_hash, g_str_equal, (GDestroyNotify) xmlFree, NULL); replacements = g_queue_new (); success = file_parse (filename, language, ctx_data, defined_regexes, styles, loaded_lang_ids, replacements, &error); if (success) success = _gtk_source_context_data_finish_parse (ctx_data, replacements->head, &error); if (success) g_hash_table_foreach_steal (styles, (GHRFunc) steal_styles_mapping, language->priv->styles); g_queue_foreach (replacements, (GFunc) _gtk_source_context_replace_free, NULL); g_queue_free (replacements); g_hash_table_destroy (loaded_lang_ids); g_hash_table_destroy (defined_regexes); g_hash_table_destroy (styles); if (!success) { g_warning ("Failed to load '%s': %s", filename, error->message); g_error_free (error); return FALSE; } return TRUE; }
static GstStateChangeReturn gst_decklink_video_src_change_state (GstElement * element, GstStateChange transition) { GstDecklinkVideoSrc *self = GST_DECKLINK_VIDEO_SRC_CAST (element); GstStateChangeReturn ret; switch (transition) { case GST_STATE_CHANGE_NULL_TO_READY: if (!gst_decklink_video_src_open (self)) { ret = GST_STATE_CHANGE_FAILURE; goto out; } break; case GST_STATE_CHANGE_READY_TO_PAUSED: g_mutex_lock (&self->input->lock); self->input->clock_start_time = GST_CLOCK_TIME_NONE; self->input->clock_last_time = 0; self->input->clock_offset = 0; g_mutex_unlock (&self->input->lock); gst_element_post_message (element, gst_message_new_clock_provide (GST_OBJECT_CAST (element), self->input->clock, TRUE)); self->flushing = FALSE; break; case GST_STATE_CHANGE_PAUSED_TO_PLAYING:{ GstClock *clock; clock = gst_element_get_clock (GST_ELEMENT_CAST (self)); if (clock && clock != self->input->clock) { gst_clock_set_master (self->input->clock, clock); } if (clock) gst_object_unref (clock); break; } default: break; } ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition); if (ret == GST_STATE_CHANGE_FAILURE) return ret; switch (transition) { case GST_STATE_CHANGE_PAUSED_TO_READY: gst_element_post_message (element, gst_message_new_clock_lost (GST_OBJECT_CAST (element), self->input->clock)); gst_clock_set_master (self->input->clock, NULL); // Reset calibration to make the clock reusable next time we use it gst_clock_set_calibration (self->input->clock, 0, 0, 1, 1); g_mutex_lock (&self->input->lock); self->input->clock_start_time = GST_CLOCK_TIME_NONE; self->input->clock_last_time = 0; self->input->clock_offset = 0; g_mutex_unlock (&self->input->lock); g_queue_foreach (&self->current_frames, (GFunc) capture_frame_free, NULL); g_queue_clear (&self->current_frames); self->caps_mode = GST_DECKLINK_MODE_AUTO; break; case GST_STATE_CHANGE_PLAYING_TO_PAUSED:{ HRESULT res; GST_DEBUG_OBJECT (self, "Stopping streams"); g_mutex_lock (&self->input->lock); self->input->started = FALSE; g_mutex_unlock (&self->input->lock); res = self->input->input->StopStreams (); if (res != S_OK) { GST_ELEMENT_ERROR (self, STREAM, FAILED, (NULL), ("Failed to stop streams: 0x%08x", res)); ret = GST_STATE_CHANGE_FAILURE; } self->internal_base_time = GST_CLOCK_TIME_NONE; self->external_base_time = GST_CLOCK_TIME_NONE; break; } case GST_STATE_CHANGE_PAUSED_TO_PLAYING:{ g_mutex_lock (&self->input->lock); if (self->input->start_streams) self->input->start_streams (self->input->videosrc); g_mutex_unlock (&self->input->lock); break; } case GST_STATE_CHANGE_READY_TO_NULL: gst_decklink_video_src_close (self); break; default: break; } out: return ret; }
static gboolean negotiate_profile_and_level (GstCapsFeatures * features, GstStructure * s, gpointer user_data) { struct ProfileLevelCtx *ctx = user_data; GstV4l2Object *v4l2object = GST_V4L2_VIDEO_ENC (ctx->self)->v4l2output; GQueue profiles = G_QUEUE_INIT; GQueue levels = G_QUEUE_INIT; gboolean failed = FALSE; if (get_string_list (s, "profile", &profiles)) { GList *l; for (l = profiles.head; l; l = l->next) { struct v4l2_control control = { 0, }; gint v4l2_profile; const gchar *profile = l->data; GST_TRACE_OBJECT (ctx->self, "Trying profile %s", profile); control.id = V4L2_CID_MPEG_VIDEO_H264_PROFILE; control.value = v4l2_profile = v4l2_profile_from_string (profile); if (control.value < 0) continue; if (v4l2_ioctl (v4l2object->video_fd, VIDIOC_S_CTRL, &control) < 0) { GST_WARNING_OBJECT (ctx->self, "Failed to set H264 profile: '%s'", g_strerror (errno)); break; } profile = v4l2_profile_to_string (control.value); if (control.value == v4l2_profile) { ctx->profile = profile; break; } if (g_list_find_custom (l, profile, g_str_equal)) { ctx->profile = profile; break; } } if (profiles.length && !ctx->profile) failed = TRUE; g_queue_foreach (&profiles, (GFunc) g_free, NULL); g_queue_clear (&profiles); } if (!failed && get_string_list (s, "level", &levels)) { GList *l; for (l = levels.head; l; l = l->next) { struct v4l2_control control = { 0, }; gint v4l2_level; const gchar *level = l->data; GST_TRACE_OBJECT (ctx->self, "Trying level %s", level); control.id = V4L2_CID_MPEG_VIDEO_H264_LEVEL; control.value = v4l2_level = v4l2_level_from_string (level); if (control.value < 0) continue; if (v4l2_ioctl (v4l2object->video_fd, VIDIOC_S_CTRL, &control) < 0) { GST_WARNING_OBJECT (ctx->self, "Failed to set H264 level: '%s'", g_strerror (errno)); break; } level = v4l2_level_to_string (control.value); if (control.value == v4l2_level) { ctx->level = level; break; } if (g_list_find_custom (l, level, g_str_equal)) { ctx->level = level; break; } } if (levels.length && !ctx->level) failed = TRUE; g_queue_foreach (&levels, (GFunc) g_free, NULL); g_queue_clear (&levels); } /* If it failed, we continue */ return failed; }
void fm_list_clear (gpointer list) { g_queue_foreach ( (GQueue*)list, (GFunc)FM_LIST (list)->funcs->item_unref, NULL); g_queue_clear ( (GQueue*)list); }
/** * g_queue_free_full: * @queue: a pointer to a #GQueue * @free_func: the function to be called to free each element's data * * Convenience method, which frees all the memory used by a #GQueue, * and calls the specified destroy function on every element's data. * * Since: 2.32 */ void g_queue_free_full (GQueue * queue, GDestroyNotify free_func) { g_queue_foreach (queue, (GFunc) free_func, NULL); g_queue_free (queue); }
void fec_dec_push_fec_packet(fec_dec *dec, GstBuffer *packet) { guint8 *fec_data; guint32 snbase; guint16 seqnum; GList *link; fec_data = GST_BUFFER_DATA(packet) + gst_rtp_buffer_get_header_len(packet); snbase = (((guint16)(fec_data[0])) << 8) | (((guint16)(fec_data[1])) << 0); seqnum = gst_rtp_buffer_get_seq(packet); GST_DEBUG("Received FEC packet, snbase %u, index %u, seqnum %u", snbase, (guint)(fec_data[12]), seqnum); if (snbase == dec->blacklisted_snbase) { GST_DEBUG("Ignoring FEC packet since data from this snbase has been restored already (= the packet is not needed)"); return; } if (g_hash_table_lookup_extended(dec->fec_packet_set, GINT_TO_POINTER(seqnum), NULL, NULL)) { GST_DEBUG("FEC packet with seqnum %u is already in queue - discarding duplicate", seqnum); return; } if (dec->cur_snbase != snbase) { GST_DEBUG("snbase changed from %u to %u - purging FEC queue (%u FEC packets and %u media packets present)", dec->cur_snbase, snbase, dec->num_received_fec_packets, dec->num_received_media_packets); g_queue_foreach(dec->fec_packets, fec_dec_clear_packet, NULL); g_queue_clear(dec->fec_packets); g_hash_table_remove_all(dec->fec_packet_set); dec->num_received_fec_packets = 0; } dec->cur_snbase = snbase; dec->has_snbase = TRUE; dec->received_media_packet_mask = 0; dec->num_received_media_packets = 0; dec->max_packet_size = 0; g_queue_push_tail(dec->fec_packets, gst_buffer_ref(packet)); g_hash_table_add(dec->fec_packet_set, GINT_TO_POINTER(seqnum)); ++dec->num_received_fec_packets; for (link = g_queue_peek_head_link(dec->media_packets); link != NULL;) { GstBuffer *media_packet; guint32 corrected_seqnum; media_packet = link->data; seqnum = gst_rtp_buffer_get_seq(media_packet); corrected_seqnum = fec_dec_correct_seqnum(dec, seqnum); if ((corrected_seqnum < snbase) || (corrected_seqnum > (snbase + dec->num_media_packets - 1))) { GList *old_link; GST_DEBUG("Found media packet with seqnum %u outside bounds [%u, %u] - purging", seqnum, snbase, snbase + dec->num_media_packets - 1); g_hash_table_remove(dec->media_packet_set, GINT_TO_POINTER(seqnum)); gst_buffer_unref(media_packet); old_link = link; link = link->next; g_queue_delete_link(dec->media_packets, old_link); } else { dec->max_packet_size = MAX(dec->max_packet_size, GST_BUFFER_SIZE(media_packet)); dec->received_media_packet_mask |= (1ul << (corrected_seqnum - dec->cur_snbase)); ++dec->num_received_media_packets; link = link->next; } } fec_dec_check_state(dec); }
void fec_dec_push_media_packet(fec_dec *dec, GstBuffer *packet) { guint32 original_seqnum; original_seqnum = gst_rtp_buffer_get_seq(packet); if (g_hash_table_lookup_extended(dec->media_packet_set, GINT_TO_POINTER(original_seqnum), NULL, NULL)) { GST_DEBUG("Media packet with seqnum %u is already in queue - discarding duplicate", original_seqnum); return; } if (dec->has_snbase) { guint32 corrected_seqnum; corrected_seqnum = fec_dec_correct_seqnum(dec, original_seqnum); GST_DEBUG("Pushing media packet with seqnum %u, current snbase is %u", original_seqnum, dec->cur_snbase); if ((corrected_seqnum - (guint32)(dec->cur_snbase)) >= dec->num_media_packets) { GST_DEBUG("Distance between FEC packets and incoming media packets is too large - purging %u FEC packets and setting has_snbase to FALSE", dec->num_received_fec_packets); dec->has_snbase = FALSE; dec->blacklisted_snbase = dec->cur_snbase; g_queue_foreach(dec->fec_packets, fec_dec_clear_packet, NULL); g_queue_clear(dec->fec_packets); g_hash_table_remove_all(dec->fec_packet_set); dec->num_received_fec_packets = 0; GST_DEBUG("Pushing media packet with seqnum %u, no current snbase set", original_seqnum); g_queue_push_tail(dec->media_packets, gst_buffer_ref(packet)); g_hash_table_add(dec->media_packet_set, GINT_TO_POINTER(original_seqnum)); ++dec->num_received_media_packets; } else if ((corrected_seqnum >= (guint32)(dec->cur_snbase)) && (corrected_seqnum <= ((guint32)(dec->cur_snbase) + ((guint32)(dec->num_media_packets)) - 1))) { g_queue_push_tail(dec->media_packets, gst_buffer_ref(packet)); g_hash_table_add(dec->media_packet_set, GINT_TO_POINTER(original_seqnum)); ++dec->num_received_media_packets; dec->received_media_packet_mask |= (1ul << (corrected_seqnum - dec->cur_snbase)); dec->max_packet_size = MAX(dec->max_packet_size, GST_BUFFER_SIZE(packet)); fec_dec_check_state(dec); } else { GST_DEBUG("Received media packet with seqnum %u outside bounds [%u, %u] - pushing aborted", original_seqnum, dec->cur_snbase, dec->cur_snbase + dec->num_media_packets - 1); } } else { GST_DEBUG("Pushing media packet with seqnum %u, no current snbase set", original_seqnum); g_queue_push_tail(dec->media_packets, gst_buffer_ref(packet)); g_hash_table_add(dec->media_packet_set, GINT_TO_POINTER(original_seqnum)); ++dec->num_received_media_packets; } if (dec->num_received_media_packets > dec->num_media_packets) { guint i; GST_DEBUG("Too many media packets in queue - deleting the %u oldest packets", dec->num_received_media_packets - dec->num_media_packets); for (i = dec->num_media_packets; i < dec->num_received_media_packets; ++i) { GstBuffer *media_packet; guint16 seqnum; media_packet = g_queue_pop_head(dec->media_packets); seqnum = gst_rtp_buffer_get_seq(packet); g_hash_table_remove(dec->media_packet_set, GINT_TO_POINTER(seqnum)); gst_buffer_unref(media_packet); } dec->num_received_media_packets = dec->num_media_packets; } }
static void ik_process_events (void) { g_queue_foreach (events_to_process, ik_pair_moves, NULL); while (!g_queue_is_empty (events_to_process)) { ik_event_internal_t *event = g_queue_peek_head (events_to_process); /* This must have been sent as part of a MOVED_TO/MOVED_FROM */ if (event->sent) { /* Pop event */ g_queue_pop_head (events_to_process); /* Free the internal event structure */ g_free (event); continue; } /* The event isn't ready yet */ if (!ik_event_ready (event)) break; /* Pop it */ event = g_queue_pop_head (events_to_process); /* Check if this is a MOVED_FROM that is also sitting in the cookie_hash */ if (event->event->cookie && event->pair == NULL && g_hash_table_lookup (cookie_hash, GINT_TO_POINTER (event->event->cookie))) g_hash_table_remove (cookie_hash, GINT_TO_POINTER (event->event->cookie)); if (event->pair) { /* We send out paired MOVED_FROM/MOVED_TO events in the same event buffer */ /* g_assert (event->event->mask == IN_MOVED_FROM && event->pair->event->mask == IN_MOVED_TO); */ /* Copy the paired data */ event->pair->sent = TRUE; event->sent = TRUE; ik_move_matches++; } else if (event->event->cookie) { /* If we couldn't pair a MOVED_FROM and MOVED_TO together, we change * the event masks */ /* Changeing MOVED_FROM to DELETE and MOVED_TO to create lets us make * the gaurantee that you will never see a non-matched MOVE event */ if (event->event->mask & IN_MOVED_FROM) { event->event->mask = IN_DELETE|(event->event->mask & IN_ISDIR); ik_move_misses++; /* not super accurate, if we aren't watching the destination it still counts as a miss */ } if (event->event->mask & IN_MOVED_TO) event->event->mask = IN_CREATE|(event->event->mask & IN_ISDIR); } /* Push the ik_event_t onto the event queue */ g_queue_push_tail (event_queue, event->event); /* Free the internal event structure */ g_free (event); } }
void li_http_headers_free(liHttpHeaders* headers) { if (!headers) return; g_queue_foreach(&headers->entries, _header_queue_free, NULL); g_queue_clear(&headers->entries); g_slice_free(liHttpHeaders, headers); }
void li_http_headers_reset(liHttpHeaders* headers) { g_queue_foreach(&headers->entries, _header_queue_free, NULL); g_queue_clear(&headers->entries); }
gint xmms_xform_this_read (xmms_xform_t *xform, gpointer buf, gint siz, xmms_error_t *err) { gint read = 0; gint nexths; if (xform->error) { xmms_error_set (err, XMMS_ERROR_GENERIC, "Read on errored xform"); return -1; } /* update hotspots */ nexths = xmms_xform_hotspots_update (xform); if (nexths >= 0) { siz = MIN (siz, nexths); } if (xform->buffered) { read = MIN (siz, xform->buffered); memcpy (buf, xform->buffer, read); xform->buffered -= read; /* buffer edited, update hotspot positions */ g_queue_foreach (xform->hotspots, &xmms_xform_hotspot_callback, &read); if (xform->buffered) { /* unless we are _peek:ing often this should be fine */ memmove (xform->buffer, &xform->buffer[read], xform->buffered); } } if (xform->eos) { return read; } while (read < siz) { gint res; res = xmms_xform_plugin_read (xform->plugin, xform, buf + read, siz - read, err); if (xform->metadata_collected && xform->metadata_changed) xmms_xform_metadata_update (xform); if (res < -1) { XMMS_DBG ("Read method of %s returned bad value (%d) - BUG IN PLUGIN", xmms_xform_shortname (xform), res); res = -1; } if (res == 0) { xform->eos = TRUE; break; } else if (res == -1) { xform->error = TRUE; return -1; } else { if (read == 0) xmms_xform_hotspots_update (xform); if (!g_queue_is_empty (xform->hotspots)) { if (xform->buffered + res > xform->buffersize) { xform->buffersize = MAX (xform->buffersize * 2, xform->buffersize + res); xform->buffer = g_realloc (xform->buffer, xform->buffersize); } g_memmove (xform->buffer + xform->buffered, buf + read, res); xform->buffered += res; break; } read += res; } } return read; }
void checkcopy_worker (CheckcopyWorkerParams * params) { GQueue *int_q; ProgressDialog * progress_dialog; CheckcopyPlanner *planner; CheckcopyProcessor *proc; CheckcopyFileList * list; gboolean verify_only; verify_only = g_file_has_uri_scheme (params->dest, "verify"); list = checkcopy_file_list_get_instance (); g_object_set (G_OBJECT (list), "verify-only", verify_only, NULL); progress_dialog = params->progress_dialog; planner = checkcopy_planner_new (progress_dialog); proc = checkcopy_processor_new (progress_dialog, params->dest, verify_only); int_q = g_queue_new (); ext_q = params->queue; g_async_queue_ref (ext_q); while (TRUE) { GFile *file; /* Collect everything from the external queue to calculate the size. * Since the files are not processed yet, stick them into the internal queue. * * At this point the internal queue is empty, so we can block once for getting the first item * from the external queue */ file = g_async_queue_pop (ext_q); progress_dialog_thread_set_status (progress_dialog, PROGRESS_DIALOG_STATUS_CALCULATING_SIZE); do { g_queue_push_tail (int_q, file); checkcopy_traverse (file, CHECKCOPY_FILE_HANDLER (planner)); } while ((file = g_async_queue_try_pop (ext_q)) != NULL); #ifdef DEBUG { gchar *size_str; guint64 total_size = 0; g_object_get (planner, "total-size", &total_size, NULL); size_str = g_format_size_for_display (total_size); DBG ("Total size is now %s", size_str); g_free (size_str); } #endif progress_dialog_thread_set_status (progress_dialog, PROGRESS_DIALOG_STATUS_COPYING); g_object_set (G_OBJECT (progress_dialog), "num-files", checkcopy_planner_get_num_files (planner), NULL); /* Now process the internal queue */ while ((file = g_queue_pop_head (int_q)) != NULL) { checkcopy_traverse (file, CHECKCOPY_FILE_HANDLER (proc)); g_object_unref (file); } checkcopy_file_list_write_checksum (list, params->dest); checkcopy_file_list_sweep (list); progress_dialog_thread_set_status (progress_dialog, PROGRESS_DIALOG_STATUS_COMPLETED); #ifdef DEBUG progress_dialog_thread_check_stats (progress_dialog); #endif DBG ("Waiting for more things to do"); } /* we won't ever get here but just in case * we change the loop condition later */ g_async_queue_unref (ext_q); g_queue_foreach (int_q, (GFunc) g_object_unref, NULL); g_queue_free (int_q); g_object_unref (planner); g_object_unref (proc); g_object_unref (list); g_object_unref (params->dest); g_free (params); }
static void stat_srv_on_stats_cb (struct evhttp_request *req, void *ctx) { StatSrv *stat_srv = (StatSrv *) ctx; struct evbuffer *evb = NULL; gint ref = 0; GString *str; struct evhttp_uri *uri; guint32 total_inodes, file_num, dir_num; guint64 read_ops, write_ops, readdir_ops, lookup_ops; guint32 cache_entries; guint64 total_cache_size, cache_hits, cache_miss; struct tm *cur_p; struct tm cur; time_t now; char ts[50]; uri = evhttp_uri_parse (evhttp_request_get_uri (req)); LOG_debug (STAT_LOG, "Incoming request: %s from %s:%d", evhttp_request_get_uri (req), req->remote_host, req->remote_port); if (uri) { const gchar *query; query = evhttp_uri_get_query (uri); if (query) { const gchar *refresh = NULL; struct evkeyvalq q_params; TAILQ_INIT (&q_params); evhttp_parse_query_str (query, &q_params); refresh = http_find_header (&q_params, "refresh"); if (refresh) ref = atoi (refresh); evhttp_clear_headers (&q_params); } evhttp_uri_free (uri); } str = g_string_new (NULL); now = time (NULL); localtime_r (&now, &cur); cur_p = &cur; if (!strftime (ts, sizeof (ts), "%H:%M:%S", cur_p)) ts[0] = '\0'; g_string_append_printf (str, "RioFS version: %s Uptime: %u sec, Now: %s, Log level: %d, Dir cache time: %u sec<BR>", VERSION, (guint32)(now - stat_srv->boot_time), ts, log_level, conf_get_uint (application_get_conf (stat_srv->app), "filesystem.dir_cache_max_time")); // DirTree dir_tree_get_stats (application_get_dir_tree (stat_srv->app), &total_inodes, &file_num, &dir_num); g_string_append_printf (str, "<BR>DirTree: <BR>-Total inodes: %u, Total files: %u, Total directories: %u<BR>", total_inodes, file_num, dir_num); // Fuse rfuse_get_stats (application_get_rfuse (stat_srv->app), &read_ops, &write_ops, &readdir_ops, &lookup_ops); g_string_append_printf (str, "<BR>Fuse: <BR>-Read ops: %"G_GUINT64_FORMAT", Write ops: %"G_GUINT64_FORMAT ", Readdir ops: %"G_GUINT64_FORMAT", Lookup ops: %"G_GUINT64_FORMAT"<BR>", read_ops, write_ops, readdir_ops, lookup_ops); // CacheMng cache_mng_get_stats (application_get_cache_mng (stat_srv->app), &cache_entries, &total_cache_size, &cache_hits, &cache_miss); g_string_append_printf (str, "<BR>CacheMng: <BR>-Total entries: %"G_GUINT32_FORMAT", Total cache size: %"G_GUINT64_FORMAT " bytes, Cache hits: %"G_GUINT64_FORMAT", Cache misses: %"G_GUINT64_FORMAT" <BR>", cache_entries, total_cache_size, cache_hits, cache_miss); g_string_append_printf (str, "<BR>Read workers (%d): <BR>", client_pool_get_client_count (application_get_read_client_pool (stat_srv->app))); client_pool_get_client_stats_info (application_get_read_client_pool (stat_srv->app), str, &print_format_http); g_string_append_printf (str, "<BR>Write workers (%d): <BR>", client_pool_get_client_count (application_get_write_client_pool (stat_srv->app))); client_pool_get_client_stats_info (application_get_write_client_pool (stat_srv->app), str, &print_format_http); g_string_append_printf (str, "<BR>Op workers (%d): <BR>", client_pool_get_client_count (application_get_ops_client_pool (stat_srv->app))); client_pool_get_client_stats_info (application_get_ops_client_pool (stat_srv->app), str, &print_format_http); g_string_append_printf (str, "<BR><BR>Operation history (%u max items): <BR>", conf_get_uint (application_get_conf (stat_srv->app), "statistics.history_size")); g_queue_foreach (stat_srv->q_op_history, (GFunc) stat_srv_print_history_item, str); evb = evbuffer_new (); evbuffer_add_printf (evb, "<HTTP>"); if (ref) { evbuffer_add_printf (evb, "<HEAD><meta http-equiv=\"refresh\" content=\"%d\"></HEAD>", ref); } evbuffer_add_printf (evb, "<BODY>"); evbuffer_add (evb, str->str, str->len); evbuffer_add_printf (evb, "</BODY></HTTP>"); evhttp_send_reply (req, HTTP_OK, "OK", evb); evbuffer_free (evb); g_string_free (str, TRUE); }
void queue_cleanup(void) { g_queue_foreach(queue, queue_free_song, NULL); g_queue_free(queue); }
static GstPadProbeReturn handle_mq_output (GstPad * pad, GstPadProbeInfo * info, MqStreamCtx * ctx) { GstSplitMuxSink *splitmux = ctx->splitmux; MqStreamBuf *buf_info = NULL; GST_LOG_OBJECT (pad, "Fired probe type 0x%x\n", info->type); /* FIXME: Handle buffer lists, until then make it clear they won't work */ if (info->type & GST_PAD_PROBE_TYPE_BUFFER_LIST) { g_warning ("Buffer list handling not implemented"); return GST_PAD_PROBE_DROP; } if (info->type & GST_PAD_PROBE_TYPE_EVENT_DOWNSTREAM) { GstEvent *event = gst_pad_probe_info_get_event (info); GST_LOG_OBJECT (pad, "Event %" GST_PTR_FORMAT, event); switch (GST_EVENT_TYPE (event)) { case GST_EVENT_SEGMENT: gst_event_copy_segment (event, &ctx->out_segment); break; case GST_EVENT_FLUSH_STOP: GST_SPLITMUX_LOCK (splitmux); gst_segment_init (&ctx->out_segment, GST_FORMAT_UNDEFINED); g_queue_foreach (&ctx->queued_bufs, (GFunc) mq_stream_buf_free, NULL); g_queue_clear (&ctx->queued_bufs); ctx->flushing = FALSE; GST_SPLITMUX_UNLOCK (splitmux); break; case GST_EVENT_FLUSH_START: GST_SPLITMUX_LOCK (splitmux); GST_LOG_OBJECT (pad, "Flush start"); ctx->flushing = TRUE; GST_SPLITMUX_BROADCAST (splitmux); GST_SPLITMUX_UNLOCK (splitmux); break; case GST_EVENT_EOS: GST_SPLITMUX_LOCK (splitmux); if (splitmux->state == SPLITMUX_STATE_STOPPED) goto beach; ctx->out_eos = TRUE; GST_SPLITMUX_UNLOCK (splitmux); break; case GST_EVENT_GAP:{ GstClockTime gap_ts; gst_event_parse_gap (event, &gap_ts, NULL); if (gap_ts == GST_CLOCK_TIME_NONE) break; GST_SPLITMUX_LOCK (splitmux); gap_ts = gst_segment_to_running_time (&ctx->out_segment, GST_FORMAT_TIME, gap_ts); GST_LOG_OBJECT (pad, "Have GAP w/ ts %" GST_TIME_FORMAT, GST_TIME_ARGS (gap_ts)); if (splitmux->state == SPLITMUX_STATE_STOPPED) goto beach; ctx->out_running_time = gap_ts; complete_or_wait_on_out (splitmux, ctx); GST_SPLITMUX_UNLOCK (splitmux); break; } default: break; } return GST_PAD_PROBE_PASS; } /* Allow everything through until the configured next stopping point */ GST_SPLITMUX_LOCK (splitmux); buf_info = g_queue_pop_tail (&ctx->queued_bufs); if (buf_info == NULL) /* Can only happen due to a poorly timed flush */ goto beach; /* If we have popped a keyframe, decrement the queued_gop count */ if (buf_info->keyframe && splitmux->queued_gops > 0) splitmux->queued_gops--; ctx->out_running_time = buf_info->run_ts; GST_LOG_OBJECT (splitmux, "Pad %" GST_PTR_FORMAT " buffer with TS %" GST_TIME_FORMAT " size %" G_GSIZE_FORMAT, pad, GST_TIME_ARGS (ctx->out_running_time), buf_info->buf_size); complete_or_wait_on_out (splitmux, ctx); if (splitmux->muxed_out_time == GST_CLOCK_TIME_NONE || splitmux->muxed_out_time < buf_info->run_ts) splitmux->muxed_out_time = buf_info->run_ts; splitmux->muxed_out_bytes += buf_info->buf_size; #ifndef GST_DISABLE_GST_DEBUG { GstBuffer *buf = gst_pad_probe_info_get_buffer (info); GST_LOG_OBJECT (pad, "Returning to pass buffer %" GST_PTR_FORMAT " run ts %" GST_TIME_FORMAT, buf, GST_TIME_ARGS (ctx->out_running_time)); } #endif GST_SPLITMUX_UNLOCK (splitmux); mq_stream_buf_free (buf_info); return GST_PAD_PROBE_PASS; beach: GST_SPLITMUX_UNLOCK (splitmux); return GST_PAD_PROBE_DROP; }
void fec_dec_flush_recovered_packets(fec_dec *dec) { g_queue_foreach(dec->recovered_packets, fec_dec_clear_packet, NULL); g_queue_clear(dec->recovered_packets); }
static void photos_item_manager_collection_path_free (PhotosItemManager *self) { g_queue_foreach (self->collection_path, photos_item_manager_collection_path_free_foreach, NULL); g_queue_free (self->collection_path); }
static gpointer brasero_dvdcss_write_image_thread (gpointer data) { guchar buf [DVDCSS_BLOCK_SIZE * BRASERO_DVDCSS_I_BLOCKS]; BraseroScrambledSectorRange *range = NULL; BraseroMedium *medium = NULL; BraseroVolFile *files = NULL; dvdcss_handle *handle = NULL; BraseroDrive *drive = NULL; BraseroDvdcssPrivate *priv; gint64 written_sectors = 0; BraseroDvdcss *self = data; BraseroTrack *track = NULL; guint64 remaining_sectors; FILE *output_fd = NULL; BraseroVolSrc *vol; gint64 volume_size; GQueue *map = NULL; brasero_job_set_use_average_rate (BRASERO_JOB (self), TRUE); brasero_job_set_current_action (BRASERO_JOB (self), BRASERO_BURN_ACTION_ANALYSING, _("Retrieving DVD keys"), FALSE); brasero_job_start_progress (BRASERO_JOB (self), FALSE); priv = BRASERO_DVDCSS_PRIVATE (self); /* get the contents of the DVD */ brasero_job_get_current_track (BRASERO_JOB (self), &track); drive = brasero_track_disc_get_drive (BRASERO_TRACK_DISC (track)); vol = brasero_volume_source_open_file (brasero_drive_get_device (drive), &priv->error); files = brasero_volume_get_files (vol, 0, NULL, NULL, NULL, &priv->error); brasero_volume_source_close (vol); if (!files) goto end; medium = brasero_drive_get_medium (drive); brasero_medium_get_data_size (medium, NULL, &volume_size); if (volume_size == -1) { priv->error = g_error_new (BRASERO_BURN_ERROR, BRASERO_BURN_ERROR_GENERAL, _("The size of the volume could not be retrieved")); goto end; } /* create a handle/open DVD */ handle = dvdcss_open (brasero_drive_get_device (drive)); if (!handle) { priv->error = g_error_new (BRASERO_BURN_ERROR, BRASERO_BURN_ERROR_GENERAL, _("Video DVD could not be opened")); goto end; } /* look through the files to get the ranges of encrypted sectors * and cache the CSS keys while at it. */ map = g_queue_new (); if (!brasero_dvdcss_create_scrambled_sectors_map (self, drive, map, handle, files, &priv->error)) goto end; BRASERO_JOB_LOG (self, "DVD map created (keys retrieved)"); g_queue_sort (map, brasero_dvdcss_sort_ranges, NULL); brasero_volume_file_free (files); files = NULL; if (dvdcss_seek (handle, 0, DVDCSS_NOFLAGS) < 0) { BRASERO_JOB_LOG (self, "Error initial seeking"); priv->error = g_error_new (BRASERO_BURN_ERROR, BRASERO_BURN_ERROR_GENERAL, _("Error while reading video DVD (%s)"), dvdcss_error (handle)); goto end; } brasero_job_set_current_action (BRASERO_JOB (self), BRASERO_BURN_ACTION_DRIVE_COPY, _("Copying video DVD"), FALSE); brasero_job_start_progress (BRASERO_JOB (self), TRUE); remaining_sectors = volume_size; range = g_queue_pop_head (map); if (brasero_job_get_fd_out (BRASERO_JOB (self), NULL) != BRASERO_BURN_OK) { gchar *output = NULL; brasero_job_get_image_output (BRASERO_JOB (self), &output, NULL); output_fd = fopen (output, "w"); if (!output_fd) { priv->error = g_error_new_literal (BRASERO_BURN_ERROR, BRASERO_BURN_ERROR_GENERAL, g_strerror (errno)); g_free (output); goto end; } g_free (output); } while (remaining_sectors) { gint flag; guint64 num_blocks, data_size; if (priv->cancel) break; num_blocks = BRASERO_DVDCSS_I_BLOCKS; /* see if we are approaching the end of the dvd */ if (num_blocks > remaining_sectors) num_blocks = remaining_sectors; /* see if we need to update the key */ if (!range || written_sectors < range->start) { /* this is in a non scrambled sectors range */ flag = DVDCSS_NOFLAGS; /* we don't want to mix scrambled and non scrambled sectors */ if (range && written_sectors + num_blocks > range->start) num_blocks = range->start - written_sectors; } else { /* this is in a scrambled sectors range */ flag = DVDCSS_READ_DECRYPT; /* see if we need to update the key */ if (written_sectors == range->start) { int pos; pos = dvdcss_seek (handle, written_sectors, DVDCSS_SEEK_KEY); if (pos < 0) { BRASERO_JOB_LOG (self, "Error seeking"); priv->error = g_error_new (BRASERO_BURN_ERROR, BRASERO_BURN_ERROR_GENERAL, _("Error while reading video DVD (%s)"), dvdcss_error (handle)); break; } } /* we don't want to mix scrambled and non scrambled sectors * NOTE: range->end address is the next non scrambled sector */ if (written_sectors + num_blocks > range->end) num_blocks = range->end - written_sectors; if (written_sectors + num_blocks == range->end) { /* update to get the next range of scrambled sectors */ g_free (range); range = g_queue_pop_head (map); } } num_blocks = dvdcss_read (handle, buf, num_blocks, flag); if (num_blocks < 0) { BRASERO_JOB_LOG (self, "Error reading"); priv->error = g_error_new (BRASERO_BURN_ERROR, BRASERO_BURN_ERROR_GENERAL, _("Error while reading video DVD (%s)"), dvdcss_error (handle)); break; } data_size = num_blocks * DVDCSS_BLOCK_SIZE; if (output_fd) { if (fwrite (buf, 1, data_size, output_fd) != data_size) { int errsv = errno; priv->error = g_error_new (BRASERO_BURN_ERROR, BRASERO_BURN_ERROR_GENERAL, _("Data could not be written (%s)"), g_strerror (errsv)); break; } } else { BraseroBurnResult result; result = brasero_dvdcss_write_sector_to_fd (self, buf, data_size); if (result != BRASERO_BURN_OK) break; } written_sectors += num_blocks; remaining_sectors -= num_blocks; brasero_job_set_written_track (BRASERO_JOB (self), written_sectors * DVDCSS_BLOCK_SIZE); } end: if (range) g_free (range); if (handle) dvdcss_close (handle); if (files) brasero_volume_file_free (files); if (output_fd) fclose (output_fd); if (map) { g_queue_foreach (map, (GFunc) g_free, NULL); g_queue_free (map); } if (!priv->cancel) priv->thread_id = g_idle_add (brasero_dvdcss_thread_finished, self); /* End thread */ g_mutex_lock (priv->mutex); priv->thread = NULL; g_cond_signal (priv->cond); g_mutex_unlock (priv->mutex); g_thread_exit (NULL); return NULL; }
static void rm_tm_extract(RmTreeMerger *self) { /* Iterate over all directories per hash (which are same therefore) */ GList *result_table_values = g_hash_table_get_values(self->result_table); result_table_values = g_list_sort(result_table_values, (GCompareFunc)rm_tm_cmp_directory_groups); for(GList *iter = result_table_values; iter; iter = iter->next) { /* Needs at least two directories to be duplicate... */ GQueue *dir_list = iter->data; #ifdef _RM_TREEMERGE_DEBUG for(GList *i = dir_list->head; i; i = i->next) { RmDirectory *d = i->data; char buf[512]; memset(buf, 0, sizeof(buf)); rm_digest_hexstring(d->digest, buf); g_printerr(" mergeups=%" LLU ": %s - %s\n", d->mergeups, d->dirname, buf); } g_printerr("---\n"); #endif if(dir_list->length < 2) { continue; } if(rm_session_was_aborted(self->session)) { break; } /* List of result directories */ GQueue result_dirs = G_QUEUE_INIT; /* Sort the RmDirectory list by their path depth, lowest depth first */ g_queue_sort(dir_list, (GCompareDataFunc)rm_tm_sort_paths, self); /* Output the directories and mark their children to prevent * duplicate directory reports in lower levels. */ for(GList *iter = dir_list->head; iter; iter = iter->next) { RmDirectory *directory = iter->data; if(directory->finished == false) { rm_tm_mark_finished(self, directory); g_queue_push_head(&result_dirs, directory); } } /* Make sure the original directory lands as first * in the result_dirs queue. */ g_queue_sort(&result_dirs, (GCompareDataFunc)rm_tm_sort_orig_criteria, self); GQueue file_adaptor_group = G_QUEUE_INIT; for(GList *iter = result_dirs.head; iter; iter = iter->next) { RmDirectory *directory = iter->data; RmFile *mask = rm_directory_as_file(self, directory); g_queue_push_tail(&file_adaptor_group, mask); if(iter == result_dirs.head) { /* First one in the group -> It's the original */ mask->is_original = true; rm_tm_mark_original_files(self, directory); } else { if(rm_tm_mark_duplicate_files(self, directory, 0) == directory->dupe_count) { /* Mark the file as original when all files in it are preferred. */ mask->is_original = true; rm_tm_mark_original_files(self, directory); } } if(self->session->cfg->write_unfinished) { rm_tm_write_unfinished_cksums(self, directory); } } if(result_dirs.length >= 2) { rm_shred_forward_to_output(self->session, &file_adaptor_group); } g_queue_foreach(&file_adaptor_group, (GFunc)g_free, NULL); g_queue_clear(&file_adaptor_group); g_queue_clear(&result_dirs); } g_list_free(result_table_values); /* Iterate over all non-finished dirs in the tree, * and grab unfinished files that must be dupes elsewhise. */ rm_trie_iter(&self->dir_tree, NULL, true, false, rm_tm_iter_unfinished_files, self); /* Now here's a problem. Consider an input like this: * /root * ├── a * ├── sub1 * │ ├── a * │ └── b * └── sub2 * ├── a * └── b * * This yields two duplicate dirs (sub1, sub2) * and one duplicate, unmatched file (a). * * For outputting files we need groups, which consist of at least 2 files. * So how to group that, so we don't end up deleting a file many times? * We always choose which directories are originals first, so we flag all * files in it as originals. */ GHashTableIter iter; g_hash_table_iter_init(&iter, self->file_groups); GQueue *file_list = NULL; while(g_hash_table_iter_next(&iter, NULL, (void **)&file_list)) { bool has_one_dupe = false; RmOff file_size_acc = 0; GList *next = NULL; for(GList *iter = file_list->head; iter; iter = next) { RmFile *file = iter->data; next = iter->next; bool is_duplicate = g_hash_table_contains(self->file_checks, file->digest); has_one_dupe |= is_duplicate; /* with --partial-hidden we do not want to output */ if(self->session->cfg->partial_hidden && file->is_hidden) { g_queue_delete_link(file_list, iter); continue; } if(iter != file_list->head && !is_duplicate) { file_size_acc += file->file_size; } } if(file_list->length >= 2) { /* If no separate duplicate files are requested, we can stop here */ if(self->session->cfg->find_duplicates == false) { self->session->total_lint_size -= file_size_acc; self->session->dup_group_counter -= 1; self->session->dup_counter -= file_list->length - 1; } else { rm_shred_group_find_original(self->session, file_list); rm_shred_forward_to_output(self->session, file_list); } } } }