1 Star 5 Fork 1

osdba/filecache

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
文件
克隆/下载
filecache.c 8.01 KB
一键复制 编辑 原始数据 按行查看 历史
osdba 提交于 2023-02-19 20:53 +08:00 . first commit
/* cache file use mmap */
/* TangCheng 2011.07 */
/* chengdata@gmail.com */
//gcc -g -m64 filecache.c -o filecache
//in solaris : usermod -K defaultpriv=basic,priv_proc_lock_memory postgres
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <limits.h>
#include <sys/mman.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <signal.h>
#include <errno.h>
//-D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE
int usage();
void sigint_handler(int sig);
int g_bExit=0;
int g_cache_percent=100;
off_t g_max_file_size = -1;
char g_pid_file[PATH_MAX];
off_t GetFileSize(int fd);
void GetSysErrorInfo(int err_no, char * szErrInfo);
char * trim(char * s);
off_t GetArgValue(char * szValue);
typedef struct _MAPFILEINFO
{
char * filename;
void * pa;
size_t length;
struct _MAPFILEINFO * next;
} MAPFILEINFO;
MAPFILEINFO * LoadConfig(char *filename);
int CacheFile(MAPFILEINFO * fihdr);
int CloseCache(MAPFILEINFO * fihdr);
int main(int argc, char * argv[])
{
int ret;
char cfgfile[PATH_MAX];
int ch;
char errinfo[512];
char buff[1024];
MAPFILEINFO * fihdr = NULL;
MAPFILEINFO * fi;
strcpy(g_pid_file, "filecache.pid");
cfgfile[0] = '\0';
opterr=0;
while((ch = getopt(argc,argv,"hf:p:c:M:"))!= -1)
{
switch(ch)
{
case 'h':
usage(argv[0]);
return 0;
case 'f':
strcpy(cfgfile, optarg);
break;
case 'c':
g_cache_percent=atoi(optarg);
break;
case 'p':
strcpy(g_pid_file,optarg);
break;
case 'M':
g_max_file_size = GetArgValue(optarg);
if (g_max_file_size < 0)
{
printf("Invalid parameter '-M %s' !!!\n", optarg);
usage(argv[0]);
return 1;
}
break;
default:
usage(argv[0]);
return 1;
}
}
if(cfgfile[0] == 0)
{
usage(argv[0]);
return 1;
}
FILE * fp = fopen(g_pid_file, "w");
fprintf(fp, "%d", getpid());
fclose(fp);
fihdr = LoadConfig(cfgfile);
if (fihdr == NULL)
{
unlink(g_pid_file);
return -1;
}
CacheFile(fihdr);
signal(SIGINT, sigint_handler);
signal(SIGUSR1, sigint_handler);
signal(SIGTERM, sigint_handler);
while(!g_bExit)
{
sleep(1);
}
CloseCache(fihdr);
unlink(g_pid_file);
return 0;
}
int usage(char * prog)
{
printf("usage:\n");
printf(" %s -f <cfgfile> [-c <value> ] [-M <value>]\n",prog);
printf(" -c <value> : value%% of file to cache, default is 100%%\n");
printf(" -M <value> : ignore files large than <value>, default no limit\n");
printf("example:\n");
printf(" %s -f my.conf -c 110 -M 100M\n", prog);
return 0;
}
void sigint_handler(int sig)
{
char szSigName[64];
if(sig==SIGINT)
{
strcpy(szSigName,"SIGINT");
g_bExit = 1;
}
else if(sig==SIGTERM)
{
strcpy(szSigName,"SIGTERM");
g_bExit = 1;
}
printf("Receive signal %s,will exit.\n", szSigName);
}
off_t GetFileSize(int fd)
{
struct stat fs;
int ret;
ret = fstat(fd, &fs);
if (ret == -1)
{
perror("can not get file size");
return (off_t)-1;
}
return fs.st_size;
}
void GetSysErrorInfo(int err_no, char * szErrInfo)
{
char * errmsg;
int headlen;
headlen=sprintf(szErrInfo,"errno=%d, ",err_no);
strerror_r(err_no,&szErrInfo[headlen],512);
}
char * trim(char * s)
{
int i=0;
int start;
int iLen=strlen(s);
if (s==NULL)
{
return NULL;
}
for(i=0;i<iLen;i++)
{
if(s[i]!=' ' && s[i]!='\t' && s[i]!='\r' && s[i]!='\n')
{
break;
}
}
start=i;
i=iLen-1;
while((s[i]==' ' || s[i]=='\t' || s[i]=='\r' || s[i]=='\n')
&& i>=0 && i>=start)
{
s[i]=0;
i--;
}
return &s[start];
}
MAPFILEINFO * LoadConfig(char *filename)
{
char buff[1024];
MAPFILEINFO * fihdr = NULL;
MAPFILEINFO * fi;
MAPFILEINFO * currnode = NULL;
FILE * fp;
char errinfo[512];
int linenum;
int filenamelen;
char * line;
fp=fopen(filename,"r");
if(fp==NULL)
{
GetSysErrorInfo(errno, errinfo);
printf("Can not open config file %s: %s",filename,errinfo);
return NULL;
}
linenum=1;
while((line=fgets(buff,1023,fp))!=NULL)
{
line = trim(line);
filenamelen = strlen(line);
if (filenamelen<=0)
{
continue;
}
fi = (MAPFILEINFO *)malloc(sizeof(MAPFILEINFO));
fi->filename = (char * )malloc(filenamelen+1);
strcpy(fi->filename, line);
fi->next = NULL;
if (fihdr == NULL)
{
fihdr = fi;
}
else
{
currnode->next=fi;
}
currnode = fi;
}
fclose(fp);
return fihdr;
}
int CacheFile(MAPFILEINFO * fihdr)
{
MAPFILEINFO * fi = fihdr;
int fd;
off_t filesize;
char errinfo[256];
int ret;
int errid;
off_t total_memory=0;
while (fi != NULL)
{
errinfo[0] = '\0';
fi->pa = NULL;
fi->length = 0;
fd = open(fi->filename, O_RDWR);
if (fd == -1)
{
strcpy(errinfo, "open failed");
goto nextfile;
}
filesize = GetFileSize(fd);
if(filesize == -1)
{
strcpy(errinfo, "get file size failed");
close(fd);
goto nextfile;
}
if(g_max_file_size > 0 && filesize > g_max_file_size )
{
sprintf(errinfo, "too large(%lld),Ignore!!!", (long long )filesize);
close(fd);
goto nextfile;
}
fi->length = filesize * g_cache_percent/100;
if (fi->length == 0)
{
fi->length = 4096;
}
//printf("file=%s, memsize=%lld\n", fi->filename, (long long )length);
#ifdef MAP_LOCKED
fi->pa = mmap(NULL, fi->length, PROT_READ|PROT_WRITE, MAP_SHARED|MAP_NORESERVE|MAP_LOCKED, fd, 0);
#else
fi->pa = mmap(NULL, fi->length, PROT_READ|PROT_WRITE, MAP_SHARED|MAP_NORESERVE, fd, 0);
#endif
if( fi->pa==MAP_FAILED)
{
fi->pa = NULL;
GetSysErrorInfo(errno, errinfo);
printf("mmap error: %s\n", errinfo);
strcpy(errinfo, "mmap failed");
close(fd);
goto nextfile;
}
ret = mlock(fi->pa, fi->length);
if(ret == -1)
{
GetSysErrorInfo(errno, errinfo);
printf("mlock error: %s\n", errinfo);
strcpy(errinfo, "mlock failed");
munmap(fi->pa, fi->length);
close(fd);
fi->pa = NULL;
goto nextfile;
}
close(fd);
strcpy(errinfo,"OK");
nextfile:
total_memory += fi->length;
printf("%-50s %20lld %-21s\n", fi->filename, (long long)fi->length, errinfo);
fi = fi->next;
}
printf("total memory: %lldK, %lldM\n", (long long)total_memory/1024, (long long)total_memory/1024/1024);
return 0;
}
int CloseCache(MAPFILEINFO * fihdr)
{
MAPFILEINFO * fi = fihdr;
MAPFILEINFO * nextfi = NULL;
while (fi != NULL)
{
if(fi->pa != NULL)
{
munlock(fi->pa, fi->length);
munmap(fi->pa, fi->length);
}
free(fi->filename);
nextfi = fi->next;
free(fi);
fi = nextfi;
}
return 0;
}
off_t GetArgValue(char * szValue)
{
int iLen=strlen(szValue);
off_t lValue;
int i;
lValue=0;
for(i=0;i<iLen-1;i++)
{
if(szValue[i]<'0' || szValue[i]>'9')
{
return -1;
}
lValue=lValue*10+szValue[i] - '0';
}
if(szValue[i]>='0' && szValue[i]<='9')
{
lValue=lValue*10+ szValue[i] - '0';
}
else if(szValue[i]=='k' || szValue[i]=='K')
{
lValue=lValue*1024;
}
else if(szValue[i]=='m' || szValue[i]=='M')
{
lValue=lValue*1024*1024;
}
else if(szValue[i]=='g' || szValue[i]=='G')
{
lValue=lValue*1024*1024*1024;
}
else
{
return -1;
}
return lValue;
}
Loading...
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
C
1
https://gitee.com/osdba/filecache.git
git@gitee.com:osdba/filecache.git
osdba
filecache
filecache
master

搜索帮助