netatalk  4.6.0
Free and Open Source Apple Filing Protocol (AFP) Server
Loading...
Searching...
No Matches
lantest.c File Reference
#include <errno.h>
#include <getopt.h>
#include <inttypes.h>
#include <limits.h>
#include <math.h>
#include <pthread.h>
#include <pwd.h>
#include <stdarg.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <sys/types.h>
#include <time.h>
#include <unistd.h>
#include "afpclient.h"
#include "afptest_uam.h"
#include "afpcmd.h"
#include "afphelper.h"
#include "testhelper.h"

Data Structures

struct  async_io_req

Macros

#define MEASURE_TIME_MS   0
#define MEASURE_AFPD_READ_IO   1
#define MEASURE_AFPD_WRITE_IO   2
#define MEASURE_CNID_READ_IO   3
#define MEASURE_CNID_WRITE_IO   4
#define NUM_MEASUREMENTS   5
#define FPWRITE_RPLY_SIZE   24
#define TEST_WRITE100MB   0
#define TEST_READ100MB   1
#define TEST_CREATE2000FILES   2
#define TEST_DIRTREE   3
#define TEST_WRITE2000FILES   4
#define TEST_READ2000FILES   5
#define TEST_COPY1000FILES   6
#define TEST_SERVERCOPY2000FILES   7
#define TEST_STAT2000FILES   8
#define TEST_ENUM2000FILES   9
#define TEST_FORK2000LOCKS   10
#define TEST_DELETE2000FILES   11
#define TEST_BYTELOCKS   12
#define TEST_CACHE_HITS   13
#define TEST_MIXED_CACHE_OPS   14
#define TEST_DEEP_TRAVERSAL   15
#define TEST_CACHE_VALIDATION   16
#define LASTTEST   TEST_CACHE_VALIDATION
#define NUMTESTS   (LASTTEST+1)
#define TOTAL_AFP_OPS   49326
#define ERROR_MEMORY_ALLOCATION   2
#define ERROR_FILE_DIRECTORY_OPS   3
#define ERROR_FORK_OPERATIONS   4
#define ERROR_NETWORK_PROTOCOL   5
#define ERROR_THREAD_OPERATIONS   6
#define ERROR_VALIDATION_TEST   7
#define ERROR_CONFIGURATION   8
#define ERROR_VOLUME_OPERATIONS   9
#define ERROR_LOGIN   10
#define DIRNUM_I   20
#define DIRNUM_J   9
#define DIRNUM_K   10
#define TEST_NAME_DISPLAY_WIDTH   66

Functions

void clean_exit (int exit_code)
static int cleanup_test_directory (CONN *conn, uint16_t volume, char *dirname)
 Clean up a test directory (main entry point).
int32_t is_there (CONN *conn, uint16_t volume, int32_t did, char *name)
int delete_directory_tree (CONN *conn, uint16_t volume, uint32_t parent_did, char *dirname)
 depth-first recursively delete a directory tree by parent DID and name
static void starttimer (void)
static void stoptimer (void)
static uint64_t timediff (void)
static void format_padded_test_name (char *dest, const char *src, size_t width)
static void addresult (int32_t test, uint8_t iteration)
static int32_t should_skip_measurement (int32_t measure_type)
static void results_calc_stats (uint64_t averages[NUMTESTS][NUM_MEASUREMENTS], double std_devs[NUMTESTS][NUM_MEASUREMENTS], char tests_enabled[NUMTESTS])
static void results_print_headers (bool is_csv)
static int cmp_uint64 (const void *a, const void *b)
static void results_time_spread (int32_t test, uint64_t *min_ms, uint64_t *max_ms, uint64_t *median_ms)
static void results_print_row (int32_t test, bool is_csv, uint64_t averages[NUMTESTS][NUM_MEASUREMENTS], double std_devs[NUMTESTS][NUM_MEASUREMENTS])
static void result_print_summary (uint64_t averages[NUMTESTS][NUM_MEASUREMENTS], bool is_csv, char tests_enabled[NUMTESTS])
static void displayresults (void)
static int32_t safe_atoi (const char *str, const char *param_name, int32_t min_val, int32_t max_val)
static void * rply_thread (void *p)
void run_test (const int32_t dir)
void usage (char *av0)
int main (int32_t ac, char **av)

Variables

bool Debug = false
bool lantest_Quiet = false
CONNConn
int ExitCode = 0
int Version = 34
int Mac = 0
int EmptyVol = 0
char Data [300000] = ""
char * Vol = ""
char * User = ""
char * Path
char * Test = NULL
static uint16_t vol
static DSIdsi
char * Server = "localhost"
static int32_t Port = DSI_AFPOVERTCP_PORT
static char * Password = ""
static uint8_t Iterations = 2
static uint8_t Iterations_save
static uint8_t iteration_counter = 0
static struct timeval tv_start
static struct timeval tv_end
static struct timeval tv_dif
static pthread_t tid
static bool active_thread = false
CONNConn2
uint16_t VolID
int PassCount = 0
int FailCount = 0
int SkipCount = 0
int NotTestedCount = 0
char FailedTests [1024][256] = {{0}}
char NotTestedTests [1024][256] = {{0}}
char SkippedTests [1024][256] = {{0}}
static off_t rwsize = 100 * 1024 * 1024
static int32_t num_locks = 2000
static int32_t create_enum_files = 2000
static int32_t copy_files = 1000
static int32_t num_fork_locks
static int32_t cache_dirs
static int32_t cache_files_per_dir = 100
static int32_t mixed_cache_files = 500
static int32_t deep_dir_levels = 20
static int32_t deep_traversals = 100
static int32_t validation_files = 500
static uint64_t numrw
static char teststorun [NUMTESTS]
static uint64_t(* results )[][NUMTESTS][NUM_MEASUREMENTS]
static char * bigfilename
static bool csv_output = false
static const char * test_names [NUMTESTS]

Macro Definition Documentation

◆ DIRNUM_I

#define DIRNUM_I   20

◆ DIRNUM_J

#define DIRNUM_J   9

◆ DIRNUM_K

#define DIRNUM_K   10

◆ ERROR_CONFIGURATION

#define ERROR_CONFIGURATION   8

◆ ERROR_FILE_DIRECTORY_OPS

#define ERROR_FILE_DIRECTORY_OPS   3

◆ ERROR_FORK_OPERATIONS

#define ERROR_FORK_OPERATIONS   4

◆ ERROR_LOGIN

#define ERROR_LOGIN   10

◆ ERROR_MEMORY_ALLOCATION

#define ERROR_MEMORY_ALLOCATION   2

◆ ERROR_NETWORK_PROTOCOL

#define ERROR_NETWORK_PROTOCOL   5

◆ ERROR_THREAD_OPERATIONS

#define ERROR_THREAD_OPERATIONS   6

◆ ERROR_VALIDATION_TEST

#define ERROR_VALIDATION_TEST   7

◆ ERROR_VOLUME_OPERATIONS

#define ERROR_VOLUME_OPERATIONS   9

◆ FPWRITE_RPLY_SIZE

#define FPWRITE_RPLY_SIZE   24

◆ LASTTEST

#define LASTTEST   TEST_CACHE_VALIDATION

◆ MEASURE_AFPD_READ_IO

#define MEASURE_AFPD_READ_IO   1

◆ MEASURE_AFPD_WRITE_IO

#define MEASURE_AFPD_WRITE_IO   2

◆ MEASURE_CNID_READ_IO

#define MEASURE_CNID_READ_IO   3

◆ MEASURE_CNID_WRITE_IO

#define MEASURE_CNID_WRITE_IO   4

◆ MEASURE_TIME_MS

#define MEASURE_TIME_MS   0

◆ NUM_MEASUREMENTS

#define NUM_MEASUREMENTS   5

◆ NUMTESTS

#define NUMTESTS   (LASTTEST+1)

◆ TEST_BYTELOCKS

#define TEST_BYTELOCKS   12

◆ TEST_CACHE_HITS

#define TEST_CACHE_HITS   13

◆ TEST_CACHE_VALIDATION

#define TEST_CACHE_VALIDATION   16

◆ TEST_COPY1000FILES

#define TEST_COPY1000FILES   6

◆ TEST_CREATE2000FILES

#define TEST_CREATE2000FILES   2

◆ TEST_DEEP_TRAVERSAL

#define TEST_DEEP_TRAVERSAL   15

◆ TEST_DELETE2000FILES

#define TEST_DELETE2000FILES   11

◆ TEST_DIRTREE

#define TEST_DIRTREE   3

◆ TEST_ENUM2000FILES

#define TEST_ENUM2000FILES   9

◆ TEST_FORK2000LOCKS

#define TEST_FORK2000LOCKS   10

◆ TEST_MIXED_CACHE_OPS

#define TEST_MIXED_CACHE_OPS   14

◆ TEST_NAME_DISPLAY_WIDTH

#define TEST_NAME_DISPLAY_WIDTH   66

Display width for test names in progress output

◆ TEST_READ100MB

#define TEST_READ100MB   1

◆ TEST_READ2000FILES

#define TEST_READ2000FILES   5

◆ TEST_SERVERCOPY2000FILES

#define TEST_SERVERCOPY2000FILES   7

◆ TEST_STAT2000FILES

#define TEST_STAT2000FILES   8

◆ TEST_WRITE100MB

#define TEST_WRITE100MB   0

◆ TEST_WRITE2000FILES

#define TEST_WRITE2000FILES   4

◆ TOTAL_AFP_OPS

#define TOTAL_AFP_OPS   49326

Function Documentation

◆ addresult()

void addresult ( int32_t test,
uint8_t iteration )
static

◆ clean_exit()

void clean_exit ( int exit_code)

◆ cleanup_test_directory()

int cleanup_test_directory ( CONN * conn,
uint16_t volume,
char * dirname )
static

Clean up a test directory (main entry point).

Parameters
connAFP connection
volumeVolume ID
dirnameDirectory name to delete
Returns
0 on success, -1 on failure

◆ cmp_uint64()

int cmp_uint64 ( const void * a,
const void * b )
static

qsort comparator for uint64_t

◆ delete_directory_tree()

int delete_directory_tree ( CONN * conn,
uint16_t volume,
uint32_t parent_did,
char * dirname )
extern

depth-first recursively delete a directory tree by parent DID and name

Resolves the starting directory once, then deletes descendants by DID so cleanup does not depend on round-tripping mangled long names from enumerate.

Parameters
connAFP connection
volumeVolume ID
parent_didParent directory ID
dirnameDirectory name to delete
Returns
0 on success, -1 on failure

◆ displayresults()

void displayresults ( void )
static

◆ format_padded_test_name()

void format_padded_test_name ( char * dest,
const char * src,
size_t width )
static

Helper function to format test name with fixed-width padding

◆ is_there()

int32_t is_there ( CONN * conn,
uint16_t volume,
int32_t did,
char * name )

◆ main()

int main ( int32_t ac,
char ** av )

◆ result_print_summary()

void result_print_summary ( uint64_t averages[NUMTESTS][NUM_MEASUREMENTS],
bool is_csv,
char tests_enabled[NUMTESTS] )
static

◆ results_calc_stats()

void results_calc_stats ( uint64_t averages[NUMTESTS][NUM_MEASUREMENTS],
double std_devs[NUMTESTS][NUM_MEASUREMENTS],
char tests_enabled[NUMTESTS] )
static

Helper function to calculate statistics for all tests

◆ results_print_headers()

void results_print_headers ( bool is_csv)
static

Helper function to print headers

◆ results_print_row()

void results_print_row ( int32_t test,
bool is_csv,
uint64_t averages[NUMTESTS][NUM_MEASUREMENTS],
double std_devs[NUMTESTS][NUM_MEASUREMENTS] )
static

Helper function to print data row

◆ results_time_spread()

void results_time_spread ( int32_t test,
uint64_t * min_ms,
uint64_t * max_ms,
uint64_t * median_ms )
static

Compute min, max and median of a test's per-iteration MEASURE_TIME_MS samples (>0 values only). Outputs 0 when no valid samples exist.

◆ rply_thread()

void * rply_thread ( void * p)
static

◆ run_test()

void run_test ( const int32_t dir)

◆ safe_atoi()

int32_t safe_atoi ( const char * str,
const char * param_name,
int32_t min_val,
int32_t max_val )
static

Safe integer conversion with validation

◆ should_skip_measurement()

int32_t should_skip_measurement ( int32_t measure_type)
inlinestatic

Helper function to check if measurement should be skipped

◆ starttimer()

void starttimer ( void )
static

◆ stoptimer()

void stoptimer ( void )
static

◆ timediff()

uint64_t timediff ( void )
static

◆ usage()

void usage ( char * av0)

Variable Documentation

◆ active_thread

bool active_thread = false
static

◆ bigfilename

char* bigfilename
static

◆ cache_dirs

int32_t cache_dirs
static
Initial value:
=
20

◆ cache_files_per_dir

int32_t cache_files_per_dir = 100
static

◆ Conn

CONN* Conn

◆ Conn2

CONN* Conn2

◆ copy_files

int32_t copy_files = 1000
static

◆ create_enum_files

int32_t create_enum_files = 2000
static

◆ csv_output

bool csv_output = false
static

Result display controls false = tabular (default), true = CSV

◆ Data

char Data[300000] = ""

◆ Debug

bool Debug = false

Global Debug flag

Global Debug flag - controlled by -b option in lantest.c

◆ deep_dir_levels

int32_t deep_dir_levels = 20
static

◆ deep_traversals

int32_t deep_traversals = 100
static

◆ dsi

DSI* dsi
static

◆ EmptyVol

int EmptyVol = 0

◆ ExitCode

int ExitCode = 0

◆ FailCount

int FailCount = 0

◆ FailedTests

char FailedTests[1024][256] = {{0}}

◆ iteration_counter

uint8_t iteration_counter = 0
static

◆ Iterations

uint8_t Iterations = 2
static

◆ Iterations_save

uint8_t Iterations_save
static

◆ lantest_Quiet

bool lantest_Quiet = false

Global Quiet flag override for lantest (stdout output enabled)

◆ Mac

int Mac = 0

◆ mixed_cache_files

int32_t mixed_cache_files = 500
static

◆ NotTestedCount

int NotTestedCount = 0

◆ NotTestedTests

char NotTestedTests[1024][256] = {{0}}

◆ num_fork_locks

int32_t num_fork_locks
static
Initial value:
=
2000

◆ num_locks

int32_t num_locks = 2000
static

◆ numrw

uint64_t numrw
static

◆ PassCount

int PassCount = 0

◆ Password

char* Password = ""
static

◆ Path

char* Path

◆ Port

int32_t Port = DSI_AFPOVERTCP_PORT
static

◆ results

uint64_t(* results)[][NUMTESTS][NUM_MEASUREMENTS]
static

◆ rwsize

off_t rwsize = 100 * 1024 * 1024
static

◆ Server

char* Server = "localhost"

◆ SkipCount

int SkipCount = 0

◆ SkippedTests

char SkippedTests[1024][256] = {{0}}

◆ Test

char* Test = NULL

◆ test_names

const char* test_names[NUMTESTS]
static
Initial value:
= {
"Writing one large file [103 AFP ops]",
"Reading one large file [102 AFP ops]",
"Creating 2000 files [4,000 AFP ops]",
"Create 2000 dirs tree (20×9×10) [2,000 AFP ops]",
"Open, write 1024 bytes, close 2000 files [6,000 AFP ops]",
"Open, read 1024 bytes, close 2000 files [6,000 AFP ops]",
"Copying 1000 files client-side (R+W) [7,000 AFP ops]",
"Copying 2000 files server-side [2,000 AFP ops]",
"Stat (lookup+getparams) 2000 files [4,000 AFP ops]",
"Enumerate dir with 2000 files [~51 AFP ops]",
"Lock then unlock 2000 open forks [4,000 AFP ops]",
"Deleting 2000 files [2,000 AFP ops]",
"Byte-range lock/unlock 2000 ranges in one fork [4,000 AFP ops]",
"Directory cache hits (20 dirs x 100 files) [2,020 AFP ops]",
"Mixed cache operations (create/stat/enum/delete) on 500 files [2,050 AFP ops]",
"Deep path traversal (20 levels x 100 walks) [2,000 AFP ops]",
"Cache validation (500 files x 4 lookups) [2,000 AFP ops]"
}

Descriptive test names for output formatting with AFP operation counts

◆ teststorun

char teststorun[NUMTESTS]
static

◆ tid

pthread_t tid
static

◆ tv_dif

struct timeval tv_dif
static

◆ tv_end

struct timeval tv_end
static

◆ tv_start

struct timeval tv_start
static

◆ User

char* User = ""

◆ validation_files

int32_t validation_files = 500
static

◆ Version

int Version = 34

◆ Vol

char* Vol = ""

◆ vol

uint16_t vol
static

◆ VolID

uint16_t VolID