/// <summary> /// 生きているスレとdat落ちしているスレを分離 /// </summary> /// <param name="oldBoard">ログが存在する板</param> /// <param name="newBoard">生きているスレの移転先</param> /// <param name="leaveItems">dat落ちしているスレが格納される</param> /// <param name="liveItems">生きているスレが格納される</param> private void Separate(BoardInfo oldBoard, BoardInfo newBoard, out List <ThreadHeader> leaveItems, out List <ThreadHeader> liveItems) { leaveItems = new List <ThreadHeader>(); liveItems = new List <ThreadHeader>(); if (cache.Exists(oldBoard)) { List <ThreadHeader> oldItems = GotThreadListIndexer.Read(cache, oldBoard); List <ThreadHeader> newItems = new List <ThreadHeader>(); ThreadListReader listReader = null; if (oldItems.Count > 0) { try { listReader = TypeCreator.CreateThreadListReader(newBoard.Bbs); listReader.Open(newBoard); while (listReader.Read(newItems) != 0) { ; } // 移転先のスレ一覧に存在するログのみ移転 (dat落ちしているスレは移転しない) foreach (ThreadHeader header in oldItems) { Predicate <ThreadHeader> p = new Predicate <ThreadHeader>(delegate(ThreadHeader h) { return(h.Key == header.Key); }); if (newItems.Exists(p)) { // 生きているスレの板情報を移転先板に書き換える if (ThreadIndexer.Read(cache, header) != null) { ThreadIndexer.Delete(cache, header); liveItems.Add(header); header.BoardInfo = newBoard; ThreadIndexer.Write(cache, header); } } else { leaveItems.Add(header); } } } finally { if (listReader != null) { listReader.Close(); } } } } }
public void Indexing(BoardInfo bi, string[] datFiles, DatIndexingCallback callback) { LocalThreadReader reader = new LocalThreadReader(new X2chThreadParser()); float length = datFiles.Length, current = 0; if (length == 0) { return; } foreach (string path in datFiles) { ThreadHeader header = new X2chThreadHeader(); header.BoardInfo = bi; header.Key = Path.GetFileNameWithoutExtension(path); int parsed; try { if (!reader.__Open(path)) { continue; } ResSetCollection buffer = new ResSetCollection(); int byteCount = 0; while (reader.Read(buffer, out parsed) != 0) { byteCount += parsed; } if (buffer.Count > 0) { header.GotByteCount = byteCount; header.ResCount = buffer.Count; header.GotResCount = buffer.Count; header.LastModified = File.GetLastWriteTime(path); header.UseGzip = false; header.Subject = buffer[0].Tag as String; ThreadIndexer.Write( Path.ChangeExtension(path, ".idx"), header); } if (callback != null) { callback(++current / length * 100f); } } finally { reader.Close(); } } }
/// <summary> /// oldBoardからnewBoardにログを移動 /// </summary> /// <param name="oldItems"></param> /// <param name="newBoard"></param> private void CopyDatFiles(BoardInfo oldItems, BoardInfo newBoard) { string fromFolder = cache.GetFolderPath(oldItems); string toFolder = cache.GetFolderPath(newBoard, true); string[] fileNames = Directory.GetFiles(fromFolder, "*.dat*"); // .dat .dat.gz を検索 foreach (string fromPath in fileNames) { try { string fromName = Path.GetFileName(fromPath); string destPath = Path.Combine(toFolder, fromName); File.Copy(fromPath, destPath, true); File.Delete(fromPath); int token = fromName.IndexOf('.'); if (token != -1) { string key = fromName.Substring(0, token); string fromIndexFile = Path.Combine(fromFolder, key + ".idx"); string toIndexFile = Path.Combine(toFolder, key + ".idx"); ThreadHeader h = ThreadIndexer.Read(fromIndexFile); if (h != null) { h.BoardInfo.Server = newBoard.Server; ThreadIndexer.Write(toIndexFile, h); File.Delete(fromIndexFile); } } } catch (IOException ex) { TwinDll.Output(ex); } } }
private void OpenInternal() { CompleteStatus status = CompleteStatus.Success; try { try { isWaiting = true; OnLoading(new EventArgs()); } finally { isWaiting = false; } if (canceled) { return; } // 開く処理を行う if (modeOpen) { Invoke(new MethodInvoker(Opening)); } // キャッシュを読み込み表示 ReadCache(resCollection); if (canceled) { return; } Invoke(new MethodInvoker(WriteBegin)); if (canceled) { return; } if (modeOpen) { Invoke(new WriteResMethodInvoker(Write), new object[] { resCollection }); // スクロール位置を復元 (値が0の場合は復元しない) if (modeOpen && headerInfo.Position != 0.0f) { Invoke(new PositionMethodInvoker(SetScrollPosition), new object[] { headerInfo.Position }); } } Retry: try { // サーバーに接続 if (OpenReader()) { if (canceled) { return; } Reading(); // あぼーんを検知した場合 if (aboneDetected) { } } else { headerInfo.NewResCount = 0; ThreadIndexer.Write(Cache, headerInfo); } } finally { if (reader != null) { reader.Close(); } } // 再試行が要求された場合、最初から if (retried) { goto Retry; } if (canceled) { return; } Invoke(new MethodInvoker(WriteEnd)); } catch (Exception ex) { status = CompleteStatus.Error; // isOpen = false; #10/15 TwinDll.Output(ex); OnStatusTextChanged(ex.Message); } finally { // 中止された場合はETagをリセット if (canceled) { headerInfo.ETag = String.Empty; } indicesValues.Clear(); canceled = false; lock (syncObject) thread = null; if (status == CompleteStatus.Success) { OnStatusTextChanged( String.Format("{0}の読み込みを完了 (新着: {1}件)", headerInfo.Subject, headerInfo.NewResCount)); } /** 9/26 追加 **/ else if (reader is X2chAuthenticateThreadReader) { X2chRokkaResponseState rokkaState = ((X2chAuthenticateThreadReader)reader).RokkaResponseState; if (rokkaState != X2chRokkaResponseState.Success) { TwinDll.Output("RokkaResponseState: {0}, URL: {1}, ", rokkaState, headerInfo.Url); } OnStatusTextChanged(String.Format("RokkaResponseState: {0}", rokkaState)); } /****/ IsReading = false; lastCompletedDateTime = DateTime.Now; OnComplete(new CompleteEventArgs(status)); } }
/// <summary> /// データを読み込む&書き込む /// </summary> private void Reading() { ResSetCollection items = new ResSetCollection(), buffer = new ResSetCollection(); int read = -1, byteParsed, totalByteCount = 0; while (read != 0) { if (canceled) { return; } read = reader.Read(buffer, out byteParsed); // あぼーんを検知した場合、処理を中止。 if (read == -1) { aboneDetected = true; return; } totalByteCount += byteParsed; items.AddRange(buffer); // 逐次受信の場合はビューアに書き込む if (!isPackageReception) { if (canceled) { return; } Invoke(new WriteResMethodInvoker(WriteInternal), new object[] { buffer }); } buffer.Clear(); OnReceive(new ReceiveEventArgs( reader.Length, reader.Position, read)); OnStatusTextChanged( String.Format("{0} 受信中 ({1}/{2})", headerInfo.Subject, reader.Position, reader.Length)); } // 一括受信の場合はここで一気にフラッシュ if (isPackageReception) { if (canceled) { return; } Invoke(new WriteResMethodInvoker(WriteInternal), new object[] { items }); } try { // スレッドのインデックス情報を保存 storage = new LocalThreadStorage(Cache, headerInfo, StorageMode.Write); storage.BufferSize = bufferSize; storage.Write(items); headerInfo.GotByteCount += totalByteCount; headerInfo.GotResCount += items.Count; headerInfo.NewResCount = items.Count; ThreadIndexer.Write(Cache, headerInfo); } catch (Exception ex) { TwinDll.Output(ex); } finally { storage.Close(); } SaveThreadListIndices(); }