Seer Trace Collection: http://www.lasr.cs.ucla.edu/seer/seer_traces.html
----------------------------------------------------------------------------------------------------------------------------------------------------------
/*
* =====================================================================================
*
* Filename: seer_trace.c
* Description: traslating seer format traces to the format can be used in object oriented file system
* Version: 1.0
* Created: 07/05/2012 12:17:11 AM
* Revision: none
* Compiler: gcc
* Author: Si Ma
*
* =====================================================================================
*/
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
#include "list.h"
#define MAX_CHARS 10000 // max number of chars of one line
#define MAX_FILES 20000 //max number of files used at the same time in one trace
#define SYSCALL_NUM 7
#define SYSCALL_NUM_MAC 5
/**
* file_node
* @ oid: object id of this file, from the value of time33(pathname)
* @ cur_offset: current read/write offset
* fd will be the index of file_node array...
*/
struct file_node{
unsigned long oid;
unsigned long cur_offset;
};
struct file_node File_hstb[MAX_FILES];
struct user{
int usr_id;
char cur_path[1000];
struct list_head list;
};
/**
* system call list that we care about in the original trace file
*/
char *SYS_CALL[SYSCALL_NUM]={
"open\0", "chdir\0", "read\0", "write\0", "lstat\0", "stat\0", "close\0" //0--5
};
/**
* system call list that we care about in the original trace file
*/
char *SYS_CALL_MAC[SYSCALL_NUM_MAC]={
"oread\0",
"owrite\0",
"ogattr\0",
"osattr\0",
"oflush\0"
};
/**
* type list of the lines in the trace file
*/
char *LINE_TYPE[3]={
"UID\0", //we only need this type and the other two will be ignored
"TIMESTAMP\0",
"RESTART\0"
};
/**
* path2oid - mapping pathname to object id: time33 hashing
*/
unsigned long path2oid(char const *pathname, int len)
{
unsigned long hash = 0;
int i ;
for (i=0; i < len; i++) {
hash = ((hash <<5) + hash) + (unsigned long) pathname[i];
}
return hash;
}
/**
* type_of_op - check and return the specific index number according to SYS_CALL array
* @op: operation string abstracted from the line buffer
*/
int type_of_op(char *op)
{
int i=0;
for(i=0; i<SYSCALL_NUM;i++){
//printf("\nloop for the %d time", i+1);
if(strcmp(op,SYS_CALL[i])==0)
return i;
}
return -1;
}
/**
* extract_no_str - to extract the NO.(no+1) item from this line: l_buf
* @l_buf: line buffer
* @ no: the number of item in l_buf
* @ str: to save the NO.no item in l_buf
*/
int extract_no_str(char *l_buf, int no, char* str)
{
int l_len=strlen(l_buf);
int i=0, j=0, k=0;
if(!str)
return 1;
for(i=0; i< l_len; i++){
if(l_buf[i]==32){ //space: 32...
j++;
i=i+1;
if(j==no-1)
break;
}
}
while(l_buf[i]!=32)
str[k++]=l_buf[i++];
str[k]='\0';
return 0;
}
/**
* extract_op - to extract the operation item from this line: l_buf
* @l_buf: line buffer
* @ op: to save the operation item in l_buf
*/
int extract_op(char *l_buf, char* op)
{
int l_len=strlen(l_buf);
int i=0, j=0, k=0;
if(!op)
return 1;
for(i=0; i< l_len; i++){
if(l_buf[i]==32){ //space: 32...
j++;
i=i+1;
if(j==8)
break;
}
}
while(l_buf[i]!='(')
op[k++]=l_buf[i++];
op[k]='\0';
return 0;
}
/**
* extract_path - to extract the path item from this line: l_buf
* @l_buf: line buffer
* @ op: to save the path item in l_buf
*/
int extract_path(char *l_buf, char* path)
{
int l_len=strlen(l_buf);
int i=0, k=0;
if(!path)
return 1;
while(l_buf[i]!=34) //34 is ascii of ' " '
i++;
i++;
while(l_buf[i]!=34)
path[k++]=l_buf[i++];
path[k]='\0';
//printf("\nIn extract_path and path is: %s", path);
return 0;
}
/**
* extract_last_item - to extract the last item: return value from this line: l_buf
* @l_buf: line buffer
* @ rt: to save the last item in l_buf
*/
int extract_last_item(char *l_buf, char* rt)
{
int k=0, l_len=strlen(l_buf);
int off_set=l_len-3;
while(l_buf[off_set]!='=')
off_set--;
//printf("\noff_set is: %d", off_set);
k=0;
off_set+=2;
while((l_buf[off_set]<58)&&(l_buf[off_set]>44)&&(off_set < l_len))
rt[k++]= l_buf[off_set++];
rt[k]='\0';
//printf("\nIn extract_last_item and fd is |%s|", rt);
return 0;
}
struct user * user_lookup(struct list_head *user_list, int uid)
{
struct list_head *pos;
struct user *tmp;
list_for_each(pos, user_list){
tmp = list_entry(pos, struct user, list);
//printf("\nuserid is :%d pathname is: %s", tmp->usr_id, tmp->cur_path);
}
list_for_each(pos, user_list){
tmp = list_entry(pos, struct user, list);
if(tmp->usr_id==uid)
return tmp;
}
return NULL;
}
int free_userlist(struct list_head *user_list)
{
printf("\nuser_lookup is called ...");
struct list_head *pos;
struct user *tmp;
list_for_each(pos, user_list){
tmp = list_entry(pos, struct user, list);
list_del(&(tmp->list));
free(tmp);
}
return 0;
}
int extract_rw_fd(char *l_buf, char *s_fd)
{
int i=0, j=0;
for(i=0;i<strlen(l_buf);i++)
if(l_buf[i]=='(')
break;
i++;
while(l_buf[i]!=',')
s_fd[j++]=l_buf[i++];
s_fd[j]='\0';
return 0;
}
/**
* line_process - refine the operation and parameters according to the specific content of this line
* @ l_buf: buffer contains this line
* @ o_fs: object file stream handler
* file obj_trace.txt will contai the final trace result
*/
int line_process(char *l_buf, FILE *o_fs, struct list_head *user_list)
{
int op_no=100;
char l_type[10], op[10];
extract_no_str(l_buf, 2, l_type);
if(-1==strcmp(l_type,LINE_TYPE[0])) //we only need type of "UID" and ignore "RESTART" and "TIMESTAMP"
return 0;
extract_op(l_buf, op); //operation type
op_no = type_of_op(op);
switch(op_no){
case 0:
//printf("\nhandle line open...");
handle_line_open(l_buf, user_list);
break;
case 1:
//printf("\nhandle line chdir...");
handle_line_chdir(l_buf, user_list);
break;
case 2:
//printf("\nhandle line read...");
handle_line_read(l_buf,o_fs);
break;
case 3:
//printf("\nhandle line write...");
handle_line_write(l_buf, o_fs);
break;
case 4:
case 5:
//printf("\nhandle line stat...");
handle_line_path_stat(l_buf, user_list, o_fs);
break;
case 6:
handle_line_close(l_buf,o_fs);
break;
default:
break;
}
//printf("\nOne line is processed...");
return 0;
}
int main(int argc, char *argv[])
{
if(argc < 2){
printf("\nPlease make sure that you have input your trace file!!\n");
return 0;
}else{
printf("\nTrace file is: %s\n", argv[1]);
}
char line_buf[MAX_CHARS];
int i=0;
FILE * fs, *ofs;
struct list_head *user_list; //=&usr_list;
LIST_HEAD(ulist);
user_list=&ulist;
INIT_LIST_HEAD(user_list); //define and init the user list
fs = fopen(argv[1], "r+");
ofs = fopen("obj_trace.txt", "a+");
for(i=0;i<MAX_FILES;i++){
File_hstb[i].cur_offset = 0;
File_hstb[i].oid =0;
}
i=0;
if(fs && ofs){
while(fgets(line_buf, MAX_CHARS, fs) > 0){ //get one line from the file...
//if(i>220000)
// break;
i++;
line_process(line_buf, ofs, user_list);
}
}
//free_userlist();
printf("\nThe number of last line is:%d \n", i);
fclose(fs);
fclose(ofs);
return 0;
}
/**
* handle_line_open - process a line of open trace
* @ l_buf: buffer contains this line
*/
int handle_line_open(char *l_buf, struct list_head *user_list)
{
int fd=0;
char pathname[500], s_fd[150], tmppath[500];
struct user *cur_user=NULL;
int i=0, j=0;
int usr_id;
char uid[10];
extract_last_item(l_buf, s_fd);
fd=atoi(s_fd);
//printf("\nfd:%d...",fd);
if(fd<0||fd>20000) //if open failed , just ignore this line
return 0;
extract_path(l_buf,pathname);
switch(pathname[0]){
case '.':
//printf("\nopen case . ..");
extract_no_str(l_buf, 3, uid);
usr_id=atoi(uid);
cur_user=user_lookup(user_list, usr_id);
if(cur_user==NULL){
cur_user=(struct user*)malloc(sizeof(struct user));
cur_user->cur_path[0]='/';
cur_user->cur_path[1]='\0'; //default current path : "/"
cur_user->usr_id=usr_id;
list_add(&(cur_user->list), user_list); //add this new user to the list
strcpy(pathname,cur_user->cur_path);
}else{
if((strlen(pathname)>=2)&&pathname[1]=='.'){
strcpy(tmppath,cur_user->cur_path);
for(i=strlen(tmppath);i>0; i--) //here we assume ../../../ will not emerge...
if(tmppath[i]=='/'){
tmppath[i]='\0';
break;
}
for(i=0; i<strlen(pathname)-2;i++)//delete .. from the head
pathname[i]=pathname[i+2];
strcat(tmppath, pathname);
strcpy(pathname,tmppath); //here the dir of the file is ok...
}else if((strlen(pathname)>=2)&&pathname[1]=='/'){
strcpy(tmppath,cur_user->cur_path);
for(i=0; i<strlen(pathname);i++)
pathname[i]=pathname[i+1];
strcat(tmppath, pathname);
strcpy(pathname,tmppath);
}else{ //case the file type like .config
strcpy(tmppath,cur_user->cur_path);
j=strlen(pathname);
if(pathname[j-1]!='/'){
pathname[j]='/';
pathname[j+1]='\0';
}
strcat(tmppath, pathname);
strcpy(pathname,tmppath);
}
}
break;
case '/':
//printf("\nopen case / ..");
break;
default:
//printf("\nopen case default ..");
extract_no_str(l_buf, 3, uid);
usr_id=atoi(uid);
cur_user=user_lookup(user_list, usr_id);
if(cur_user==NULL){
cur_user=(struct user*)malloc(sizeof(struct user));
cur_user->cur_path[0]='/';
cur_user->cur_path[1]='\0'; //default current path : "/"
cur_user->usr_id=usr_id;
list_add(&(cur_user->list), user_list); //add this new user to the list
strcpy(pathname,cur_user->cur_path);
}else{
strcpy(tmppath,cur_user->cur_path);
j=strlen(pathname);
if(pathname[j-1]!='/'){
pathname[j]='/';
pathname[j+1]='\0';
}
strcat(tmppath, pathname);
strcpy(pathname,tmppath); //here the dir of the file is ok...
}
break;
}
//printf("\npathname is: %s", pathname);
File_hstb[fd].cur_offset= 0;
File_hstb[fd].oid=path2oid(pathname, strlen(pathname));
return 0;
}
int handle_line_chdir(char *l_buf, struct list_head *user_list)
{
int fd=0;
char pathname[5000], s_fd[15], tmppath[5000];
struct user *cur_user=NULL;
int i=0, j=0;
int usr_id;
char uid[10];
extract_last_item(l_buf, s_fd);
fd=atoi(s_fd);
if(fd<0||fd>20000) //if open failed , just ignore this line
return 0;
extract_path(l_buf,pathname);
extract_no_str(l_buf, 3, uid);
usr_id=atoi(uid);
cur_user=user_lookup(user_list, usr_id);
if(cur_user==NULL){
cur_user=(struct user*)malloc(sizeof(struct user));
cur_user->cur_path[0]='/';
cur_user->cur_path[1]='\0';
cur_user->usr_id=usr_id;
list_add(&(cur_user->list), user_list); //add this new user to the list
strcpy(cur_user->cur_path, pathname);
}else{
//printf("\nOrignal cur-path is:%s and pathname is: %s", cur_user->cur_path, pathname);
switch(pathname[0]){
case '.':
//printf("\nEntering . dir...");
if((strlen(pathname)>=2)&&(pathname[1]=='.')){
strcpy(tmppath,cur_user->cur_path);
//printf("\nAfter strcpy .. dir...");
j=0;
for(i=strlen(tmppath);i>0; i--){ //cd .. here we assume ../../../ will not emerge...
if(tmppath[i]=='/'){
j++;
if(j==2){
tmppath[i]='\0';
break;
}
}
//printf("\ni value is: %d", i);
}
for(i=0; i<strlen(pathname);i++)//delete .. from the head
pathname[i]=pathname[i+2];
strcat(tmppath, pathname);
strcpy(cur_user->cur_path,tmppath);
}else{
strcpy(tmppath,cur_user->cur_path);
for(i=0; i<strlen(pathname);i++)
pathname[i]=pathname[i+1];
strcat(tmppath, pathname);
strcpy(cur_user->cur_path,tmppath); //here the dir of the file is ok...
}
break;
case '/':
if(cur_user->cur_path[strlen(cur_user->cur_path)-1]=='/'){
for(i=0; i<strlen(pathname)-1;i++)
tmppath[i]=pathname[i+1];
tmppath[i]='\0';
strcat(cur_user->cur_path,tmppath);
}else
strcat(cur_user->cur_path, pathname);
strcpy(cur_user->cur_path,pathname);
break;
default: // directly a name string....
if(cur_user->cur_path[strlen(cur_user->cur_path)-1]!='/'){
tmppath[0]='/';
for(i=0; i<strlen(pathname);i++)
tmppath[i+1]=pathname[i];
tmppath[i+2]='\0';
strcat(cur_user->cur_path,tmppath);
}else
strcat(cur_user->cur_path, pathname);
break;
}
}
//printf("\nAfter chdir: cur-path is:%s", cur_user->cur_path);
return 0;
}
int handle_line_read(char *l_buf, FILE * o_fs)
{
int fd, rcount;
char s_fd[15], s_rct[15];
extract_rw_fd(l_buf, s_fd);
fd=atoi(s_fd);
extract_last_item(l_buf, s_rct);
rcount=atoi(s_rct);
if(rcount<=0)
return 0;
if(o_fs)
fprintf(o_fs,"0 %s %lu %lu %d\n", SYS_CALL_MAC[0], File_hstb[fd].oid, File_hstb[fd].cur_offset, rcount);
else
printf("\nInvalid file handler...");
File_hstb[fd].cur_offset+=rcount;
return 0;
}
int handle_line_close(char *l_buf, FILE * o_fs)
{
int fd;
char s_fd[15];
extract_rw_fd(l_buf, s_fd);
fd=atoi(s_fd);
if(o_fs)
fprintf(o_fs,"0 %s %lu\n", SYS_CALL_MAC[4], File_hstb[fd].oid);
else
printf("\nInvalid file handler...");
return 0;
}
int handle_line_write(char *l_buf, FILE * o_fs)
{
int fd, count;
char s_fd[15], s_ct[15];
extract_rw_fd(l_buf, s_fd);
fd=atoi(s_fd);
extract_last_item(l_buf, s_ct);
count=atoi(s_ct);
if(count<=0)
return 0;
if(o_fs)
fprintf(o_fs,"0 %s %lu %lu %d\n", SYS_CALL_MAC[1], File_hstb[fd].oid, File_hstb[fd].cur_offset, count);
else
printf("\nInvalid file handler...");
File_hstb[fd].cur_offset+=count;
return 0;
}
int handle_line_path_stat(char *l_buf, struct list_head *user_list, FILE * o_fs)
{
int rtv=0;
char pathname[5000], s_rt[15], tmppath[5000];
struct user *cur_user=NULL;
int i=0, j=0;
int usr_id;
char uid[10];
extract_last_item(l_buf, s_rt);
rtv=atoi(s_rt);
if(rtv<0) //if stat failed , just ignore this line
return 0;
//printf("\n\n\nin handle line stat and before extract pathname...");
extract_path(l_buf,pathname);
switch(pathname[0]){
case '.':
//printf("\nIn stat case . ....");
extract_no_str(l_buf, 3, uid);
usr_id=atoi(uid);
cur_user=user_lookup(user_list, usr_id);
if(cur_user==NULL){
cur_user=(struct user*)malloc(sizeof(struct user));
cur_user->cur_path[0]='/';
cur_user->cur_path[1]='\0'; //default current path : "/"
cur_user->usr_id=usr_id;
list_add(&(cur_user->list), user_list); //add this new user to the list
strcpy(pathname,cur_user->cur_path);
break;
}
if((strlen(pathname)>=2)&&pathname[1]=='.'){
//printf("\nEntering .. process...");
strcpy(tmppath,cur_user->cur_path);
for(i=strlen(tmppath);i>0; i--) //here we assume ../../../ will not emerge...
if(tmppath[i]=='/'){
tmppath[i]='\0';
break;
}
for(i=0; i<strlen(pathname);i++)//delete .. from the head
pathname[i]=pathname[i+2];
strcat(tmppath, pathname);
strcpy(pathname,tmppath); //here the dir of the file is ok...
}else if((strlen(pathname)>=3)&&pathname[1]=='/'){
strcpy(tmppath,cur_user->cur_path);
for(i=0; i<strlen(pathname);i++)//delete .. from the head
pathname[i]=pathname[i+1];
strcat(tmppath, pathname);
strcpy(pathname,tmppath);
}else{ //case the file type .config
strcpy(tmppath,cur_user->cur_path);
j=strlen(pathname);
pathname[j]='/';
pathname[j+1]='\0';
strcat(tmppath, pathname);
strcpy(pathname,tmppath); //here the dir of the file is ok...
}
break;
case '/':
//printf("\nIn stat case / ....");
break;
default:
//printf("\nIn stat case default ....");
extract_no_str(l_buf, 3, uid);
usr_id=atoi(uid);
cur_user=user_lookup(user_list, usr_id);
if(cur_user==NULL){
cur_user=(struct user*)malloc(sizeof(struct user));
cur_user->cur_path[0]='/';
cur_user->cur_path[1]='\0'; //default current path : "/"
cur_user->usr_id=usr_id;
list_add(&(cur_user->list), user_list); //add this new user to the list
strcpy(pathname,cur_user->cur_path);
}else{
strcpy(tmppath,cur_user->cur_path);
j=strlen(pathname);
pathname[j]='/';
pathname[j+1]='\0';
strcat(tmppath, pathname);
strcpy(pathname,tmppath); //here the dir of the file is ok...
}
break;
}
if(o_fs)
fprintf(o_fs,"0 %s %lu\n", SYS_CALL_MAC[2], path2oid(pathname, strlen(pathname)));
else
printf("\nInvalid file handler...");
return 0;
}