package io.eguan.iscsisrv;
/*
* #%L
* Project eguan
* %%
* Copyright (C) 2012 - 2017 Oodrive
* %%
* Licensed 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.
* #L%
*/
import io.eguan.iscsisrv.IscsiServerConfig;
import io.eguan.iscsisrv.IscsiTarget;
import io.eguan.srv.TestAbstractServerIO;
import java.io.File;
import java.io.FileInputStream;
import java.io.RandomAccessFile;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.util.ArrayList;
import java.util.Random;
import java.util.concurrent.Future;
import org.jscsi.target.TargetServer;
import org.junit.Assert;
import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class IscsiServerIOTest extends
TestAbstractServerIO<TargetServer, IscsiTarget, IscsiServerConfig, IscsiServerTargetImpl> {
static final Logger LOGGER = LoggerFactory.getLogger(IscsiServerIOTest.class);
public IscsiServerIOTest() {
super(new IscsiServerTargetImpl());
}
@Test
public void testTargetMultiThreadedWrite() throws Exception {
final File deviceFile = File.createTempFile("testDevice", null);
targets.put(deviceFile, Long.valueOf(size));
mgr.addTarget(server, targets);
final File tmpFile = File.createTempFile("vold", "test");
try {
final InitiatorClientBasicIops iopClient = (InitiatorClientBasicIops) mgr.initClient();
iopClient.createSession(mgr.getTargetName(deviceFile));
try {
writeData(tmpFile, iopClient, mgr.getTargetName(deviceFile));
readData(tmpFile, iopClient, mgr.getTargetName(deviceFile), size);
}
finally {
iopClient.closeSession(mgr.getTargetName(deviceFile));
}
}
finally {
tmpFile.delete();
}
}
private final void writeData(final File dataDump, final InitiatorClientBasicIops initiator, final String target)
throws Exception {
final Random random = new Random(System.currentTimeMillis());
final ArrayList<Future<Void>> writes = new ArrayList<>();
try (final RandomAccessFile raf = new RandomAccessFile(dataDump.getAbsolutePath(), "rw")) {
final FileChannel out = raf.getChannel();
for (int i = 0; i < LENGTH; i++) {
final ByteBuffer writeData = ByteBuffer.allocate(BLOCKSIZE * NUMBLOCKS);
final int lba = i * NUMBLOCKS;
random.nextBytes(writeData.array());
// Write buffer in the tmp file
out.write(writeData, lba * BLOCKSIZE);
writeData.rewind();
// Write it on the target
writes.add(initiator.multiThreadedWrite(target, writeData, lba, writeData.capacity(), BLOCKSIZE));
}
for (int i = 0; i < LENGTH; i++) {
writes.get(i).get();
}
}
}
private final void readData(final File dataDump, final InitiatorClientBasicIops initiator, final String target,
final long size) throws Exception {
final ByteBuffer readData = ByteBuffer.allocate(BLOCKSIZE * NUMBLOCKS);
final ByteBuffer refData = ByteBuffer.allocate(BLOCKSIZE * NUMBLOCKS);
try (final FileInputStream fis = new FileInputStream(dataDump.getAbsolutePath())) {
final FileChannel in = fis.getChannel();
for (int i = 0; i < LENGTH; i++) {
final int lba = i * NUMBLOCKS;
int toRead = BLOCKSIZE * NUMBLOCKS;
toRead -= in.read(refData, lba * BLOCKSIZE);
while (toRead > 0) {
toRead -= in.read(refData);
}
refData.rewind();
initiator.read(target, readData, lba, readData.capacity(), BLOCKSIZE);
readData.rewind();
Assert.assertEquals("Error i=" + i + ", lba=" + lba, readData, refData);
}
}
/* !!! Initiator.getCapacity() == last block address */
initiator.checkCapacity(target, size);
}
}