コンテンツにスキップ

データの置き場所とパスの決め方

扱うこと: work/ の中身(自動生成)、setting.config・ワークスペースの置き場所の決め方、パスの定数、ワークスペースの中の場所(Workspace クラス)。扱わないこと: scripts/ の配置そのもの(配布物と開発用のフォルダ構成)、どの処理がどのファイルを読み書きするか(どの処理がどのファイルを読み書きするか)。先に読むページ: 設計の概要。

tebunko が読み書きするファイルとフォルダの一覧(置き場ごと・配布形ごと)は、どの処理がどのファイルを読み書きするか にある。

設計書の work/ の書き方

設計書では、ワークスペース(インデックス・取り込み一覧・ログを置くフォルダ)を work/ と書く。実際の場所は、既定では %USERPROFILE%\Documents\tebunko_ws(テストと実機の確かめでは、環境変数 TEBUNKO_DEFAULT_WORKSPACE で使い捨ての場所に差し替える。テストの実行)、[設定]で変えたときはその場所である(下の「データの置き場所」)。開発用のリポジトリ直下の work/(work/test/・work/release/・work/site/ など、git 管理外)は別のもの。

自動生成(work/)

パス 説明
work/store/content/ インデックス。クロール対象フォルダごとに work/store/content/<インデックス名>/ に分かれ、その下はクロール対象フォルダと同じフォルダ構成で、各フォルダに元のファイルの拡張子ごとの本文インデックス(content_index.xlsx.001.tsv など)を置く。取り込み中だけ、元のファイル 1 つにつき 1 フォルダの TSV(<ファイル名.xlsx>/<場所>.tsv)ができ、フォルダの取り込みが終わると本文インデックスに入れて消す(インデックスのファイルの形)
work/store/content/<インデックス名>/source_folder.txt インデックス名と元のフォルダ(クロール対象フォルダ)の対応。インデックス 1 件につき 1 ファイル。work/store/content ごとでも <インデックス名> のフォルダだけでも、別の PC・場所へコピーすれば検索結果から元のファイルを開ける
work/store/gram/ 2-gram の索引(検索で照合する本文インデックスのファイルを絞る。インデックス名ごとの toc.tsv と g<10 桁>.seg。作り直せる。2-gram の索引)
work/store/ingest_status.tsv 取り込み対象のファイルごとの更新日時・サイズ・状態(未取り込み・済・失敗)
work/store/journal/ingest.tsv 取り込みのジャーナル(仕事の始まり・フォルダの書き出しの追記ログ)。取り込み一覧を書き直し終えたら「終」を書く。「終」が無いまま残っていれば、取り込み中に強制終了した
work/office_pids/<PC の鍵>/<PID>.txt インデックス作成が起動した Office の記録(起動時の確認で、残ったものだけを終了するため。前回残った Office の確認)
work/publish/<PID>/ 1 ファイル分の TSV を、インデックスに入れる直前に集めるフォルダ(インデックス作成の終了時に削除する)
work/tmp/<PC の鍵>/<PID>/ 取り込みの作業領域(下の説明)
work/indexing_log.txt インデクサの表示内容の記録(実行ごとに新しく書く。先頭に版と環境の見出し)。前回の分は work/indexing_log_previous.txt
work/gui_error_log.txt 画面で起きた予期しないエラーの記録(追記。1 MB 以上で work/gui_error_log_previous.txt へ移す)
work/search_results.txt 画面の[結果をファイルに出力]で書き出す検索結果
work/test/・work/release/・work/site/・work/cache/ 開発用の出力(テスト結果とカバレッジ・配布物・設計書のサイト・サイトを作るときのキャッシュ)

取り込みの作業領域は、既定では work/tmp/<PC の鍵>/<PID>/ に置く(Workspace の TmpRoot。tebunko/core/workspace.ps1 の selectTmpDir)。<PC の鍵> はコンピューター名から作る 8 文字の鍵(getMachineKey)で、ワークスペースを複数の PC から共有しても、互いの作業フォルダを衝突・削除させない(プロセス ID だけでは PC をまたいで重なりうるため)。その下は、取り込みのスレッド(Excel・Word・PowerPoint・Office を使わずに読むワーカー)ごとに w<番号> のフォルダに分ける(newWorkerTmpDir。work/publish/<PID> も同じ。取り込みの並列化)。

ワークスペースのパスに [ ] が含まれる(Excel が保存できない)・パスが長すぎる(Office が開けない)ときは、作業フォルダを作らず、取り込みをすべてスキップする(どのファイルも中間 TSV やコピー(Office・テキストとも、元のファイルのコピーをここに置いて読み、読み終えたら消す)をこの作業領域に作るため、テキストファイルを含めすべての取り込みが対象になる。%TEMP% には逃がさない。理由をログに 1 行残し、スキップした各ファイルは取り込みの失敗として取り込み一覧に残る。エラーメッセージ)。インデックス作成の始め(initTmpDir)に、強制終了などで残った前回までの作業フォルダ(work/tmp/ 配下・work/publish/ 配下・前の版(%TEMP%\tebunko\)が残したものがあればそれも)を片付けてから、今回の場所を決める。

できた TSV をインデックス(本文インデックスに入れる前の置き場所)に入れるときは、work/publish/<PID> にいったん集めてからフォルダごと入れ替える(publishIndexFiles)。途中で強制終了しても作りかけのインデックスが残らない。フォルダごと移すには同じドライブである必要があるため、作業領域とは別に work の中に置く。どちらのフォルダも、終了時と次回の開始時(終了済みのプロセスの分)に削除する。

データの置き場所(setting.config・work/)

ツールを書き込めない場所(C:\Program Files、読み取り専用の共有フォルダ)に置いても動くよう、また、インデックス(元の文書の本文を持つ。安全性の要約 の インデックスが元文書の本文を保持する(情報の集約))をアクセス権を絞ったフォルダや容量のあるドライブに置けるよう、データの置き場所をツールのフォルダと分けられるようにしている。

flowchart TD
    A["$rootDir に書き込める?"] -- はい --> B["設定の置き場 = $rootDir"]
    A -- いいえ --> C["設定の置き場 = 既定のワークスペース(%USERPROFILE%\Documents\tebunko_ws)の直下"]
    B & C --> D["$settingsFile = 設定の置き場\setting.config"]
    D --> E{"setting.config の workspaceFolder は空?"}
    E -- はい --> F["既定: %USERPROFILE%\Documents\tebunko_ws"]
    E -- いいえ --> G["workspaceFolder の場所"]
    F & G --> H["Workspace(下の「ワークスペースの中の場所」)"]
変数 決め方 定義
設定の置き場 ツールのフォルダ($rootDir)にファイルを作れればそこ。作れなければ、呼び出し側が渡す代わりのフォルダ(tebunko では既定のワークスペース getDefaultWorkDir)の直下。%LOCALAPPDATA%\tebunko と %TEMP% には置かない(ツールのフォルダ自体が %LOCALAPPDATA%\Programs\tebunko にあるインストーラー版では、書き込めるのでその直下に置く) scripts/shared/core/data_dir.ps1 の getDataDir(書き込めるかは testWritableFolder。試しに作ったファイルは閉じると消える)、scripts/tebunko/core/settings.ps1 の getSettingsFilePath
$settingsFile 設定の置き場の setting.config scripts/tebunko/core/settings.ps1
$workspace.Dir setting.config の workspaceFolder(設定ファイル(setting.config)の形式)。空なら既定の %USERPROFILE%\Documents\tebunko_ws(getDefaultWorkDir。OneDrive にリダイレクトされた「ドキュメント」ではなく、プロファイルの直下の Documents) scripts/tebunko/core/settings.ps1(getWorkDir)
  • 既定の場所はドキュメントにする。既定の場所にほかのファイルが置いてあると、インデックスのファイルと混ざるため使わせない。ただし設定ファイル(setting.config・保存途中の setting.config.tmp・壊れた設定の退避 setting.config.broken-<日時>[-<番号>]。testSettingsFileName)は、ツールのフォルダに書けないときにここへ置くので、ワークスペースの中身として数えない(移す・消す対象にもならない。Workspace.Entries に入らない)(testDefaultWorkspace・getWorkspaceBlockMessage。起動時・インデックス作成の開始・[既定に戻す]・インデクサで確かめ、「…」は空のフォルダではありません。… と出す)。無い・空・前から使っているワークスペース(store・前の版の content_index・前の前の版の index・ingest_status.tsv のどれかがある)なら使える。以前の既定(設定ファイルと同じフォルダの work)からは移さない(使い続けるときは[設定]の[変更…]で選ぶ)。
  • $workspace.Dir のフォルダを画面ではワークスペースと呼ぶ。[設定]で表示し、[変更…]で空のフォルダに変えられる([設定]タブ)。
  • work/ の中身(インデックス・取り込み一覧・ログ・取り込みの出力)はまとめて動く。取り込みの出力(work/publish/<PID>)はインデックスとフォルダごと入れ替えるため、インデックスと同じ work の中に置く。
  • 置き場所を変えると、今の work/ の中身(tebunko が作るファイル・フォルダだけ。Workspace.Entries)を新しい場所へ移す(WorkspaceMover.MoveEntries)。新しい場所に同じ名前があれば移さずに止める。フォルダは、ほかの処理が一時的に掴んでいても、待ちながら数回試して移す。数回試しても途中で移せなければ移した分を戻し、戻せなかった項目は名前と場所を伝える。検索対象のツリーでチェックを外したフォルダ(searchExcludes)も、移した先のインデックスに付け替える(moveSearchExcludes)。ただし新しい場所にすでにインデックスなどがあるとき(ほかの人が共有したワークスペースなど)は、それを使う(今の中身は移さず、インデックスの一覧をそのワークスペースの取り込み一覧に合わせる)か、消して最初からやり直す(消してから今の中身を移す)かを利用者が選ぶ([設定]タブ)。
  • 同じ work を複数の PC・利用者から同時に使うことは考えない(取り込み一覧・インデックスが食い違う)。同じ PC の中では、インデックス作成の二重起動の鍵を $workspace.Dir から作るため、別のツールのフォルダから同じ work を指しても二重には動かない。
  • $rootDir が書き込めるかは読み込むたびに調べる。書き込めない場所から書き込める場所に戻すと、設定は $rootDir 直下のものに戻る。

パス定義

パスと定数は、どのツールからも使うもの(shared/)と tebunko 固有のもの(tebunko/core/paths.ps1・settings.ps1)に分かれる。

変数 値 定義
$rootDir リポジトリ直下 shared/core/paths.ps1
$utf8Bom BOM 付き UTF-8 の System.Text.Encoding shared/core/paths.ps1
$cellNewLine インデックス TSV でセル内改行の代わりに使う文字(U+2028 LINE SEPARATOR) shared/core/text.ps1
$maxFileNameLength ファイル名 1 つの長さの上限(255) shared/core/text.ps1
$officeFileKinds 取り込み対象の拡張子(.xlsx .xlsm .xls .xlsb .docx .docm .doc .pptx .pptm .ppt)と、その種類(Excel・Word・PowerPoint)の表。拡張子と種類の対応はここだけにある shared/office/office_file_kind_view.ps1
$officeExtensions 取り込み対象の拡張子($officeFileKinds の拡張子) shared/office/office_file_kind_view.ps1
$pdfExtensions 取り込み対象の PDF の拡張子(.pdf) shared/core/pdf_file.ps1
$officeProcessNames 強制終了の対象のプロセス名 → 表示名(EXCEL → Excel、WINWORD → Word、POWERPNT → PowerPoint) shared/office/office_process.ps1
$workspace 今のワークスペース(Workspace。下の「ワークスペースの中の場所」)。設定 workspaceFolder から決める(getWorkDir) tebunko/core/paths.ps1
$tmpDir 取り込みの作業フォルダ(work/tmp/<PC の鍵>/<PID>。initTmpDir が決める。置けないときは空で、取り込みのスレッドは、その下の w<番号> を使う) 同上
$tmpDirReason $tmpDir を置けなかった理由(Brackets / TooLong)。置けたときは空 同上
${legacyTmpParent} 前の版(%TEMP%\tebunko\<PID> に一時ファイルを置いていた版)が残した作業フォルダの片付け専用。今の版はここに書き込まない 同上
$sourceFolderFileName 各インデックスのフォルダに置く元のフォルダの記録のファイル名(source_folder.txt) 同上
$indexingPhaseCrawl / $indexingPhaseConfirm / $indexingPhaseIngest / $indexingPhaseFinish インデックス作成の進み具合の段階(クロール / 確認 / 取り込み / 仕上げ) 同上
$ingestPlanColumns 取り込み予定の列名(インデックス名 元のフォルダ 区分 ファイル数 取り込み対象 新規 更新あり 前回未完了 インデックスなし 前回失敗 クラウド クラウド失敗 クラウド容量 クラウド失敗容量) 同上
$planKindIngest / $planKindUnchecked / $planKindMissing / $planKindDropped 取り込み予定の区分(取り込み / チェックなし / フォルダなし / 削除予定。削除予定 は設定から外れたインデックスで、確認のあとにだけ消す) 同上
$statusColumns 取り込み一覧の列名(相対パス 更新日時 サイズ 状態 TSV数 取り込み日時 エラー 抽出版) 同上
$statusFolderKey 取り込み一覧の先頭のクロール対象フォルダの行の見出し(クロール対象フォルダ) 同上
$stateNew / $stateDone / $stateFailed 取り込み一覧の状態(未取り込み / 済 / 失敗) 同上
$appId ツールの ID(tebunko。ミューテックスの名前に使う) tebunko/core/settings.ps1(起動口が lib.ps1 より先に settings.ps1 だけを読み込んで設定を確かめるため、ここで決める)
$settingsFile 設定の置き場の setting.config(上の「データの置き場所」。画面が保存する設定。内容は JSON。設定ファイル(setting.config)) tebunko/core/settings.ps1
$openModeNormal / $openModeReadOnly / $openModeNew・$openModes 元のファイルの開き方(設定 openMode の値 normal / readOnly / new)と、その一覧 同上

ワークスペースの中の場所(Workspace)

tebunko/core/workspace.ps1 の Workspace クラスは、ワークスペースのフォルダ(Dir)から中の場所を組み立てる。設定は読まない。

flowchart LR
    W["Workspace(Dir)"] --> IX["IndexDir<br>Dir\store\content"]
    W --> LI["LegacyIndexDir<br>Dir\index(前の版。読まず消さない)"]
    W --> GR["GramDir<br>Dir\store\gram"]
    W --> SI["OldSystemIndexDir<br>Dir\system_index(前の版。起動・インデックスの作成と更新の始め・インポートのときに消す)"]
    W --> SS["OldSystemIndexStateFile<br>Dir\system_index_state.tsv"]
    W --> PB["PublishDir<br>Dir\publish\<PID>"]
    W --> ST["StatusFile<br>Dir\store\ingest_status.tsv"]
    W --> IG["JournalFile<br>Dir\store\journal\ingest.tsv"]
    W --> OP["OfficePidRoot<br>Dir\office_pids"]
    W --> RS["ResultFile<br>Dir\search_results.txt"]
    W --> IL["IndexingLogFile<br>Dir\indexing_log.txt"]
    W --> GE["GuiErrorLogFile<br>Dir\gui_error_log.txt"]
    W --> ILP["IndexingLogPreviousFile<br>Dir\indexing_log_previous.txt"]
    W --> GEP["GuiErrorLogPreviousFile<br>Dir\gui_error_log_previous.txt"]
  • 関数は、ワークスペースの中の場所を既定値で $workspace から取る(例 [string]$path = $workspace.StatusFile)。既定値は呼んだときに決まるため、$workspace を差し替えれば、読み込み直さずに別のワークスペースを使う。
  • 別のスレッド(画面の裏の仕事・検索の司令・取り込み)は lib.ps1 を読み込んだときの $workspace を持つ。そのため画面は、場所を引数で渡すか、Dir(文字列)を渡してそのスレッドで Workspace を作り直す。オブジェクトはスレッドをまたいで渡さない。
  • 取り込みのスレッドは PublishDir を、その下の w<番号> に差し替える。
  • ワークスペースを変えるときは、今のワークスペースの中身を移す。移すのは Entries()(tebunko が作るファイル・フォルダ)だけで、利用者のほかのファイルは移さない。WorkspaceMover.ListEntries(あるものだけ)・WorkspaceMover.Conflicts(移し先に同じ名前があるもの)・WorkspaceMover.MoveEntries(移す。移し先に同じ名前があれば何も移さず、フォルダは moveDirectoryRetry で数回試して移し、途中で失敗したら移した分を戻す。戻せなかった項目は例外の文に書く。別のドライブ(testSameDriveRoot が偽)のフォルダは CopyTree で写してから消し、元を消せなければ移し先を正として、残った元の場所を戻り値の Leftovers で返す)・moveSearchExcludes(searchExcludes を移した先のインデックスに付け替える)。選んだフォルダにすでにインデックスなどがあれば、WorkspaceMover.UseTargets(そのワークスペースの取り込み一覧のクロール対象フォルダを、インデックスの一覧にする)で使うか、WorkspaceMover.RemoveEntries(tebunko のファイル・フォルダだけを削除する)で消してから移す。
  • 前の前の版の index\ の扱い(前の前の版の index\ の扱い): getLegacyIndexState(dir → @{HasLegacyIndex; ContentEmpty}。前の前の版のしるし・store\content\ と content_index\ がどちらも空かを調べる)・getLegacyIndexMessage(dir, hasLegacyIndex → 知らせの文言。しるしが無ければ空)。画面の判断層(indexing_view.ps1 の getReingestConfirm。hasLegacyIndex, contentEmpty → 確かめの文言)は[すべて更新]で使う(更新し直しの確かめ)。
  • 前の版が作った検索用のファイル(前の版が作った検索用のファイルの片付け): removeOldSystemIndex(dir → @{Ok; Reason}。system_index\ と system_index_state.tsv の削除。失敗したら理由を返す)。画面の起動のとき(裏の仕事。startOldSystemIndexRemoval)、インデクサ(invokeIndexerBody)のインデックス作成の始め、インポートの取り込む前に呼ぶ。
プロパティ 値
Dir ワークスペースのフォルダ
StoreDir <Dir>\store(格納形式の置き場。目録 format.tsv・取り込み一覧・本文インデックスをまとめる)
FormatFile <Dir>\store\format.tsv(目録。目録)
IndexDir <Dir>\store\content
OldIndexDir <Dir>\content_index(前の版の置き場。読まず、作り直しが終わったら消す)
LegacyIndexDir <Dir>\index(前の版が使っていた場所。読まず、消しもしない)
GramDir <Dir>\store\gram(2-gram の索引)
OldSystemIndexDir <Dir>\system_index(前の版のシステムインデックス。読まず、起動・インデックス作成の始め・インポートのときに消す)
OldSystemIndexStateFile <Dir>\system_index_state.tsv(前の版の状態ファイル。同じく消す)
PublishDir <Dir>\publish\<PID>(TSV をインデックスに入れる直前に集めるフォルダ)
StatusFile <Dir>\store\ingest_status.tsv
OldStatusFile <Dir>\ingest_status.tsv(前の版の取り込み一覧。作り直しが終わったら消す)
JournalFile <Dir>\store\journal\ingest.tsv
ResultFile <Dir>\search_results.txt
IndexingLogFile <Dir>\indexing_log.txt(インデクサの表示内容の記録。実行ごとに新しく書き、前回の分は IndexingLogPreviousFile へ移す)
IndexingLogPreviousFile <Dir>\indexing_log_previous.txt(前回のインデックス作成の記録)
GuiErrorLogFile <Dir>\gui_error_log.txt(画面で起きた予期しないエラーの記録。追記。共通基盤の writeErrorLog は、画面が setGuiErrorLogSource で登録する getToolGuiErrorLogFile からこの場所を得る)
GuiErrorLogPreviousFile <Dir>\gui_error_log_previous.txt(gui_error_log.txt が 1 MB 以上になったときに移した前の分)