<?

/*
// пример теста
$write_buffer = 1*1024*1024;
$content = str_repeat("1", $write_buffer);
$fpath = "test_write.txt";
$try_num = 5;
$fh = fopen($fpath, 'wb');

$res = multi_try_write($fh, $fpath, &$content, $try_num, $write_buffer, false);
var_dump($res);
print "размер content: " . strlen($content) . "\n";

*/
// $fh сразу передается. Но в процессе работы может потребоваться открыть файл заново, потому передаем fpath
function multi_try_write($fh, $fpath, &$content, $try_num, $write_buffer, $is_thread=true) {
	GLOBAL $log, $thread,  $Disc_info, $Paths;

	$ds_err =& $GLOBALS[DS_error];

	// несколько попыток записи
	$write_str = $content;
	for($i=1; $i<=$try_num; $i++) {
		
		$need = strlen($write_str);
		if($need == 0)
			return true;

		// тестирование функции
		// if($i == 1) 
		// 	 $real_w = substr($write_str, 500);
		// else $real_w = $write_str;
		// if($i == 2) fclose($fh);
		// $writed = fwrite($fh, $real_w);

		n();
		$writed = fwrite($fh, $write_str);
		fflush($fh);
		y();

		if($writed == $need) {
			if($i > 1) 
				$log->line("Успешно дописали в файл");

			return true;
		}
		elseif($writed > 0) {
			$log->line("Попытка $i. Записано недостаточно байт: $writed. Продолжаем пытаться");
			$add_str = substr($write_str, $writed);
			unset($write_str); // чтобы удалить ссылку на content, если это первый проход цикла
			$write_str = $add_str;
		}
		else {

			// проверяем, а не закончилось ли место на диск. Разные бывают ситуации, например системная папка разбухла.
			// вдруг диск не закончился, а наткнулись на битый сектор
			$disk_size = $Disc_info->size($Paths->disc_name, 'MB', 2, false);
			if($disk_size['free'] < 0.3) { 
				$msg = "Место на диске закончилось. Cтранно, но допустимо";
				trigger_error($msg);
				logFile("multi_try_write ($fpath): $msg");
				$log->line($msg);
				return true;
			}

			$log->line("Попытка $i. Не удалочь ничего записать. Пробуем еще раз");
			// если не удалось ничего записать, просто идем на следующую итерацию
		}

		if($is_thread) 
			$thread->send_info();

		// если файл закрыт по  каким то причинам, открываем снова
		if(!is_resource($fh)) {
			$log->line("Файл почему то закрылся. Открываем заново");

			n(); fclose($fh); y(); // на всякий случай пробуем закрыть

			clearstatcache();
			if(file_exists($fpath)) 
				 $fmode = 'ab';
			else $fmode = 'wb';

			for($p=1; $p<=10; $p++) {
				n(); $fh = fopen($fpath, $fmode); y();
				if($fh) {
					stream_set_write_buffer($fh, $write_buffer);
					break;
				}
				else {
					$log->line("Попытка $p. Не удалось открыть файл. Пробуем еще раз");

					if($is_thread) 
						$thread->send_info();
				}
			}

			if(!$fh)
				throw new Error_def("multi_try_write: Не удалось повторно открыть файл");
		}

		//TODO: если файл заблокирован, можно открыть другой с цифровым окончанием 
	}

	throw new Error_def("multi_try_write: Не удалось записать файл $fpath");
}

?>