Blame tests/benchmarks/bench_sftp.c

Packit Service 31306d
/* bench_sftp.c
Packit Service 31306d
 *
Packit Service 31306d
 * This file is part of the SSH Library
Packit Service 31306d
 *
Packit Service 31306d
 * Copyright (c) 2011 by Aris Adamantiadis
Packit Service 31306d
 *
Packit Service 31306d
 * The SSH Library is free software; you can redistribute it and/or modify
Packit Service 31306d
 * it under the terms of the GNU Lesser General Public License as published by
Packit Service 31306d
 * the Free Software Foundation; either version 2.1 of the License, or (at your
Packit Service 31306d
 * option) any later version.
Packit Service 31306d
 *
Packit Service 31306d
 * The SSH Library is distributed in the hope that it will be useful, but
Packit Service 31306d
 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
Packit Service 31306d
 * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
Packit Service 31306d
 * License for more details.
Packit Service 31306d
 *
Packit Service 31306d
 * You should have received a copy of the GNU Lesser General Public License
Packit Service 31306d
 * along with the SSH Library; see the file COPYING.  If not, write to
Packit Service 31306d
 * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
Packit Service 31306d
 * MA 02111-1307, USA.
Packit Service 31306d
 */
Packit Service 31306d
Packit Service 31306d
#include "benchmarks.h"
Packit Service 31306d
#include <libssh/libssh.h>
Packit Service 31306d
#include <libssh/sftp.h>
Packit Service 31306d
#include <stdio.h>
Packit Service 31306d
#include <fcntl.h>
Packit Service 31306d
#include <stdlib.h>
Packit Service 31306d
Packit Service 31306d
#define SFTPDIR "/tmp/"
Packit Service 31306d
#define SFTPFILE "scpbenchmark"
Packit Service 31306d
Packit Service 31306d
/** @internal
Packit Service 31306d
 * @brief benchmarks a synchronous sftp upload using an
Packit Service 31306d
 * existing SSH session.
Packit Service 31306d
 * @param[in] session Open SSH session
Packit Service 31306d
 * @param[in] args Parsed command line arguments
Packit Service 31306d
 * @param[out] bps The calculated bytes per second obtained via benchmark.
Packit Service 31306d
 * @return 0 on success, -1 on error.
Packit Service 31306d
 */
Packit Service 31306d
int benchmarks_sync_sftp_up (ssh_session session, struct argument_s *args,
Packit Service 31306d
    float *bps){
Packit Service 31306d
  unsigned long bytes;
Packit Service 31306d
  struct timestamp_struct ts;
Packit Service 31306d
  float ms=0.0;
Packit Service 31306d
  unsigned long total=0;
Packit Service 31306d
  sftp_session sftp;
Packit Service 31306d
  sftp_file file = NULL;
Packit Service 31306d
Packit Service 31306d
  bytes = args->datasize * 1024 * 1024;
Packit Service 31306d
  sftp = sftp_new(session);
Packit Service 31306d
  if(sftp == NULL)
Packit Service 31306d
    goto error;
Packit Service 31306d
  if(sftp_init(sftp)==SSH_ERROR)
Packit Service 31306d
    goto error;
Packit Service 31306d
  file = sftp_open(sftp,SFTPDIR SFTPFILE,O_RDWR | O_CREAT | O_TRUNC, 0777);
Packit Service 31306d
  if(!file)
Packit Service 31306d
    goto error;
Packit Service 31306d
  if(args->verbose>0)
Packit Service 31306d
    fprintf(stdout,"Starting upload of %lu bytes now\n",bytes);
Packit Service 31306d
  timestamp_init(&ts);
Packit Service 31306d
  while(total < bytes){
Packit Service 31306d
    unsigned long towrite = bytes - total;
Packit Service 31306d
    int w;
Packit Service 31306d
    if(towrite > args->chunksize)
Packit Service 31306d
      towrite = args->chunksize;
Packit Service 31306d
    w=sftp_write(file,buffer,towrite);
Packit Service 31306d
    if(w == SSH_ERROR)
Packit Service 31306d
      goto error;
Packit Service 31306d
    total += w;
Packit Service 31306d
  }
Packit Service 31306d
  sftp_close(file);
Packit Service 31306d
  ms=elapsed_time(&ts);
Packit Service 31306d
  *bps=8000 * (float)bytes / ms;
Packit Service 31306d
  if(args->verbose > 0)
Packit Service 31306d
    fprintf(stdout,"Upload took %f ms for %lu bytes, at %f bps\n",ms,
Packit Service 31306d
        bytes,*bps);
Packit Service 31306d
  sftp_free(sftp);
Packit Service 31306d
  return 0;
Packit Service 31306d
error:
Packit Service 31306d
  fprintf(stderr,"Error during scp upload : %s\n",ssh_get_error(session));
Packit Service 31306d
  if(file)
Packit Service 31306d
    sftp_close(file);
Packit Service 31306d
  if(sftp)
Packit Service 31306d
    sftp_free(sftp);
Packit Service 31306d
  return -1;
Packit Service 31306d
}
Packit Service 31306d
Packit Service 31306d
/** @internal
Packit Service 31306d
 * @brief benchmarks a synchronous sftp download using an
Packit Service 31306d
 * existing SSH session.
Packit Service 31306d
 * @param[in] session Open SSH session
Packit Service 31306d
 * @param[in] args Parsed command line arguments
Packit Service 31306d
 * @param[out] bps The calculated bytes per second obtained via benchmark.
Packit Service 31306d
 * @return 0 on success, -1 on error.
Packit Service 31306d
 */
Packit Service 31306d
int benchmarks_sync_sftp_down (ssh_session session, struct argument_s *args,
Packit Service 31306d
    float *bps){
Packit Service 31306d
  unsigned long bytes;
Packit Service 31306d
  struct timestamp_struct ts;
Packit Service 31306d
  float ms=0.0;
Packit Service 31306d
  unsigned long total=0;
Packit Service 31306d
  sftp_session sftp;
Packit Service 31306d
  sftp_file file = NULL;
Packit Service 31306d
  int r;
Packit Service 31306d
Packit Service 31306d
  bytes = args->datasize * 1024 * 1024;
Packit Service 31306d
  sftp = sftp_new(session);
Packit Service 31306d
  if(sftp == NULL)
Packit Service 31306d
    goto error;
Packit Service 31306d
  if(sftp_init(sftp)==SSH_ERROR)
Packit Service 31306d
    goto error;
Packit Service 31306d
  file = sftp_open(sftp,SFTPDIR SFTPFILE,O_RDONLY,0);
Packit Service 31306d
  if(!file)
Packit Service 31306d
    goto error;
Packit Service 31306d
  if(args->verbose>0)
Packit Service 31306d
    fprintf(stdout,"Starting download of %lu bytes now\n",bytes);
Packit Service 31306d
  timestamp_init(&ts);
Packit Service 31306d
  while(total < bytes){
Packit Service 31306d
    unsigned long toread = bytes - total;
Packit Service 31306d
    if(toread > args->chunksize)
Packit Service 31306d
      toread = args->chunksize;
Packit Service 31306d
    r=sftp_read(file,buffer,toread);
Packit Service 31306d
    if(r == SSH_ERROR)
Packit Service 31306d
      goto error;
Packit Service 31306d
    total += r;
Packit Service 31306d
    /* we had a smaller file */
Packit Service 31306d
    if(r==0){
Packit Service 31306d
      fprintf(stdout,"File smaller than expected : %lu (expected %lu).\n",total,bytes);
Packit Service 31306d
      bytes = total;
Packit Service 31306d
      break;
Packit Service 31306d
    }
Packit Service 31306d
  }
Packit Service 31306d
  sftp_close(file);
Packit Service 31306d
  ms=elapsed_time(&ts);
Packit Service 31306d
  *bps=8000 * (float)bytes / ms;
Packit Service 31306d
  if(args->verbose > 0)
Packit Service 31306d
    fprintf(stdout,"download took %f ms for %lu bytes, at %f bps\n",ms,
Packit Service 31306d
        bytes,*bps);
Packit Service 31306d
  sftp_free(sftp);
Packit Service 31306d
  return 0;
Packit Service 31306d
error:
Packit Service 31306d
  fprintf(stderr,"Error during sftp download : %s\n",ssh_get_error(session));
Packit Service 31306d
  if(file)
Packit Service 31306d
    sftp_close(file);
Packit Service 31306d
  if(sftp)
Packit Service 31306d
    sftp_free(sftp);
Packit Service 31306d
  return -1;
Packit Service 31306d
}
Packit Service 31306d
Packit Service 31306d
/** @internal
Packit Service 31306d
 * @brief benchmarks an asynchronous sftp download using an
Packit Service 31306d
 * existing SSH session.
Packit Service 31306d
 * @param[in] session Open SSH session
Packit Service 31306d
 * @param[in] args Parsed command line arguments
Packit Service 31306d
 * @param[out] bps The calculated bytes per second obtained via benchmark.
Packit Service 31306d
 * @return 0 on success, -1 on error.
Packit Service 31306d
 */
Packit Service 31306d
int benchmarks_async_sftp_down (ssh_session session, struct argument_s *args,
Packit Service 31306d
    float *bps){
Packit Service 31306d
  unsigned long bytes;
Packit Service 31306d
  struct timestamp_struct ts;
Packit Service 31306d
  float ms=0.0;
Packit Service 31306d
  unsigned long total=0;
Packit Service 31306d
  sftp_session sftp;
Packit Service 31306d
  sftp_file file = NULL;
Packit Service 31306d
  int r,i;
Packit Service 31306d
  int warned = 0;
Packit Service 31306d
  unsigned long toread;
Packit Service 31306d
  int *ids=NULL;
Packit Service 31306d
  int concurrent_downloads = args->concurrent_requests;
Packit Service 31306d
Packit Service 31306d
  bytes = args->datasize * 1024 * 1024;
Packit Service 31306d
  sftp = sftp_new(session);
Packit Service 31306d
  if(sftp == NULL)
Packit Service 31306d
    goto error;
Packit Service 31306d
  if(sftp_init(sftp)==SSH_ERROR)
Packit Service 31306d
    goto error;
Packit Service 31306d
  file = sftp_open(sftp,SFTPDIR SFTPFILE,O_RDONLY,0);
Packit Service 31306d
  if(!file)
Packit Service 31306d
    goto error;
Packit Service 31306d
  ids = malloc(concurrent_downloads * sizeof(int));
Packit Service 31306d
  if(args->verbose>0)
Packit Service 31306d
    fprintf(stdout,"Starting download of %lu bytes now, using %d concurrent downloads\n",bytes,
Packit Service 31306d
        concurrent_downloads);
Packit Service 31306d
  timestamp_init(&ts);
Packit Service 31306d
  for (i=0;i
Packit Service 31306d
    ids[i]=sftp_async_read_begin(file, args->chunksize);
Packit Service 31306d
    if(ids[i]==SSH_ERROR)
Packit Service 31306d
        goto error;
Packit Service 31306d
  }
Packit Service 31306d
  i=0;
Packit Service 31306d
  while(total < bytes){
Packit Service 31306d
    r = sftp_async_read(file, buffer, args->chunksize, ids[i]);
Packit Service 31306d
    if(r == SSH_ERROR)
Packit Service 31306d
      goto error;
Packit Service 31306d
    total += r;
Packit Service 31306d
    if(r != (int)args->chunksize && total != bytes && !warned){
Packit Service 31306d
      fprintf(stderr,"async_sftp_download : receiving short reads (%d, requested %d) "
Packit Service 31306d
          "the received file will be corrupted and shorted. Adapt chunksize to %d\n",
Packit Service 31306d
          r, args->chunksize,r);
Packit Service 31306d
      warned = 1;
Packit Service 31306d
    }
Packit Service 31306d
    /* we had a smaller file */
Packit Service 31306d
    if(r==0){
Packit Service 31306d
      fprintf(stdout,"File smaller than expected : %lu (expected %lu).\n",total,bytes);
Packit Service 31306d
      bytes = total;
Packit Service 31306d
      break;
Packit Service 31306d
    }
Packit Service 31306d
    toread = bytes - total;
Packit Service 31306d
    if(toread < args->chunksize * concurrent_downloads){
Packit Service 31306d
      /* we've got enough launched downloads */
Packit Service 31306d
      ids[i]=-1;
Packit Service 31306d
    }
Packit Service 31306d
    if(toread > args->chunksize)
Packit Service 31306d
      toread = args->chunksize;
Packit Service 31306d
    ids[i]=sftp_async_read_begin(file,toread);
Packit Service 31306d
    if(ids[i] == SSH_ERROR)
Packit Service 31306d
      goto error;
Packit Service 31306d
    i = (i+1) % concurrent_downloads;
Packit Service 31306d
  }
Packit Service 31306d
  sftp_close(file);
Packit Service 31306d
  ms=elapsed_time(&ts);
Packit Service 31306d
  *bps=8000 * (float)bytes / ms;
Packit Service 31306d
  if(args->verbose > 0)
Packit Service 31306d
    fprintf(stdout,"download took %f ms for %lu bytes, at %f bps\n",ms,
Packit Service 31306d
        bytes,*bps);
Packit Service 31306d
  sftp_free(sftp);
Packit Service 31306d
  free(ids);
Packit Service 31306d
  return 0;
Packit Service 31306d
error:
Packit Service 31306d
  fprintf(stderr,"Error during sftp download : %s\n",ssh_get_error(session));
Packit Service 31306d
  if(file)
Packit Service 31306d
    sftp_close(file);
Packit Service 31306d
  if(sftp)
Packit Service 31306d
    sftp_free(sftp);
Packit Service 31306d
  free(ids);
Packit Service 31306d
  return -1;
Packit Service 31306d
}