#!/opt/Guardian/Admin/php/bin/php
<?php
// ƺץ (GUARDIANSUITE V4.0ʾ)
// оݡƺǡ᡼ƺץǡִƺץǡ
//
// Copyright (c) 2006 Canon System Solutions Inc. All rights reserved.

require_once "util.php";
require_once "const.php";
require_once "db/db.php";

// PostgreSQL ΥॢȤ 0 
putenv("PGOPTIONS=-c statement_timeout=0");

define('DISK_USAGE', GRDN_BASE . "local/bin/du -ks ");
global $lockfp, $conf, $check;

function usage() {
    print "Usage: " . basename($_SERVER["PHP_SELF"]) . " [options] \n";
    print "  -f : config file path. \n";
    print "  -n : check only (display remove target file). \n";
    exit(1);
}

function errex($s) {
    global $lockfp;
    guts_log_err("guts_kansa_logger: " . $s);
	release_lock($lockfp);
    exit(1);
}

$conf = null;
$check = false;

if (count($argv) == 1) usage();
array_shift($argv);
while(($opt = array_shift($argv)) != null) {
    if ($opt{0} != '-')
        break;
    switch($opt{1}) {
    case 'f':
        $conf = array_shift($argv);
        break;
    case 'n':
        $check = true;
        break;
    default:
        usage();
        break;
    }
}

if (!file_exists($conf)) {
	errex("Not Exists ConfigFile($conf)");
}
$lockfp = getLock();
if ($lockfp === false) errex("¾Υץꥱ󤬥ǡ١Ǥ");

// -------------------------------------------------------------
// ͼ
// -------------------------------------------------------------
// ƺǥ쥯ȥ
$kansa_dir = getCmdConfig('Kansa', 'KansaArchiveDirectory');
if (!preg_match("/\/$/", $kansa_dir)) $kansa_dir .= '/';
if (!is_dir($kansa_dir)) {
	errex("ƺǥ쥯ȥ꤬ޤ");
}

// 
$KansaLog = getConf('Expire', 'KansaLog', '365');
// ƺǡ
$KansaArchive = getConf('Expire', 'KansaArchive', '365');
$MaxKansaArchiveSize = getConf('Expire', 'MaxKansaArchiveSize', '0');
// ᡼ƺץǡ
$KansaMailStat = getConf('Expire', 'KansaMailStat', '365');
$MaxKansaMailStatSize = getConf('Expire', 'MaxKansaMailStatSize', '0');
// ִƺץǡ
$KansaWebStat = getConf('Expire', 'KansaWebStat', '365');
$MaxKansaWebStatSize = getConf('Expire', 'MaxKansaWebStatSize', '0');

if ($check) {
	print "[KansaLog]            :" . $KansaLog . " days\n";
	print "[KansaArchive]        :" . $KansaArchive . " days\n";
	print "[MaxKansaArchiveSize] :". $MaxKansaArchiveSize . " MB\n";
	print "[KansaMailStat]       :" . $KansaMailStat . " days\n";
	print "[MaxKansaMailStatSize]:" . $MaxKansaMailStatSize . " MB\n";
	print "[KansaWebStat]        :" . $KansaWebStat . " days\n";
	print "[MaxKansaWebStatSize] :" . $MaxKansaWebStatSize . " MB\n";
}

// -------------------------------------------------------------
// ƥκ
// -------------------------------------------------------------
if ($KansaLog > 0 && !removeExpireKansaLog($KansaLog)) {
	errex("顼");
}
if ($KansaArchive > 0 && !removeExpireKansaArchive($kansa_dir, $KansaArchive)) {
	errex("ƺǡĶ顼");
}
if ($KansaMailStat > 0 && !removeExpireStat($kansa_dir, 'mail', $KansaMailStat)) {
	errex("᡼ƺץǡĶ顼");
}
if ($KansaWebStat > 0 && !removeExpireStat($kansa_dir, 'web', $KansaWebStat)) {
	errex("ִƺץǡĶ顼");
}
if ($MaxKansaArchiveSize > 0 
	&& !removeMaxSizeKansaArchive($kansa_dir, $MaxKansaArchiveSize, &$err)) 
{
	errex($err);
}
if ($MaxKansaMailStatSize > 0
	&& !removeMaxSizeKansaStat($kansa_dir, $MaxKansaMailStatSize, 'mail', &$err)) 
{
	errex($err);
}
if ($MaxKansaWebStatSize > 0
	&& !removeMaxSizeKansaStat($kansa_dir, $MaxKansaWebStatSize, 'web', &$err)) 
{
	errex($err);
}

// VACUUM ANALYZE
if (!$check && !vacuum(&$err)) {
	errex($err);
}
release_lock($lockfp);

exit(0);

/* ͼ */
function getConf($sec, $key, $default) {
	global $conf;
    $val = ReadServerConfig($key, $default, $conf, $sec);
    if ($val == "") // key = ʤȤä
        $val = $default;
    return intval($val);
}

/*
 * ¸֤β᤮ƺ
 */
function removeExpireKansaLog($days) {
	global $check;
	if ($check) {
    	$sql  = "SELECT count(*) as cnt FROM kansa_log";
    	$sql .= " WHERE time < (CURRENT_DATE - " . $days . ")";
	} else {
    	$sql  = "DELETE FROM kansa_log";
    	$sql .= " WHERE time < (CURRENT_DATE - " . $days . ")";
	}
	$result = query($sql);
    if (DB::isError($result)) return false;
	if ($check) {
		print "<remove> KansaLog: " . $result[0]->cnt . " records \n";
	}
    return true;
}

/*
 * ¸֤β᤮ƺ֤
 */
function removeExpireKansaArchive($dir, $days) {
	global $check;
    $charc_dir = $dir . "charc/";
    if (!is_dir($charc_dir)) return true;
    foreach (glob($charc_dir . "*/*/*") as $dirname) {
        if (preg_match("/^.*(\d{4})\/(\d{2})\/(\d{2})$/", $dirname, $v)) {
            $ymd = $v[1] . $v[2] . $v[3];
        } else {
            continue;
        }
        // о
        if (isRemoveDir($ymd, $days)) {
			if ($check) {
				print "<remove> $dirname\n";
			} else {
            	if (!removeDir($dirname)) return false;
			}
        }
    }
    return true;
}

/*
 * ¸֤β᤮׾ե(᡼,)
 */
function removeExpireStat($dir, $type, $days) {
	global $check;
    $stat_dir = $dir . "stat/" . $type . "/";

    if (!is_dir($stat_dir))
        return true;

    foreach (glob($stat_dir . "*") as $file) {
        if (preg_match("/\/(\d{8})-(\d{6})\.csv$/", $file, $v)) {
            $ymd = $v[1];
        } else {
            continue;
        }
        // о
        if (isRemoveDir($ymd, $days)) {
			if ($check) {
				print "<remove> $file \n";
			} else {
            	if (!su_rm($file)) return false;
			}
        }
    }
    return true;
}

/* ǯĶᤫɤȽ */
function isRemoveDir($ymd, $days) {
    if (!$ymd || strlen($ymd) != 8) {
        return false;
    }
    $y = substr($ymd, 0, 4);
    $m = substr($ymd, 4, 2);
    $d = substr($ymd, 6, 2);
    $ymd_t = mktime(0, 0, 0, $m, $d, $y);

    $chk_t = $days * 24 * 60 * 60;

    $now_y = date("Y", time());
    $now_m = date("m", time());
    $now_d = date("d", time());
    $now_t = mktime(0, 0, 0, $now_m, $now_d, $now_y);

    return ($now_t - $ymd_t > $chk_t);
}

/* եǥ쥯ȥ */
function removeDir($dir) {
    if (!rmdir_tree($dir, true)) {
        print "failed remove dir ($dir).";
        return false;
    }
    // ƥǥ쥯ȥ()⤬ˤʤäϿƥǥ쥯ȥ
    $parent = dirname($dir);
    if (isEmptyDir($parent)) {
        rmdir_tree($parent, true);
    }
    // ƥǥ쥯ȥ(ǯ)⤬ˤʤäϿƥǥ쥯ȥ
    $gparent = dirname($parent);
    if (isEmptyDir($gparent)) {
        rmdir_tree($gparent, true);
    }
    return true;
}

/* ǥ쥯ȥ꤬Ǥ뤫ɤȽ */
function isEmptyDir($path) {
    if ($path == '' || !is_dir($path)) {
        return false;
    }
    $rtn = true;
    $df = opendir($path);
    if (!$df) {
        print "error open dir ($path). \n";
        return false;
    }
    while ($file = readdir($df)) {
        if ($file != "." && $file != "..") {
            $rtn = false;
            break;
        }
    }
    closedir($df);
    return $rtn;
}

/*
 * ƺǡ¥Ķե
 */
function removeMaxSizeKansaArchive($dir, $size, $err) {
	global $check;
	$charc_dir = $dir . "charc/";
	$du = getDiskUsage($charc_dir, &$err);
	if ($du === false) return false;
	// MB -> KB
	$size = $size * 1024;
	if ($check) print "[KansaArchiveDir(du)]: " . $du . " KB\n";
	while($du > $size) {
		if (removeOldestKansaArchive($charc_dir) == 0) {
			break;
		}
		$du = getDiskUsage($charc_dir, &$err);
		if ($du === false) return false;
	}
	return true;
}

/*
 * դָŤƺ֤
 * return: ǥ쥯ȥο
 */
function removeOldestKansaArchive($charc_dir) {
	global $check;
    if (!is_dir($charc_dir)) return 0;

    foreach (glob($charc_dir . "*/*/*") as $dirname) {
        if (preg_match("/^.*(\d{4})\/(\d{2})\/(\d{2})$/", $dirname, $v))
            $dirlist[] = $dirname;
    }

    // ǥ쥯ȥ꤬ʤ 0 ֤
    if (count($dirlist) == 0)
        return 0;

    sort($dirlist);
    $dir = array_shift($dirlist);

	if ($check) {
		print "<remove> $dir\n";
		return 0;
	} else {
        if (!removeDir($dir)) return 0;
    }
    return 1;
}

/*
 * ƺǡ¥Ķե
 */
function removeMaxSizeKansaStat($dir, $size, $type, $err) {
	global $check;
	$stat_dir = $dir . "stat/" . $type . "/";
	$du = getDiskUsage($stat_dir, &$err);
	if ($du === false) return false;
	// MB -> KB
	$size = $size * 1024;
	if ($check) print "[{$type}KansaStatDir(du)]: " . $du . " KB \n";
	while($du > $size) {
		if (removeOldestStat($stat_dir, $type) == 0) {
			break;
		}
		$du = getDiskUsage($stat_dir, &$err);
		if ($du === false) return false;
	}
	return true;
}
/*
 * դָŤ᡼׾ե
 * return: եο
 */
function removeOldestStat($stat_dir) {
	global $check;
    if (!is_dir($stat_dir)) return 0;

    foreach (glob($stat_dir . "*") as $file) {
        if (preg_match("/\/(\d{8})-(\d{6})\.csv$/", $file, $v)) {
            $filelist[] = $file;
            $datelist[] = $v[1];
        }
    }

    // ե뤬ʤ 0 ֤
    if (count($filelist) == 0) return 0;

    // ָŤդ
    sort($datelist);
    $oldest = array_shift($datelist);

    // ָŤդ˥ޥåե
    $count = 0;
    foreach ($filelist as $file) {
        if (preg_match("/\/$oldest-(\d{6})\.csv$/", $file, $v)) {
            if ($check) {
				print "<remove> $file\n";
			} else {
            	if (!su_rm($file)) break;
            	$count++;
			}
        }
    }
	if ($check) return 0;
    else return $count;
}

/*
 * VACUUM ANALYZE
 * ǡ١饹Τ٤ƤΥǡ١ VACUUM ANALYZE ¹Ԥ
 */
function vacuum($err) {

    $vacuumdb = PGSQL_BIN . 'vacuumdb';
    $cmd = sprintf("%s -h %s -U grdndb -a -z", 
                   $vacuumdb, PGSOCKET_DIR);

    exec($cmd, $out, $ret);
    if ($ret != 0) {
        $err = "Cannot VACUUM ANALYZE";
        return false;
    }

    return true;
}

/* ǥ̤μ(KB) */
function getDiskUsage($dir, $err) {
    $cmd = SUEXEC . ' ' . DISK_USAGE . $dir;
    exec($cmd, $out, $rtn);
    if ($rtn != 0) {
        $err = "exec error ($cmd).";
        return false;
    }
    $v = preg_split("/\t+/", $out[0]);
    return trim($v[0]);
}

/**
 * ǡ١å
 */
function getLock() {
    if (!file_exists(DB_LOCKFILE)) {
        if (!su_exec("/bin/touch " . DB_LOCKFILE)) {
            guts_log_err("touch " . DB_LOCKFILE . " at guts_db_maintenance");
            return false;
        }
    }
    if (!su_chown("nobody:nobody", DB_LOCKFILE)) {
        guts_log_err("chown " . DB_LOCKFILE . " at guts_db_maintenance");
        return false;
    }
    if (!su_chmod("644", DB_LOCKFILE)) {
        guts_log_err("chmod " . DB_LOCKFILE . " at guts_db_maintenance");
        return false;
    }
    $fp = @fopen(DB_LOCKFILE, 'w');
    if ($fp === false) {
        guts_log_err("fopen " . DB_LOCKFILE . " at guts_db_maintenance");
        return false;
    }
    $lock = flock($fp, LOCK_EX);    // Ԥ(LOCK_NBʤ)
    if (!$lock) return false;
    return $fp;
}

?>
