Analysis Plugins を作成して、自然言語解析が行える外部プログラムを呼び出したいと考えているのですが、呼び出した際に、以下のような IOException が発生しており、調査をしています。
...<略>...
Caused by: java.io.IOException: Cannot run program "C:/DummyAnalyzer/dummyanalyzer.bat": CreateProcess error=1816, この コマンドを実行するための十分なクォータがありません。
at java.base/java.lang.ProcessBuilder.start(ProcessBuilder.java:1128)
at java.base/java.lang.ProcessBuilder.start(ProcessBuilder.java:1071)
at java.base/java.lang.Runtime.exec(Runtime.java:589)
at java.base/java.lang.Runtime.exec(Runtime.java:448)
at com.example.index.analysis.DummyCharFilter$1.run(DummyCharFilter.java:90)
... 21 more
Caused by: java.io.IOException: CreateProcess error=1816, このコマンドを実行するための十分なクォータがありません。
at java.base/java.lang.ProcessImpl.create(Native Method)
at java.base/java.lang.ProcessImpl.<init>(ProcessImpl.java:483)
at java.base/java.lang.ProcessImpl.start(ProcessImpl.java:158)
at java.base/java.lang.ProcessBuilder.start(ProcessBuilder.java:1107)
... 25 more
環境は次の通りです。
- Elasticsearch 7.6.0 (シングルノード)
- Windows 10
Character Filter を次のように実装しています。
/**
* DummyCharFilter
*/
public class DummyCharFilter extends BaseCharFilter {
private Reader transformedInput;
public DummyCharFilter(Reader in) {
super(in);
}
@Override
public int read(char[] cbuf, int off, int len) throws IOException {
if (transformedInput == null) {
fill();
}
return transformedInput.read(cbuf, off, len);
}
private void fill() throws IOException {
StringBuilder buffered = new StringBuilder();
char [] temp = new char [1024];
for (int cnt = input.read(temp); cnt > 0; cnt = input.read(temp)) {
buffered.append(temp, 0, cnt);
}
transformedInput = new StringReader(execDummy(buffered).toString());
}
@Override
public int read() throws IOException {
if (transformedInput == null) {
fill();
}
return transformedInput.read();
}
@Override
protected int correct(int currentOff) {
return Math.max(0, super.correct(currentOff));
}
CharSequence execDummy(CharSequence input) {
String dummyProg = "C:/DummyAnalyzer/dummyanalyzer.bat";
String[] command = { dummyProg, input.toString() };
Runtime runtime = Runtime.getRuntime();
Process p = AccessController.doPrivileged(new PrivilegedAction<Process>() {
@Override
public Process run() {
Process proc = null;
try {
proc = runtime.exec(command);
} catch (IOException e) {
throw new AssertionError("<<Dummy program>> Failed to execution.", e);
}
return proc;
}
});
try {
p.waitFor(); // プロセスの正常終了まで待機させる
} catch (InterruptedException e) {
throw new AssertionError("<<Dummy program>> - Interruption by processing interrupted.", e);
}
InputStream is = p.getInputStream();
BufferedReader br = new BufferedReader(new InputStreamReader(is, StandardCharsets.UTF_8));
String line = null;
try {
line = br.readLine();
} catch (IOException e) {
throw new AssertionError("<<Dummy program>> - Failed to reading Standard output.", e);
}
return line;
}
}
プラグインに外部プログラムの読み取りと実行権限を与えるため plugin-security.policy
には以下の設定を行いました。
grant {
permission java.io.FilePermission "<<ALL FILES>>", "read,execute";
};
また、呼び出し先のプログラムは模擬的に以下のような bat ファイルにしています。
@echo off
echo %1 [Added By Dummy Program]
期待する挙動としては、Kibana の DevTool 等で
GET _analyze
{
"text": "本日は晴天なり。",
"char_filter": [
"dummy_char_filter"
]
}
と送信すると、text
の末尾に [Added By Dummy Program]
という文字列が付与されて、アナライズされた結果が返却される、というものなのですが、batファイルの実行タイミングで冒頭の IOException が発生している状態です。
このコマンドを実行するための十分なクォータがありません。
ということだったので、できうる限り他に起動していたアプリケーションをシャットダウンして試してみたのですが、症状は変わらないままでした。
そもそも、プラグインから外部プログラムを呼び出すことは不可能なのでしょうか?