Cygwin で Subversion を使用して一部のリポジトリを更新すると、一部のディレクトリは正常に更新されますが、他のディレクトリは次のエラー メッセージで失敗します。
svn: E200030: sqlite: ディスク I/O エラー
同じリポジトリに対して再度実行svn update
すると、別のディレクトリで同じエラーが発生する可能性があります。場合によっては、上記のエラー メッセージの後に SVN 命令が表示されます。
これは、CygwinのSQLiteパッケージで誰かが望んでいた変更が原因で発生しました。この質問があったとき、私はそのパッケージの保守者であり、この症状の原因となる変更を加えました。
この変更はCygwinSQLiteバージョンとしてリリースされ3.7.12.1-1
、1人の問題が修正されましたが、CygwinのSubversionパッケージがネイティブのWindowsSubversion実装と連携できなくなるというこの悪い副作用がありました。
ここでの主要な問題は、Subversion1.7がディスク上の作業コピーのフォーマットを変更したことです。その変更の一部には、新しいSQLiteデータベースファイルが含まれます.svn/wc.db
。ここで、SQLiteの同時実行性保証を実装するために、SQLiteはデータベースファイルにアクセスしている間、データベースファイルをロックします。
これはすべて問題なく賢明ですが、WindowsネイティブとPOSIXファイルロックのセマンティクスを混在させようとすると問題が発生します。Windowsでは、ファイルロックはほとんどの場合必須のロックを意味しますが、Linuxシステム(Cygwinがエミュレートしようとしている)では、ロックは通常、代わりにアドバイザリロックを意味します。
これは、「ディスクI/Oエラー」の原因を理解するのに役立ちます。
Cygwin SQLiteの3.7.12.1-1
変更は、ライブラリを「Cygwinモード」ではなく「Unixモード」でビルドすることでした。Cygwinモードでは、ライブラリはWindowsネイティブファイルロックを使用します。これはCygwinの哲学に反します。可能な場合、CygwinパッケージはWindows APIに直接ではなくPOSIX関数を呼び出すcygwin1.dll
ため、適切なPOSIXセマンティクスを提供できます。
問題のSQLiteDBにアクセスするすべてのプログラムがCygwinで構築されている場合、POSIXアドバイザリファイルロックはまさにSQLiteで必要なものです。これは、Cygwin内のデフォルトの前提です。ただし、TortoiseSVNなどのWindowsネイティブSubversionプログラムを純粋なPOSIX Cygwinと一緒に実行するとsvn
、競合が発生します。TortoiseSVN Windowsエクスプローラーのシェル拡張機能で.svn/wc.db
ファイルが必須ロックでロックされていて、Cygwinsvn
がアクセスしてアドバイザリロックを試行すると、すぐに失敗します。Cygwinsvn
は、ロックの試行がすぐに成功するか、成功するまでブロックされると想定しているため、ロックの失敗をディスクI/Oエラーとして誤って解釈します。
Cygwin内では、可能な限りWindowsネイティブプログラムで常にうまく機能するようにしています。秘訣は、Cygwinプログラムでもうまく遊んでいる間に、それを行う方法を見つけることでした。
誰もがこれを試みるべきだということに同意したわけではありません。「CygwinSQLiteはCygwinの一部であるため、他のCygwinプログラムとうまく連携する必要があるだけです」とあるグループは言います。カウンターパーティの回答者は、「CygwinはWindowsで実行されるため、他のWindowsプログラムとうまく連携する必要があります」と答えます。
幸い、私たちは両方のグループを幸せにする方法を思いつきました。
3.7.17-x
Cygwin SQLiteのパッケージ化作業の一環として、 CorinnaVinschenがバージョン1.7.19に追加した新機能をテストしました。これにより、プログラムはBSDファイルロックAPIを介して必須のファイルロックを要求できました。私の変更の一部は、Cygwin SQLiteにユーザーの指示でこの機能のオンとオフを切り替えさせ、同じパッケージでCygwin中心のキャンプとWindowsネイティブのキャンプの両方のニーズを満たすことができるようにすることでした。cygwin1.dll
3.7.13-3
このCygwinDLL機能は1.7.20でさらに改善され、最終的なロックセマンティクスを使用してCygwinSQLiteをリリースしました。このバージョンでは、POSIXアドバイザリロック、BSDアドバイザリロック、およびBSD/Cygwin必須ロックの3つのロック戦略を選択できました。これまでのところ、後者の戦略は、ネイティブのWindowsロックと完全に互換性があることが証明されています。
その後、JanNijtmansがCygwinSQLiteのメンテナンスを引き継いだとき、彼はこのメカニズムをSQLiteVFSレイヤーと完全に統合することでさらに強化しました。これにより、4番目のオプションが可能になりました。この旅を始める前にCygwinSQLiteが使用していたネイティブのWindowsロックです。これは主に、BSD/Windowsのロック戦略がネイティブのWindowsSQLiteプログラムとうまく連携しない可能性に対するヘッジです。私の知る限り、このオプションを使用する必要はありませんが、そこにあることを知っておくと便利です。
Cygwinのコマンドラインsvn
とTortoiseSVNWindowsExplorerシェル拡張機能の間に競合がある場合は、それを修正する別のオプションがあります。TortoiseSVNには、ネイティブのWindowsSubversionコマンドラインプログラムも付属しています。PATH
これらをCygwinのディレクトリの前に置いておけばbin
、この問題に遭遇することはまったくありません。
同じ問題が発生したため、(少なくとも私の場合は) TortoiseSVN とのやり取りのようです。TortoiseSVN のステータス アイコン キャッシュを無効にすると ([設定] > [アイコン オーバーレイ] > [ステータス キャッシュ「なし」] > [適用])、すべて正常に機能します。
(それは明らかに根本的な問題を解決しません。これは、Cygwin の Subversion パッケージがそのアクセス モードの変更に依存している SQL パッケージが原因であるように思われます。私が書いているように、Cygwin メーリング リストでは、その方法について活発な [遅い場合] の議論があります。これを解決します。)
ldd /usr/bin/svn
SVN が /usr/bin/cygsqlite3-0.dll に依存していることを示しています。
libsqlite3 を 3.7.12 から 3.7.3 に戻すと、問題は解決したようです。したがって、これはSQLiteライブラリの問題である可能性があります。
TortoiseSVN を使用して、問題Refresh shell overlays
をclean up
解決しました。
参考までに、同じエラー ( svn: E200030: sqlite: disk I/O error
) が発生し、ログ ファイルの 1 つがすべての容量を占有していることがわかりました (空き容量がないため、HDD に書き込むことができませんでした)。
実行 (十分なディスク容量があることを確認するため)
df -h
(いくつかの大きなファイルを削除しない場合 (いくつかのバックアップ ファイルとログ ファイルを削除しただけです)
次に、実行する必要がありました:
svn cleanup
これでエラーが解決しました。