0001 function studyinfo = dsStudyinfoIO(studyinfo,study_file,id,verbose_flag)
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021 if nargin<4, verbose_flag=0; end
0022 if nargin<3, id=[]; end
0023 if nargin<2 || isempty(study_file)
0024 study_file='studyinfo.mat';
0025 elseif isdir(study_file)
0026 study_file=fullfile(study_file,'studyinfo.mat');
0027 end
0028 study_dir=fileparts2(study_file);
0029 if nargin<1, studyinfo=[]; end
0030
0031
0032 [~,OS]=system('uname');
0033 OS=lower(strtrim(OS));
0034 if length(OS)>7
0035
0036 OS=strtrim(OS(end-6:end));
0037 end
0038
0039
0040
0041 if isempty(id)
0042
0043 curr_ids=[];
0044 switch OS
0045 case {'linux','darwin'}
0046
0047 [status,result]=system(['ls ' study_dir '/.lock_* 2>/dev/null']);
0048 if status==0
0049 ids=regexp(result,'.lock_\d+_(\d+)','tokens');
0050 if ~isempty(ids), curr_ids=cellstr2num([ids{:}]); end
0051 end
0052 otherwise
0053
0054 D=dir(study_dir);
0055 status=~any(find(~cellfun(@isempty,regexp({D.name},'^lock_'))));
0056 if status==0
0057 ids=regexp({D.name},'lock_\d+_(\d+)','tokens','once');
0058 if ~isempty(ids), curr_ids=cellstr2num([ids{:}]); end
0059 end
0060 end
0061 end
0062
0063 MIN_LOAD_ID=1e7;
0064
0065
0066
0067
0068
0069
0070 if isempty(studyinfo)
0071
0072 action='load';
0073 if isempty(id)
0074
0075 if ~isempty(curr_ids) && any(curr_ids>=MIN_LOAD_ID)
0076 id=max(curr_ids)+1;
0077 else
0078 id=MIN_LOAD_ID;
0079 end
0080 end
0081 if ~exist(study_file,'file')
0082 error('studyinfo.mat file not found: %s',study_file);
0083 end
0084 else
0085
0086 action='save';
0087 if isempty(id)
0088
0089 if ~isempty(curr_ids) && any(curr_ids<MIN_LOAD_ID) && ismember(0,curr_ids)
0090 id=max(curr_ids)+1;
0091 else
0092 id=0;
0093 end
0094 end
0095 end
0096
0097
0098 timestamp=datestr(now,'yyyymmddHHMMSSFFF');
0099
0100 switch OS
0101 case {'linux','darwin'}
0102 lock_file=fullfile(study_dir,sprintf('.lock_%s_%i',timestamp,id));
0103 [s,r]=system(['touch ' lock_file]);
0104 if s, error(r); end
0105 common_lock_file=fullfile(study_dir,'.locked');
0106 otherwise
0107 lock_file=fullfile(study_dir,sprintf('lock_%s_%i',timestamp,id));
0108 fid=fopen(lock_file,'w');
0109 fclose(fid);
0110 common_lock_file=fullfile(study_dir,'locked');
0111 end
0112
0113 if verbose_flag
0114 fprintf('created temporary lock file for this process: %s\n',lock_file);
0115 end
0116
0117
0118
0119
0120 try
0121
0122
0123 timeout=30;
0124 delay=0.001;
0125 max_num_timeouts=50;
0126
0127 cnt=1;
0128 done=0;
0129 while ~done
0130
0131 for idx=1:(timeout/delay)
0132 next_id=NextStudyinfoID(study_dir,OS);
0133
0134 if (id==next_id) && ~exist(common_lock_file,'file')
0135
0136 switch OS
0137 case {'linux','darwin'}
0138 [s,r]=system(['touch ' common_lock_file]);
0139 if s, error(r); end
0140 otherwise
0141 fid=fopen(common_lock_file,'w');
0142 fclose(fid);
0143 end
0144 try
0145 switch action
0146 case 'load'
0147
0148 if verbose_flag
0149 fprintf('loading study file: %s\n',study_file);
0150 end
0151 studyinfo=getfield(load(study_file,'studyinfo'),'studyinfo');
0152 case 'save'
0153 if isfield(studyinfo,'sim_id')
0154
0155 simulations=studyinfo;
0156
0157 studyinfo=getfield(load(study_file,'studyinfo'),'studyinfo');
0158
0159 for sim=1:length(simulations)
0160 ix=[studyinfo.simulations.sim_id]==simulations(sim).sim_id;
0161 studyinfo.simulations(ix)=simulations(sim);
0162 end
0163 if verbose_flag
0164 fprintf('updating simulation metadata in study file: %s\n',study_file);
0165 end
0166 else
0167 if verbose_flag
0168 fprintf('saving study file: %s\n',study_file);
0169 end
0170 end
0171
0172 try
0173 save(study_file,'studyinfo','-v7');
0174 if ~strcmp(reportUI,'matlab')
0175 [wrn_msg,wrn_id] = lastwarn;
0176 if strcmp(wrn_msg,'save: wrong type argument ''function handle''')
0177 error('save: wrong type argument ''function handle''');
0178 end
0179 end
0180 catch
0181 fprintf('Data is not ''-v7'' compatible. Saving in hdf5 format.\n')
0182 save(study_file,'studyinfo','-hdf5');
0183 end
0184 end
0185 done=1; break;
0186 catch
0187 if verbose_flag
0188 fprintf('failed to %s study file: %s\n',action,study_file);
0189 end
0190 pause(delay);
0191 end
0192 else
0193 pause(delay);
0194 end
0195
0196
0197 if idx==1
0198 is_unchanged=1;
0199 else
0200 is_unchanged = is_unchanged && (next_id==last_next_id);
0201 end
0202 last_next_id=next_id;
0203 end
0204
0205 if idx==(timeout/delay) && is_unchanged
0206
0207
0208 D=dir(study_dir);
0209 pat=sprintf('^.?lock_\\d+_%i$',last_next_id);
0210 ind=find(~cellfun(@isempty,regexp({D.name},pat)));
0211 if ~isempty(ind)
0212 next_lock_file=D(ind).name;
0213 if verbose_flag
0214 fprintf('deleting stale temporary lock file: %s\n',next_lock_file);
0215 end
0216 delete(next_lock_file);
0217 delete(common_lock_file);
0218 end
0219 end
0220 if ~done
0221 if verbose_flag
0222 fprintf('TIMEOUT #%g while waiting to %s study file for process %g (next_id=%g).\n',cnt,action,id,next_id);
0223 end
0224 cnt=cnt+1;
0225 end
0226
0227 if cnt>max_num_timeouts
0228
0229 if verbose_flag
0230 fprintf('deleting temporary lock file for this process: %s\n',lock_file);
0231 end
0232 delete(lock_file);
0233 delete(common_lock_file);
0234 error('failed to access studyinfo file after %g timeouts.',max_num_timeouts);
0235 end
0236 end
0237
0238 if verbose_flag
0239 fprintf('deleting temporary lock file for this process: %s\n',lock_file);
0240 end
0241 delete(lock_file);
0242 delete(common_lock_file);
0243
0244 catch err
0245 if verbose_flag
0246 fprintf('deleting temporary lock file for this process: %s\n',lock_file);
0247 end
0248 delete(lock_file);
0249 delete(common_lock_file);
0250 displayError(err);
0251 end
0252
0253
0254
0255
0256 function id=NextStudyinfoID(study_dir,OS)
0257
0258
0259
0260
0261 id=0;
0262 switch OS
0263 case {'linux','darwin'}
0264
0265 [status,result]=system(['ls ' fullfile(study_dir,'.lock_* 2>/dev/null')]);
0266 if status==0
0267
0268 ids=regexp(result,'.lock_\d+_(\d+)','tokens');
0269 if ~isempty(ids)
0270
0271 ids=[ids{:}];
0272 id=max(cellstr2num(ids));
0273 end
0274
0275
0276
0277
0278
0279
0280
0281
0282
0283
0284
0285
0286 end
0287 otherwise
0288 D=dir(study_dir);
0289 status=~any(find(~cellfun(@isempty,regexp({D.name},'^lock_'))));
0290 if status==0
0291
0292 timestamps=regexp({D.name},'lock_(\d+)_\d+','tokens','once');
0293 if ~isempty(timestamps)
0294
0295 timestamps=[timestamps{:}];
0296 if isempty(timestamps), return; end
0297 x=cellstr2num(timestamps);
0298 timestamp=timestamps{x==min(x)};
0299
0300 ids=regexp({D.name},sprintf('lock_%s_(\\d+)',timestamp),'tokens','once');
0301
0302 id=max(cellstr2num([ids{:}]));
0303 end
0304 end
0305 end
0306
0307
0308
0309
0310
0311
0312 timeout=30*5;
0313 delay=0.01;
0314 for idx=1:(5*timeout/delay)
0315
0316
0317
0318
0319 switch OS
0320 case {'linux','darwin'}
0321
0322 [status,~]=system(['ls ' study_dir '/.lock_* 2>/dev/null']);
0323 otherwise
0324
0325 D=dir(study_dir);
0326 status=~any(find(~cellfun(@isempty,regexp({D.name},'^lock_'))));
0327 end
0328
0329 if status==0
0330
0331
0332
0333 pause(delay);
0334 else
0335 break;
0336 end
0337 end
0338
0339 if idx==(timeout/delay)
0340 if verbose_flag
0341 fprintf('deleting all temporary lock files blocking this process...\n');
0342 end
0343 D=dir(study_dir);
0344 inds=find(~cellfun(@isempty,regexp({D.name},'^.?lock_')));
0345
0346 for i=1:length(inds)
0347 file=fullfile(study_dir,D(inds(i)).name);
0348 if verbose_flag
0349 fprintf('\t%s\n',file);
0350 end
0351 delete(file);
0352 end
0353 end
0354