/// <summary> /// 删除任务 /// </summary> /// <param name="id">任务标识id</param> public void ReleaseTask(Guid id) { try { if (id == Guid.Empty) { return; } lock (_data_lck) { if (!_guid_begpos_mapping.ContainsKey(id)) { //Tracer.GlobalTracer.TraceWarning("Missing id " + id.ToString() + " in mapping, maybe it's a bug?"); return; } var beg_pos = _guid_begpos_mapping[id]; _guid_begpos_mapping.Remove(id); _segment_list[beg_pos] = new _t_struct(Guid.Empty, _segment_list[beg_pos].end_pos); #pragma warning disable if (_enable_tracing) { Tracer.GlobalTracer.TraceInfo("TaskDispatcher.ReleaseTask called: Guid id=" + id + " [segment=" + _segment_list.Count + ", task=" + _guid_begpos_mapping.Count + "]"); } #pragma warning restore } } catch (Exception ex) { Tracer.GlobalTracer.TraceError(ex.ToString()); } }
/// <summary> /// 分配新的任务,并返回该任务的标识id,若分配失败会返回Guid.Empty /// </summary> /// <param name="beg_position">文件的开始位置</param> /// <returns></returns> public Guid AllocateNewTask(out ulong beg_position) { try { //todo:优化停止段的重新分配 lock (_data_lck) { if (!_debug_check()) { throw new Exception("Debug check failed"); } ulong max_length = _segment_list.First().Key; beg_position = 0; int last_index = -1; //减小分段的优化模式 //if (_segment_list.Count == _guid_begpos_mapping.Count + 1) //{ //找到最大的空间进行分配 for (int i = 1; i < _segment_list.Count; i++) { var tmp_length = _segment_list.ElementAt(i).Key - _segment_list.ElementAt(i - 1).Value.end_pos; //last_index = i - 1; var last_index_has_task = _segment_list.ElementAt(i - 1).Value.id != Guid.Empty; if (last_index_has_task) { //上一片段已经有执行中的任务就从中间分配 var allocated_length = tmp_length >> 1; if (allocated_length > max_length) { last_index = -1; //beg_position = _segment_list.ElementAt(i - 1).Key; beg_position = _segment_list.ElementAt(i - 1).Value.end_pos; beg_position += (tmp_length - allocated_length); max_length = allocated_length; } } else { //没有的话从头开始分配 if (tmp_length > max_length) { last_index = i - 1; beg_position = _segment_list.ElementAt(i - 1).Value.end_pos; max_length = tmp_length; } } } //} //else //{ // //找到最大的空间进行分配,跳过已经有任务的 // for (int i = 1; i < _segment_list.Count; i++) // { // var tmp_length = _segment_list.ElementAt(i).Key - _segment_list.ElementAt(i - 1).Value.end_pos; // var last_index_has_task = _segment_list.ElementAt(i - 1).Value.id != Guid.Empty; // if (!last_index_has_task) // { // if (tmp_length > max_length) // { // last_index = i - 1; // beg_position = _segment_list.ElementAt(i - 1).Value.end_pos; // max_length = tmp_length; // } // } // } //} //length is too small, ignored if (max_length == 0 || (max_length < _MIN_DISPATCH_LENGTH && last_index == -1 && _segment_list.Count > 1)) { beg_position = 0; #pragma warning disable if (_enable_tracing) { Tracer.GlobalTracer.TraceInfo("TaskDispatcher.AllocateNewTask called: out ulong beg_position=" + beg_position + ", Guid id=" + Guid.Empty.ToString() + " \r\n[segment=" + _segment_list.Count + ", task=" + _guid_begpos_mapping.Count + ", last_index=" + last_index + "]"); } #pragma warning restore return(Guid.Empty); } //saving segment data var id = Guid.NewGuid(); //assign mode if (last_index == -1) { _segment_list.Add(beg_position, new _t_struct(id, beg_position)); _guid_begpos_mapping.Add(id, beg_position); } //update mode else { var last_begin_pos = _segment_list.ElementAt(last_index).Key; _segment_list[last_begin_pos] = new _t_struct(id, _segment_list[last_begin_pos].end_pos); _guid_begpos_mapping.Add(id, last_begin_pos); } #pragma warning disable if (_enable_tracing) { Tracer.GlobalTracer.TraceInfo("TaskDispatcher.AllocateNewTask called: out ulong beg_position=" + beg_position + ", Guid id=" + id.ToString() + " \r\n[segment=" + _segment_list.Count + ", task=" + _guid_begpos_mapping.Count + ", last_index=" + last_index + "]"); } return(id); #pragma warning restore } } catch (Exception ex) { Tracer.GlobalTracer.TraceError(ex.ToString()); beg_position = 0; return(Guid.Empty); } }
/// <summary> /// 更新任务的位置,返回是否需要继续下载 /// </summary> /// <param name="id">任务标识id</param> /// <param name="current_position">该任务目前已完成的位置</param> /// <returns></returns> public bool UpdateTaskSituation(Guid id, ulong current_position) { try { if (id == Guid.Empty) { return(false); } lock (_data_lck) {//合理性检测 if (!_guid_begpos_mapping.ContainsKey(id)) { return(false); } var beg_pos = _guid_begpos_mapping[id]; //当前分段数据 var segment_data = _segment_list[beg_pos]; if (segment_data.end_pos > current_position) { throw new ArgumentException("Decreasing position is forbidden"); } //修改当前数据 _complete_length += (current_position - segment_data.end_pos); _segment_list[beg_pos] = new _t_struct(id, current_position); //下一分段数据 var next_segment_index = _segment_list.IndexOfKey(beg_pos) + 1; do { if (next_segment_index == _segment_list.Count - 1) { //在获取下一分段之前,为了不影响最后一个标记文件结束位置segment,加入以下判断 if (current_position >= _length) { _complete_length -= current_position - _length; current_position = _length; _segment_list[beg_pos] = new _t_struct(Guid.Empty, _length); _guid_begpos_mapping.Remove(id); return(false); } else { return(true); } } var next_segment_data = _segment_list.ElementAt(next_segment_index); //合并检测 if (current_position >= next_segment_data.Key) { if (current_position >= next_segment_data.Value.end_pos) { //直接吞掉下一段的数据 _complete_length -= next_segment_data.Value.end_pos - next_segment_data.Key; var next_guid = next_segment_data.Value.id; _segment_list.RemoveAt(next_segment_index); if (next_guid != Guid.Empty) { _guid_begpos_mapping.Remove(next_guid); } #pragma warning disable if (_enable_tracing) { Tracer.GlobalTracer.TraceInfo("TaskDispatcher.TaskMerge: Merging Task #" + next_segment_index + " -> #" + (next_segment_index - 1) + " segments=" + _segment_list.Count + ", task=" + _guid_begpos_mapping.Count); } #pragma warning restore } else { //这一段宣告死亡,由下一段接管 _complete_length -= current_position - next_segment_data.Key; current_position = next_segment_data.Key; _segment_list[beg_pos] = next_segment_data.Value; var next_guid = next_segment_data.Value.id; if (next_guid != Guid.Empty) { _guid_begpos_mapping[next_guid] = beg_pos; } _guid_begpos_mapping.Remove(id); _segment_list.RemoveAt(next_segment_index); #pragma warning disable if (_enable_tracing) { Tracer.GlobalTracer.TraceInfo("TaskDispatcher.TaskMerge: Merging Task #" + (next_segment_index - 1) + " -> #" + next_segment_index + " segments=" + _segment_list.Count + ", task=" + _guid_begpos_mapping.Count); } #pragma warning restore _debug_check(); return(false); } } else { break; } } while (true); //执行到这里应该都是未完成该段的,包括合并后的情况 //Tracer.GlobalTracer.TraceInfo("TaskDispatcher.TaskMerge: segments=" + _segment_list.Count + ", task=" + _guid_begpos_mapping.Count); _debug_check(); return(true); } } catch (Exception ex) { Tracer.GlobalTracer.TraceError(ex.ToString()); return(false); } }