%% This is a synthetic trace generator. Each file has seven attributes: (1) its popularity weight; (2) its access arrival rate lambda; 
%% (3) its access request numbers within total REQUEST_NUM requests; (4) its size in reverse correlation with access rate using the same SKEW_DEGREE; 

%% The degree of request concentration on some hot files is controlled by the parameter zeta. When zeta=1, the probabilites obey a uniform distribution; 
%% when zeta=0, the probabilities obey a Zipfian one. 

clear all;
FILE_NUM=50;         %% Number of files to be assigned to the disk array.
REQUEST_NUM=1000;    %% Total number of requests.
TIME_SPAN=50;        %% This is the time span in which the REQUEST_NUM access requests arrived in the server. The unit is second.
FILE_BASE_SIZE=10000; %% Assume that the base size of all files is 10000 MBytes.
File_attribute=repmat(0,FILE_NUM,4); %% For each file, it has three attributes: (1) its popularity weight; (2) its access arrival rate lambda; (3) its access request numbers within total REQUEST_NUM requests; (4) its size. 
SKEW_DEGREE=0.7; %% If SKEW_DEGREE=0.7, it means that 70% of all accesses were directed to 30% percent of files.
zeta=log(SKEW_DEGREE)/log(1-SKEW_DEGREE); %% zeta must be in the range of [0,1]. 
%% Calculate each file's popularity weight and store it into the File_attribute array.
C=0;
i=1;
while i <= FILE_NUM
    C=C+i.^(zeta-1);
    File_attribute(i,1) = 1/i.^(1-zeta);
    i=i+1;
end
C=1/C;
File_attribute(:,1)=C*File_attribute(:,1); 

%% Calculate each file's access rate lambda and store it into the File_attribute array.
i=1;
while i <= FILE_NUM
    File_attribute(i,2)=(REQUEST_NUM*File_attribute(i,1))/TIME_SPAN;
    File_attribute(i,3)=floor(REQUEST_NUM*File_attribute(i,1));
    i=i+1;
end
xx=1;
%% Case One - Note that in this case we use the same value of SKEW_DEGREE for file size distrubtion.
%% A file's real size = A Base Size of all files * the file's size weight.
i=0;
while i < FILE_NUM
    File_attribute(i+1,4)=File_attribute(FILE_NUM-i,2);
    i=i+1;
end
File_attribute(:,4)=round(FILE_BASE_SIZE * File_attribute(:,4));
Real_request_num=sum(File_attribute(:,3)); %% Since there's truncation error, REQUEST_NUM usually is not the real total request number. We need to compute the real total request number.
% We need to amend each file's access rate here because there are truncation errors when we generate request numbers for each file.
i=1;
while i <= FILE_NUM
    File_attribute(i,2)=File_attribute(i,3)/TIME_SPAN;
    i=i+1;
end
Request_attribute=repmat(0,Real_request_num,2); %% Each request has two features: (1) the file number (ID) that it targets on; (2) its arrival time (in second).
%% Calculate each file's access request arrival pattern (ie., interarrival times of accesses to each file) and store it into the Request_attribute array.
rand('state',100);
start_point=1; %% This is a pointer that points to the current position of the Request_attribute array.
i=1;
while i <= FILE_NUM
    j=1;
    lambda=File_attribute(i,2);
    Total_num_request_currentfile=File_attribute(i,3); %% This is the total request numbers targeted on the current file.
    Request_arrival_time(1)=random('Exponential',1/lambda);
    Request_attribute(start_point,1)=i;              %% The number (ID) of current file.
    Request_attribute(start_point,2)=Request_arrival_time(1); %% The arrival time of the first request for the current file.
    if Total_num_request_currentfile <= 2 % All the files that have no more than 2 accesses need special handling here.
        Request_attribute(start_point,2)=1+9*rand(1,1); % Left shifting the request arrival time instances for very big files such that they can arrive earlier to block other small files.
    end
    while j < Total_num_request_currentfile %% The assumption is that each file will be accessed at least once.
        Request_arrival_time(j+1)=Request_arrival_time(j)+random('Exponential',1/lambda);
        start_point=start_point+1;          %% Advance one position to point to the current position of the current request.
        Request_attribute(start_point,1)=i; %% The number (ID) of current file.
        Request_attribute(start_point,2)=Request_arrival_time(j+1);        %% Record the arrival time of requests of the current file.
        if Total_num_request_currentfile <= 2 % All the files that have no more than 2 accesses need special handling here.
            Request_attribute(start_point,2)=1+9*rand(1,1); % Left shifting the request arrival time instances for very big files such that they can arrive earlier to block other small files.
        end
        j=j+1;
    end
    i=i+1;  %% Handle next file.
    start_point=start_point+1;
    clear Request_arrival_time;
end
%% Sort array Request_attribute's column according to the ascending order.
[Y,I]=sort(Request_attribute,1,'ascend');
i=1;
while i <= Real_request_num
    Y(i,1)=Request_attribute(I(i,2),1); %% Assign the real file ID to the right place.
    i=i+1;
end
Request_attribute=Y; %% Now the Request_attribute array was sorted according to request arrival time in the ascending order.
clear Y I;

[REQUEST_NUM,n]=size(Request_attribute); % This is the real and final total request number.
save sead_workload File_attribute Request_attribute FILE_NUM REQUEST_NUM TIME_SPAN;

