hadoop fs -rmコマンド コードリーディング
hadoop fs -rm
コマンドの挙動を詳しく確認する必要があり、コードリーディングを行った。
コード自体は自体は以下に存在しており、他のコマンドの実装も周辺にある。 github.com
実装上、-rm
、-rmdir
、-rmr
、-expunge
は全て異なる実装が行われているが、
今回対象としたのは -rm
だけである。
- 引数で与えられたオプションを処理 (
-r
,-f
,-R
,-skipTrash
,-safely
) - 引数で与えられたパス文字列を内部で PathData に変換 pathが見つからない場合終了
- 与えられたパスごとに以下の処理を実行。パスが存在しない場合終了
- まずディレクトリかどうかを確認。
-r
オプションが設定されていない場合にディレクトリを作成しようとすると失敗する - ゴミ箱に入れる処理を行う (hdfsでは実際にファイルを削除する前にTrashというゴミ箱に一時的に入る)
-skipTrash
オプションが存在する場合、処理をスキップfs.trash.interval
が Trashから削除される時間を制御. サーバー側で設定されている場合にはその値を優先するfs.trash.interval
が0の場合、Trashに入れずに直接削除する- Trashが有効な場合、まずhdfs上の絶対パスに直して、file statusを取得(この時点でgetfileinfoが発行される)
- 削除対象のパスを完全修飾パスに直す
- 現在のユーザーのTrashRootを取得する (実行ユーザーのHome Directoryに作成される xxx userで実行する場合 /user/xxx/.Trash )
- そして現在のTrashのパスは /user/xxx/.Trash/Current である
- もし、削除対象のパスがTrashRootに存在する場合、既にTrashに入っているので処理をスキップする
- そして逆にTrashRootを削除しようとする場合、削除できないので例外を投げる
- 削除対象のファイルがTrashで置かれるパスを計算
- 以下を最大2回行う
- fs.mkdirsでtrashRootの親ディレクトリを作成する。作成できない場合はTrash処理を終了
- ファイルが存在していて作成に失敗した場合は、現在時間をsuffixにしたディレクトリを親に作成することにして失敗を無視してリトライ
- 削除するファイルの名前で既にTrashに存在する場合も、現在時刻をsuffixにしたファイル名をTrashでのファイル名にする
- fs.renameでTrashに名前を変更して移動する(これが削除処理にあたる)
"Moved: '" + path + "' to trash at: " + trashPath
成功するとこれがログに出る- 失敗した場合、コマンドが失敗する
- まずディレクトリかどうかを確認。
- Trashに入れれた場合には処理を終了する。そうでない場合続行。
-safely
オプションが指定されている場合、巨大なディレクトリが削除されるような場合には確認を行い問題なければ削除に進む- fs.deleteを実行して、Trashをスキップして完全にファイルを削除する
また、コマンドの実行を細かく調査する際に、サーバー側のaudit logが設定されていればこれを確認することで実際に発行された操作の詳細を確認可能である。
例えば、クライアントで実行したコマンドが hadoop fs -rm -r xxx
だった場合でも実際にサーバー側に発行されているのは以下の4つのコマンドである。
20xx-xx-xx xx:xx:xx,xxx INFO FSNamesystem.audit: allowed=true ugi=xxx (auth:SIMPLE) ip=/xx.xxx.xxx.xx cmd=getfileinfo src=/xxx dst=null perm=null proto=rpc 20xx-xx-xx xx:xx:xx,xxx INFO FSNamesystem.audit: allowed=true ugi=xxx (auth:SIMPLE) ip=/xx.xxx.xxx.xx cmd=getfileinfo src=/xxx dst=null perm=null proto=rpc 20xx-xx-xx xx:xx:xx,xxx INFO FSNamesystem.audit: allowed=true ugi=xxx (auth:SIMPLE) ip=/xx.xxx.xxx.xx cmd=getfileinfo src=/xxx dst=null perm=null proto=rpc 20xx-xx-xx xx:xx:xx,xxx INFO FSNamesystem.audit: allowed=true ugi=xxx (auth:SIMPLE) ip=/xx.xxx.xxx.xx cmd=mkdirs src=/user/xxx/.Trash/Current/tmp dst=null perm=xxx:supergroup:rwx------ proto=rpc