//压力测试工具,分多进程和多线程两种场景
#include <errno.h>
#include <pthread.h>
#include <signal.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include "fdfs_client.h"
#include "fdfs_global.h"
#include "fdfs_base64.h"
#include "logger.h"
void
TestUsage ( int iIsThread,char *argv[] )
{
if(iIsThread)
{
printf ( "Usage: %s -t ThreadCount -c SendCountPerThread /n", argv[0] );
printf("<conf operation>/n" /
"/toperation: upload, download, getmeta, setmeta, " /
"delete and query_servers/n", argv[0]);
printf ( "e.g.: %s -t 30 -c 100 ../conf/client.conf upload file/n", argv[0] );
}
else
{
printf ( "Usage: %s -t ProcessCount -c SendCountPerProcess/n", argv[0] );
printf("<conf operation>/n" /
"/toperation: upload, download, getmeta, setmeta, " /
"delete and query_servers/n", argv[0]);
printf ( "e.g.: %s -t 30 -c 100 ../conf/client.conf upload file/n", argv[0] );
}
}
static int nSum = 0,nTradeOK=0,nTradeFailed=0;
static int OverThread = 0;
int nThreadCount=1,nReqCount=1,nTimeAllUsed=0;
static pthread_mutex_t theSumMutex = PTHREAD_MUTEX_INITIALIZER;
static pthread_mutex_t theConnMutex = PTHREAD_MUTEX_INITIALIZER;
char server[16]={0};
int port;
char operation[64]={0};
char conf_filename[64]={0};
char local_filename[64]={0};
//typedef void * (*ThreadFunction)(void *pParam);
int CreateThread(void *(* pFunction)(void *), void *pParam)
{
int nReturn = 0;
pthread_t tid;
if(pthread_create(&tid, NULL, pFunction, pParam) != 0)
{
return(0);
}
pthread_detach(tid);
nReturn = (int)tid;
if( nReturn <-1 )
{
return 1024;
}
else
{
return(nReturn);
}
}
// befor you definition you would be user ,mast have state.
void StartApp ( );
int main ( int argc, char **argv )
{
int n;
if (argc <= 6)
{
TestUsage(1,argv);
exit(1);
}
if (strchr(argv[1], '-') == NULL)
{
TestUsage(1,argv);
exit(1);
}
for ( n = 1; n < argc; ++n )
{
// read garam from command,for create number of thread
if ( strcmp ( argv[n], "-t" ) == 0 )
{
n++;
nThreadCount=atoi ( argv[n] );
}
// read garam from command, for total every thread has how mutch request
else if ( strcmp ( argv[n], "-c" ) == 0 )
{
n++;
nReqCount =atoi ( argv[n] );
}
}
strncpy(conf_filename,argv[5],64);
strncpy(operation,argv[6],64);
strncpy(local_filename,argv[7],64);
printf(" INFO: multithreading test about to FastDFS starting..../n");
printf(" INFO: conf_filename=%s,operation=%s,local_filename=%s/n",/
conf_filename,operation,local_filename);
//start the spp
StartApp ( );
printf(" INFO: you operate is all over ,you can checke the result! /n");
return ( 0 );
}
// thread to call this funcation
void * MultiThreadTest( void *pParam )
{
int MessageSum = 0;
memcpy( &MessageSum, pParam, 4);
int nStartTime = time(NULL);
int nReqStartTime = 0, nReqEndTime = 0, nTimeout = 0;
TrackerServerInfo theTrackerServer;
memset( &theTrackerServer, 0, sizeof(theTrackerServer) );
TrackerServerInfo *pTrackerServer = &theTrackerServer;
int result = 0;
TrackerServerInfo storageServer;
char group_name[FDFS_GROUP_NAME_MAX_LEN + 1];
char remote_filename[256];
char buff[32];
char token[32 + 1];
char file_id[128];
char file_url[256];
int len = 0;
int url_len = 0;
time_t ts;
char *file_buff;
int64_t file_size;
char *meta_buff;
int store_path_index = 0;
struct base64_context context;
nReqStartTime=time(NULL);
//为了最后解析出文件大小需要初始化这个变量
base64_init_ex(&context, 0, '-', '_', '.');
printf( "DEBUG :base64_init_ex ok/n");
int i=0;//发送数目
//处理在线请求时可以改成while(Running)
while(i<MessageSum)
{
//多线程安全函数
tracker_get_connection_r(pTrackerServer);
if ( pTrackerServer->sock <= 0 )
{
sleep(1);
continue;
}
printf("DEBUG :get tracker conn ok, i = %d/n", i);
store_path_index = 0;
if ((result=tracker_query_storage_store(pTrackerServer, /
&storageServer, &store_path_index )) != 0)
{
//查询tracker获取storage失败,重连tracker
printf("ERROR :tracker_query_storage fail, " /
"error no: %d, error info: %s, i = %d/n", /
result, strerror(result), i);
fdfs_quit(pTrackerServer);
tracker_disconnect_server(pTrackerServer);
sleep(1);
continue;
}
printf("DEBUG :tracker_query_storage_store ok/n");
//if(storageServer.group_name.sizeof())
/*if( sizeof(storageServer.group_name) )
{
printf("INFO : infomation get faile !");
continue;
}*/
printf("group_name=%s, ip_addr=%s, port=%d/n", /
storageServer.group_name, /
storageServer.ip_addr, /
storageServer.port);
if ((result=tracker_connect_server(&storageServer)) != 0)
{
//tracker给了一个连不上的storage,重连tracker
printf("DEBUG :conn storage failed and continue/n");
fdfs_quit(pTrackerServer);
tracker_disconnect_server(pTrackerServer);
sleep(1);
continue;
}
printf("DEBUG :conn storage ok/n");
//1下面保持tracker和storage的各1个长连接,本线程固定跟一个storage交互,出错后才返回重连进行容灾
//2实际中如果是大文件没必要保持长连接,则下面这个for循环去掉成顺序执行,出错时continue回while循环去重连tracker和storage
for(;i<MessageSum;i++)
{
//以上传为例,上传目前有3类,根据应用自己选一类即可,参见版本自带的fdfs_test.c
//if (strcmp(operation, "upload") == 0)
{
printf("DEBUG :to upload a file, i = %d/n", i);
strcpy(group_name, "");
result = storage_upload_by_filename(pTrackerServer, /
&storageServer, store_path_index, /
local_filename, NULL, /
NULL, 0, /
group_name, remote_filename);
//下面的出错或成功处理,跟上述上传种类无关,通用的
if (result != 0)
{
printf("INFO :storage_upload_by_filename fail, " /
"error no: %d, error info: %s/n", /
result, strerror(result));
fdfs_quit(&storageServer);
tracker_disconnect_server(&storageServer);
fdfs_quit(pTrackerServer);
tracker_disconnect_server(pTrackerServer);
//上传次数的统计,测试用
pthread_mutex_lock(&theSumMutex);
nTradeFailed ++;
nSum++;
pthread_mutex_unlock(&theSumMutex);
break;
}
sprintf(file_id, "%s/%s", group_name, remote_filename);
url_len = sprintf(file_url, "http://%s:%d/%s", /
pTrackerServer->ip_addr, /
g_tracker_server_http_port, file_id);
/*
if (g_anti_steal_token)
{
ts = time(NULL);
fdfs_http_gen_token(&g_anti_steal_secret_key, file_id, /
ts, token);
sprintf(file_url + url_len, "?token=%s&ts=%d", /
token, (int)ts);
}*/
printf("DEBUG :upload a file ok, i = %d/n", i);
memset(buff, 0, sizeof(buff));
base64_decode_auto(&context, remote_filename + FDFS_FILE_PATH_LEN, /
strlen(remote_filename) - FDFS_FILE_PATH_LEN /
- (FDFS_FILE_EXT_NAME_MAX_LEN + 1), buff, &len);
printf("INFO :group_name=%s, remote_filename=%s/n", /
group_name, remote_filename);
printf("INFO :file timestamp=%d/n", buff2int(buff+sizeof(int)));
printf("INFO :file size="INT64_PRINTF_FORMAT"/n", /
buff2long(buff+sizeof(int)*2));
printf("INFO :file url: %s/n", file_url);
pthread_mutex_lock(&theSumMutex);
nTradeOK ++;
nSum++;
pthread_mutex_unlock(&theSumMutex);
}
}
fdfs_quit(&storageServer);
tracker_disconnect_server(&storageServer);
fdfs_quit(pTrackerServer);
tracker_disconnect_server(pTrackerServer);
printf("quit storage ok/n");
}
int nEndTime=time(NULL);
pthread_mutex_lock(&theSumMutex);
OverThread ++;
nTimeAllUsed += (nEndTime - nStartTime);
pthread_mutex_unlock(&theSumMutex);
printf("quit thread ok/n");
return NULL;
}
void
StartApp ( )
{
int m;
char *sParam;
int result;
printf("IN StartApp/n");
log_init();
//init here
if ( (result = fdfs_client_init(conf_filename)) != 0)
{
return;
}
for ( m = 0; m < nThreadCount; m++ )
{
printf( "DEBUG :printf the thread number:(%d)/n", m );
CreateThread ( MultiThreadTest, (void*)&nReqCount );
}
printf( "INFO :wait all thread(%d) to exit/n", nThreadCount);
printf( "INFO :wait all thread(%d) to exit/n", OverThread);
while (OverThread < nThreadCount)
{
sleep(1);
}
int iTimeUsed= nTimeAllUsed/nThreadCount;
if( iTimeUsed==0 ) iTimeUsed = 1;
printf("-------------------operate is over------------------------------/n");
printf("send %d request ,OK[%d],failed[%d],TimeUsed=%d,speed=%d(r/s)/n",
nSum, nTradeOK, nTradeFailed, iTimeUsed, nSum/iTimeUsed );
tracker_close_all_connections();
fdfs_client_destroy();
return;
}
这是一个使用C语言实现的FastDFS多线程压力测试工具,用于模拟上传文件操作。程序通过命令行参数配置线程数、每个线程的请求次数,并支持连接池管理,以提高上传效率。
429

被折叠的 条评论
为什么被折叠?



