docs: public static void main(String[] args) throws IOException,
              InterruptedException {
          start = System.currentTimeMillis();
          long insertTimeStart = start;
          long insertTimeEnd;
          FileReader fr = null;
          BufferedReader br = null;
          final CSVConfig cfg = new CSVConfig();
          cfg.parse(CSVLoader.class.getName(), args);
          config = cfg;
          if (config.noquotechar) {
              config.quotechar = '\u0000';
          }
  
          configuration();
  
          final Tokenizer tokenizer;
          ICsvListReader listReader = null;
          try {
              if (CSVLoader.standin) {
                  tokenizer = new Tokenizer(new BufferedReader(new InputStreamReader(System.in)), csvPreference,
                          config.strictquotes, config.escape, config.columnsizelimit,
                          config.skip, config.header);
                  listReader = new CsvListReader(tokenizer, csvPreference);
              } else {
                  FileInputStream fis = new FileInputStream(config.file);
                  InputStreamReader isr = new InputStreamReader(fis, config.charset);
                  tokenizer = new Tokenizer(isr,
                            csvPreference,
                            config.strictquotes,
                            config.escape,
                            config.columnsizelimit,
                            config.skip,
                            config.header);
  
                  listReader = new CsvListReader(tokenizer, csvPreference);
              }
          } catch (FileNotFoundException e) {
              System.err.println("CSV file '" + config.file + "' could not be found.");
              System.exit(-1);
          }
          // Split server list
          final String[] serverlist = config.servers.split(",");
  
          // read username and password from txt file
          if (config.credentials != null && !config.credentials.trim().isEmpty()) {
              Properties props = MiscUtils.readPropertiesFromCredentials(config.credentials);
              config.user = props.getProperty("username");
              config.password = props.getProperty("password");
          }
  
          // If we need to prompt the user for a password, do so.
          config.password = CLIConfig.readPasswordIfNeeded(config.user, config.password, "Enter password: ");
  
          // Create connection
          final ClientConfig c_config;
          AutoReconnectListener listener = new AutoReconnectListener();
          if (config.stopondisconnect) {
              c_config = new ClientConfig(config.user, config.password, null);
              c_config.setReconnectOnConnectionLoss(false);
          } else {
              c_config = new ClientConfig(config.user, config.password, listener);
              c_config.setReconnectOnConnectionLoss(true);
          }
          if (config.ssl != null && !config.ssl.trim().isEmpty()) {
              c_config.setTrustStoreConfigFromPropertyFile(config.ssl);
              c_config.enableSSL();
          }
          if (!config.kerberos.trim().isEmpty()) {
              c_config.enableKerberosAuthentication(config.kerberos);
          }
          c_config.setProcedureCallTimeout(0); // Set procedure all to infinite
          Client csvClient = null;
          try {
              csvClient = CSVLoader.getClient(c_config, serverlist, config.port);
          } catch (Exception e) {
              System.err.println("Error connecting to the servers: "
                      + config.servers);
              System.exit(-1);
          }
          assert (csvClient != null);
  
          try {
              long readerTime;
              long insertCount;
              long ackCount;
              long rowsQueued;
              final CSVLoader errHandler = new CSVLoader();
              final CSVDataLoader dataLoader;
  
              errHandler.launchErrorFlushProcessor();
  
              if (config.useSuppliedProcedure) {
                  dataLoader = new CSVTupleDataLoader((ClientImpl) csvClient, config.procedure, errHandler);
              } else {
                  dataLoader = new CSVBulkDataLoader((ClientImpl) csvClient, config.table, config.batch, config.update, errHandler);
              }
              if (!config.stopondisconnect) {
                  listener.setLoader(dataLoader);
              }
  
              CSVFileReader.initializeReader(cfg, csvClient, listReader);
  
              CSVFileReader csvReader = new CSVFileReader(dataLoader, errHandler);
  
              Thread readerThread = new Thread(csvReader);
              readerThread.setName("CSVFileReader");
              readerThread.setDaemon(true);
  
              //Wait for reader to finish.
              readerThread.start();
              readerThread.join();
  
              insertTimeEnd = System.currentTimeMillis();
  
              csvClient.close();
  
              errHandler.waitForErrorFlushComplete();
  
              readerTime = (csvReader.m_parsingTime) / 1000000;
              insertCount = dataLoader.getProcessedRows();
              ackCount = insertCount - dataLoader.getFailedRows();
              rowsQueued = CSVFileReader.m_totalRowCount.get();
  
              //Close the reader.
              try {
                 listReader.close();
              } catch (Exception ex) {
                  //Do nothing here.
              }
  
              if (errHandler.hasReachedErrorLimit()) {
                 System.out.println("The number of failed rows exceeds the configured maximum failed rows: "
                                    + config.maxerrors);
              }
              System.out.println("Read " + insertCount + " rows from file and successfully inserted "
                                 + ackCount + " rows (final)");
              errHandler.produceFiles(ackCount, insertCount);
              close_cleanup();
              //In test junit mode we let it continue for reuse
              if (!CSVLoader.testMode) {
                  System.exit(errHandler.m_errorInfo.isEmpty() ? 0 : -1);
              }
          } catch (Exception ex) {
              System.err.println("Exception Happened while loading CSV data: " + ex);
              System.exit(1);
          }
      }