netatalk 4.5.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 "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 | FPWRITE_RQST_SIZE 36
#define | TEST_OPENSTATREAD 0
#define | TEST_WRITE100MB 1
#define | TEST_READ100MB 2
#define | TEST_LOCKUNLOCK 3
#define | TEST_CREATE2000FILES 4
#define | TEST_ENUM2000FILES 5
#define | TEST_DELETE2000FILES 6
#define | TEST_DIRTREE 7
#define | TEST_CACHE_HITS 8
#define | TEST_MIXED_CACHE_OPS 9
#define | TEST_DEEP_TRAVERSAL 10
#define | TEST_CACHE_VALIDATION 11
#define | LASTTEST TEST_CACHE_VALIDATION
#define | NUMTESTS (LASTTEST+1)
#define | TOTAL_AFP_OPS 80686
#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 10 /* 1000 nested dirs */
#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 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
CONN * | Conn
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 DSI * | dsi
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
CONN * | Conn2
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 int32_t | smallfiles = 1000
static off_t | rwsize = 100 * 1024 * 1024
static int32_t | locking = 10000 / 40
static int32_t | create_enum_files = 2000
static int32_t | cache_dirs = 10
static int32_t | cache_files_per_dir = 10
static int32_t | cache_lookup_iterations = 100
static int32_t | mixed_cache_files = 200
static int32_t | deep_dir_levels = 20
static int32_t | deep_test_files = 50
static int32_t | deep_traversals = 50
static int32_t | validation_files = 100
static int32_t | validation_iterations = 100
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

#define DIRNUM 10 /* 1000 nested dirs */

## ◆ 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

## ◆ FPWRITE_RQST_SIZE

#define FPWRITE_RQST_SIZE 36

## ◆ 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_CACHE_HITS

#define TEST_CACHE_HITS 8

## ◆ TEST_CACHE_VALIDATION

#define TEST_CACHE_VALIDATION 11

## ◆ TEST_CREATE2000FILES

#define TEST_CREATE2000FILES 4

## ◆ TEST_DEEP_TRAVERSAL

#define TEST_DEEP_TRAVERSAL 10

## ◆ TEST_DELETE2000FILES

#define TEST_DELETE2000FILES 6

## ◆ TEST_DIRTREE

#define TEST_DIRTREE 7

## ◆ TEST_ENUM2000FILES

#define TEST_ENUM2000FILES 5

## ◆ TEST_LOCKUNLOCK

#define TEST_LOCKUNLOCK 3

## ◆ TEST_MIXED_CACHE_OPS

#define TEST_MIXED_CACHE_OPS 9

## ◆ TEST_NAME_DISPLAY_WIDTH

#define TEST_NAME_DISPLAY_WIDTH 66

Display width for test names in progress output

## ◆ TEST_OPENSTATREAD

#define TEST_OPENSTATREAD 0

## ◆ TEST_READ100MB

#define TEST_READ100MB 2

## ◆ TEST_WRITE100MB

#define TEST_WRITE100MB 1

## ◆ TOTAL_AFP_OPS

#define TOTAL_AFP_OPS 80686

## 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

  conn | AFP connection
  volume | Volume ID
  dirname | Directory name to delete

Returns
  0 on success, -1 on failure

## ◆ 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

  conn | AFP connection
  volume | Volume ID
  parent_did | Parent directory ID
  dirname | Directory 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

## ◆ 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 | ) |
| inline static

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 = 10
| static

## ◆ cache_files_per_dir

int32_t cache_files_per_dir = 10
| static

## ◆ cache_lookup_iterations

int32_t cache_lookup_iterations = 100
| static

## ◆ Conn

CONN* Conn

## ◆ Conn2

CONN* Conn2

## ◆ 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_test_files

int32_t deep_test_files = 50
| static

## ◆ deep_traversals

int32_t deep_traversals = 50
| 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)

## ◆ locking

int32_t locking = 10000 / 40
| static

## ◆ Mac

int Mac = 0

## ◆ mixed_cache_files

int32_t mixed_cache_files = 200
| static

## ◆ NotTestedCount

int NotTestedCount = 0

## ◆ NotTestedTests

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

## ◆ 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}}

## ◆ smallfiles

int32_t smallfiles = 1000
| static

## ◆ Test

char* Test = NULL

## ◆ test_names

const char* test_names[NUMTESTS]
| static

Initial value:
= {
"Open, stat and read 512 bytes from 1000 files [8,000 AFP ops]",
"Writing one large file [103 AFP ops]",
"Reading one large file [102 AFP ops]",
"Locking/Unlocking 10000 times each [20,000 AFP ops]",
"Creating dir with 2000 files [4,000 AFP ops]",
"Enumerate dir with 2000 files [~51 AFP ops]",
"Deleting dir with 2000 files [2,000 AFP ops]",
"Create directory tree with 1000 dirs [1,110 AFP ops]",
"Directory cache hits (100 dirs + 1000 files) [11,000 AFP ops]",
"Mixed cache operations (create/stat/enum/delete) [820 AFP ops]",
"Deep path traversal (nested directory navigation) [3,500 AFP ops]",
"Cache validation efficiency (metadata changes) [30,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 = 100
| static

## ◆ validation_iterations

int32_t validation_iterations = 100
| static

## ◆ Version

int Version = 34

## ◆ Vol

char* Vol = ""

## ◆ vol

uint16_t vol
| static

## ◆ VolID

uint16_t VolID