class TarantoolClient extends DB {
  private static final Logger LOGGER = Logger.getLogger(TarantoolClient.class.getName());

  private static final String HOST_PROPERTY = "tarantool.host";
  private static final String PORT_PROPERTY = "tarantool.port";
  private static final String SPACE_PROPERTY = "tarantool.space";
  private static final String DEFAULT_HOST = "localhost";
  private static final String DEFAULT_PORT = "3301";
  private static final String DEFAULT_SPACE = "1024";

  private TarantoolConnection16 connection;
  private int spaceNo;

  public void init() throws DBException {
    Properties props = getProperties();

    int port = Integer.parseInt(props.getProperty(PORT_PROPERTY, DEFAULT_PORT));
    String host = props.getProperty(HOST_PROPERTY, DEFAULT_HOST);
    spaceNo = Integer.parseInt(props.getProperty(SPACE_PROPERTY, DEFAULT_SPACE));

    try {
      this.connection = new TarantoolConnection16Impl(host, port);
    } catch (Exception exc) {
      throw new DBException("Can't initialize Tarantool connection", exc);
    }
  }

  public void cleanup() throws DBException {
    this.connection.close();
  }

  @Override
  public Status insert(String table, String key, Map<String, ByteIterator> values) {
    return replace(key, values, "Can't insert element");
  }

  private HashMap<String, ByteIterator> tupleConvertFilter(List<String> input, Set<String> fields) {<FILL_FUNCTION_BODY>}

  @Override
  public Status read(String table, String key, Set<String> fields, Map<String, ByteIterator> result) {
    try {
      List<String> response = this.connection.select(this.spaceNo, 0, Arrays.asList(key), 0, 1, 0);
      result = tupleConvertFilter(response, fields);
      return Status.OK;
    } catch (TarantoolException exc) {
      LOGGER.log(Level.SEVERE, "Can't select element", exc);
      return Status.ERROR;
    } catch (NullPointerException exc) {
      return Status.ERROR;
    }
  }

  @Override
  public Status scan(String table, String startkey,
                     int recordcount, Set<String> fields,
                     Vector<HashMap<String, ByteIterator>> result) {
    List<List<String>> response;
    try {
      response = this.connection.select(this.spaceNo, 0, Arrays.asList(startkey), 0, recordcount, 6);
    } catch (TarantoolException exc) {
      LOGGER.log(Level.SEVERE, "Can't select range elements", exc);
      return Status.ERROR;
    } catch (NullPointerException exc) {
      return Status.ERROR;
    }
    for (List<String> i : response) {
      HashMap<String, ByteIterator> temp = tupleConvertFilter(i, fields);
      if (!temp.isEmpty()) {
        result.add((HashMap<String, ByteIterator>) temp.clone());
      }
    }
    return Status.OK;
  }

  @Override
  public Status delete(String table, String key) {
    try {
      this.connection.delete(this.spaceNo, Collections.singletonList(key));
    } catch (TarantoolException exc) {
      LOGGER.log(Level.SEVERE, "Can't delete element", exc);
      return Status.ERROR;
    } catch (NullPointerException e) {
      return Status.ERROR;
    }
    return Status.OK;
  }

  @Override
  public Status update(String table, String key, Map<String, ByteIterator> values) {
    return replace(key, values, "Can't replace element");
  }

  private Status replace(String key, Map<String, ByteIterator> values, String exceptionDescription) {
    int j = 0;
    String[] tuple = new String[1 + 2 * values.size()];
    tuple[0] = key;
    for (Map.Entry<String, ByteIterator> i : values.entrySet()) {
      tuple[j + 1] = i.getKey();
      tuple[j + 2] = i.getValue().toString();
      j += 2;
    }
    try {
      this.connection.replace(this.spaceNo, tuple);
    } catch (TarantoolException exc) {
      LOGGER.log(Level.SEVERE, exceptionDescription, exc);
      return Status.ERROR;
    }
    return Status.OK;

  }
}

    HashMap<String, ByteIterator> result = new HashMap<>();
    if (input == null) {
      return result;
    }
    for (int i = 1; i < input.toArray().length; i += 2) {
      if (fields == null || fields.contains(input.get(i))) {
        result.put(input.get(i), new StringByteIterator(input.get(i + 1)));
      }
    }
    return result;
  
<methods>public non-sealed void <init>() ,public void cleanup() throws site.ycsb.DBException,public abstract site.ycsb.Status delete(java.lang.String, java.lang.String) ,public java.util.Properties getProperties() ,public void init() throws site.ycsb.DBException,public abstract site.ycsb.Status insert(java.lang.String, java.lang.String, Map<java.lang.String,site.ycsb.ByteIterator>) ,public abstract site.ycsb.Status read(java.lang.String, java.lang.String, Set<java.lang.String>, Map<java.lang.String,site.ycsb.ByteIterator>) ,public abstract site.ycsb.Status scan(java.lang.String, java.lang.String, int, Set<java.lang.String>, Vector<HashMap<java.lang.String,site.ycsb.ByteIterator>>) ,public void setProperties(java.util.Properties) ,public abstract site.ycsb.Status update(java.lang.String, java.lang.String, Map<java.lang.String,site.ycsb.ByteIterator>) <variables>private java.util.Properties properties