org.elasticsearch.cloud.azure.SmbDirectoryWrapper Maven / Gradle / Ivy
Show all versions of cloud-azure Show documentation
/*
* Licensed to Elasticsearch under one or more contributor
* license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright
* ownership. Elasticsearch licenses this file to you under
* the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.elasticsearch.cloud.azure;
import java.io.FilterOutputStream;
import java.io.IOException;
import java.nio.channels.Channels;
import java.nio.file.Files;
import java.nio.file.StandardOpenOption;
import org.apache.lucene.store.FSDirectory;
import org.apache.lucene.store.FilterDirectory;
import org.apache.lucene.store.IOContext;
import org.apache.lucene.store.IndexOutput;
import org.apache.lucene.store.OutputStreamIndexOutput;
/**
* This class is used to wrap an existing {@link org.apache.lucene.store.FSDirectory} so that
* the new shard segment files will be opened for Read and Write access.
*
* When storing index files on an SMB share like Azure File Service, opening the file for Read
* access can save a lot of roundtrips to the storage server and thus offering better performance.
*/
public final class SmbDirectoryWrapper extends FilterDirectory {
private final FSDirectory fsDirectory;
public SmbDirectoryWrapper(FSDirectory in) {
super(in);
fsDirectory = in;
}
@Override
public IndexOutput createOutput(String name, IOContext context) throws IOException {
this.ensureOpen();
return new SmbFSIndexOutput(name);
}
/**
* Copied from final inner class {@link org.apache.lucene.store.FSDirectory.FSIndexOutput}
*/
final class SmbFSIndexOutput extends OutputStreamIndexOutput {
/**
* The maximum chunk size is 8192 bytes, because {@link java.io.FileOutputStream} mallocs
* a native buffer outside of stack if the write buffer size is larger.
*/
static final int CHUNK_SIZE = 8192;
private final String name;
public SmbFSIndexOutput(String name) throws IOException {
super("SmbFSIndexOutput(path=\"" + fsDirectory.getDirectory().resolve(name) + "\")", new FilterOutputStream(Channels.newOutputStream(Files.newByteChannel(fsDirectory.getDirectory().resolve(name), StandardOpenOption.CREATE, StandardOpenOption.TRUNCATE_EXISTING, StandardOpenOption.READ, StandardOpenOption.WRITE))) {
// This implementation ensures, that we never write more than CHUNK_SIZE bytes:
@Override
public void write(byte[] b, int offset, int length) throws IOException {
while (length > 0) {
final int chunk = Math.min(length, CHUNK_SIZE);
out.write(b, offset, chunk);
length -= chunk;
offset += chunk;
}
}
}, CHUNK_SIZE);
this.name = name;
}
}
}