diff options
| author | Sadeep Madurange <sadeep@asciimx.com> | 2026-05-06 19:42:33 +0800 |
|---|---|---|
| committer | Sadeep Madurange <sadeep@asciimx.com> | 2026-05-06 19:42:33 +0800 |
| commit | 819bf74c2841fabdcc481e12e13615d48a92cb7f (patch) | |
| tree | 00ba8c9105a96d88536f50f8ef96e838c04408e3 /_site | |
| parent | eddb76ad8c6e850c7e24f97ff27a185d48b104ee (diff) | |
| download | site-search-bm-819bf74c2841fabdcc481e12e13615d48a92cb7f.tar.gz | |
Change directory structure and add benchmark runner.
Diffstat (limited to '_site')
| -rw-r--r-- | _site/cgi-bin/find_file.cgi | 143 | ||||
| -rw-r--r-- | _site/cgi-bin/find_glob.cgi | 147 | ||||
| -rw-r--r-- | _site/cgi-bin/find_one_file.cgi | 184 | ||||
| -rw-r--r-- | _site/cgi-bin/find_sa.cgi | 173 | ||||
| -rw-r--r-- | _site/cgi-bin/find_sa_mmap.cgi | 212 | ||||
| -rw-r--r-- | _site/cgi-bin/indexer.pl | 34 | ||||
| -rw-r--r-- | _site/cgi-bin/sa_indexer.pl | 86 | ||||
| -rwxr-xr-x | _site/cgi-bin/seed.sh | 28 |
8 files changed, 0 insertions, 1007 deletions
diff --git a/_site/cgi-bin/find_file.cgi b/_site/cgi-bin/find_file.cgi deleted file mode 100644 index 2ffb808..0000000 --- a/_site/cgi-bin/find_file.cgi +++ /dev/null @@ -1,143 +0,0 @@ -#!/usr/bin/perl - -use strict; -use warnings; -use File::Find; -use Time::HiRes qw(gettimeofday tv_interval); -use BSD::Resource; # For memory and granular CPU usage - -# 1. Start Benchmark Timer -my $start_time = [gettimeofday]; - -sub escape_html { - my $str = shift; - return "" unless defined $str; - $str =~ s/&/&/g; - $str =~ s/</</g; - $str =~ s/>/>/g; - $str =~ s/"/"/g; - $str =~ s/'/'/g; - return $str; -} - -my %params; -if ($ENV{QUERY_STRING}) { - foreach my $pair (split /&/, $ENV{QUERY_STRING}) { - my ($key, $value) = split /=/, $pair; - $value =~ tr/+/ /; - $value =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg; - $params{$key} = $value; - } -} - -my $search_text = $params{'q'} || ''; -$search_text = substr($search_text, 0, 64); -$search_text =~ s/[^a-zA-Z0-9 ]//g; - -my $directory = '../log/'; -my @results; - -my %excluded_files = ( - 'index.html' => 1, -); - -# Track IO operations (simple count) -my $files_read = 0; - -if ($search_text =~ /\S/) { - find({ - wanted => sub { - return unless -f $_ && $_ eq 'index.html'; - my $rel_path = $File::Find::name; - $rel_path =~ s|^\Q$directory\E/?||; - return if $excluded_files{$rel_path}; - - if (open my $fh, '<', $_) { - $files_read++; # Tracking IO - my $content = do { local $/; <$fh> }; - close $fh; - - if ($content =~ /\Q$search_text\E/i) { - my ($title) = $content =~ /<title>(.*?)<\/title>/is; - $title = $title ? escape_html($title) : $rel_path; - my ($p_content) = $content =~ /<p[^>]*>(.*?)<\/p>/is; - my $snippet = $p_content || ""; - $snippet =~ s/<[^>]*>//g; - $snippet =~ s/\s+/ /g; - - $snippet = escape_html(substr($snippet, 0, 50)); - $snippet .= "..." if length($p_content || "") > 50; - - push @results, { - path => $File::Find::name, - title => $title, - snippet => $snippet - }; - } - } - }, - no_chdir => 0, - follow => 0, - }, $directory); -} - -# --- 2. Calculate Metrics --- -my $end_time = [gettimeofday]; -my $elapsed = tv_interval($start_time, $end_time); - -# CPU & RAM Usage via BSD::Resource -my $rusage = getrusage(); -my $user_cpu = $rusage->utime; # User CPU time -my $system_cpu = $rusage->stime; # System CPU time -my $max_rss = $rusage->maxrss; # Peak RAM (usually in KB on Linux) - -# --- 3. Output --- -print "Content-Type: text/html\n\n"; - -my $list; -if ($search_text eq '') { - $list = "<p>Please enter a search term above.</p>"; -} elsif (@results == 0) { - $list = "<p>No results found for \"<b>$search_text</b>\".</p>"; -} else { - $list = "<ul>"; - foreach my $res (@results) { - my $url = $res->{path}; - $list .= "<li><a href=\"/$url\">$res->{title}</a><br><small>$res->{snippet}</small></li>"; - } - $list .= "</ul>"; -} - -my $safe_search_text = escape_html($search_text); - -print <<"HTML"; -<!DOCTYPE html> -<html lang="en-us"> -<head> - <meta charset="utf-8"> - <title>Search Results</title> - <style> - .stats { background: #f4f4f4; padding: 10px; border-radius: 5px; font-family: monospace; font-size: 0.85em; margin-top: 20px; border: 1px solid #ddd; } - </style> -</head> -<body> - <div class="container"> - <h2>Search</h2> - <form action="" method="GET"> - <input type="text" name="q" value="$safe_search_text"> - <input type="submit" value="Search"> - </form> - $list - - <div class="stats"> - <strong>Performance Metrics:</strong><br> - Total Time: @{[ sprintf("%.4f", $elapsed) ]} seconds<br> - User CPU: $user_cpu s<br> - System CPU: $system_cpu s<br> - Peak RAM: $max_rss KB<br> - Files Read: $files_read (IO Activity) - </div> - </div> -</body> -</html> -HTML diff --git a/_site/cgi-bin/find_glob.cgi b/_site/cgi-bin/find_glob.cgi deleted file mode 100644 index db03bd5..0000000 --- a/_site/cgi-bin/find_glob.cgi +++ /dev/null @@ -1,147 +0,0 @@ -#!/usr/bin/perl - -use strict; -use warnings; -use Encode qw(decode_utf8); -use HTML::Escape qw(escape_html); -use Time::HiRes qw(gettimeofday tv_interval); -use BSD::Resource; - -# 1. Start Benchmark Timer -my $start_time = [gettimeofday]; - -my $search_text = ''; -if ($ENV{QUERY_STRING} && $ENV{QUERY_STRING} =~ /^q=([^&]*)/) { - $search_text = decode_utf8($1 // ""); - $search_text =~ s/\P{Print}//g; - $search_text = substr($search_text, 0, 64); - $search_text =~ s/^\s+|\s+$//g; -} - -my @results; -my $files_read = 0; # Track IO Activity - -my $start_dir = '../log'; -my @files = glob("$start_dir/*/index.html"); - -foreach my $path (@files) { - next if -l $path || ! -f $path; - - # Using :encoding(UTF-8) to handle the valid text files - next unless open(my $fh, "<:encoding(UTF-8)", $path); - $files_read++; - my $html = do { local $/; <$fh> }; - close($fh); - - my ($text) = $html =~ m|<main>(.*?)</main>|is; - $text =~ s|<[^>]+>| |g; - $text =~ s|\s+| |g; - - next unless $text =~ /(.{0,40})(\Q$search_text\E)(.{0,40})/is; - my ($before, $actual, $after) = ($1, $2, $3); - - $after =~ s/\s\S*$// if length($after) > 25; - $before =~ s/^.*?\s// if length($before) > 25; - - if ($before =~ /\S/) { - $before = ucfirst($before); - } else { - $before = ""; - $actual = ucfirst($actual); - } - - my $safe_before = escape_html($before); - my $safe_actual = escape_html($actual); - my $safe_after = escape_html($after); - my $snippet = "${safe_before}<b>${safe_actual}</b>${safe_after}..."; - - my ($title) = $html =~ m|<title>(.*?)</title>|is; - my $safe_title = escape_html($title || "No Title"); - - push @results, { - path => $path, - title => $safe_title, - snippet => $snippet - }; -} - -# 2. Calculate Metrics -my $end_time = [gettimeofday]; -my $elapsed = tv_interval($start_time, $end_time); - -my $rusage = getrusage(); -my $user_cpu = $rusage->utime; -my $system_cpu = $rusage->stime; -my $max_rss = $rusage->maxrss; - -# 3. Output -print "Content-Type: text/html\n\n"; - -my $list; -if ($search_text eq '') { - $list = "<p>Please enter a search term above.</p>"; -} elsif (@results == 0) { - $list = "<p>No results found for \"<b>$search_text</b>\".</p>"; -} else { - $list = "<ul>"; - foreach my $res (@results) { - my $url = $res->{path}; - $list .= "<li><a href=\"/$url\">$res->{title}</a><br><small>$res->{snippet}</small></li>"; - } - $list .= "</ul>"; -} - -my $safe_search_text = escape_html($search_text); -my $year = (localtime)[5] + 1900; - -print <<"HTML"; -<!DOCTYPE html> -<html lang="en-us"> -<head> - <meta charset="utf-8"> - <meta name="viewport" content="width=device-width, initial-scale=1"> - <title>Search</title> - <link rel="stylesheet" href="/assets/css/main.css"> - <link rel="stylesheet" href="/assets/css/skeleton.css"> -</head> -<body> - <div id="nav-container" class="container"> - <ul id="navlist" class="left"> - <li><a href="/" class="link-decor-none">hme</a></li> - <li><a href="/log/" class="link-decor-none">log</a></li> - <li><a href="/projects/" class="link-decor-none">poc</a></li> - <li><a href="/about/" class="link-decor-none">abt</a></li> - <li class="active"><a href="/cgi-bin/find.cgi" class="link-decor-none">sws</a></li> - <li><a href="/feed.xml" class="link-decor-none">rss</a></li> - </ul> - </div> - <main class="container" id="main"> - <div class="container"> - <h2>Search</h2> - <form action="" method="GET"> - <input id="search-box" type="text" name="q" value="$safe_search_text"> - <input id="search-btn" type="submit" value="Search"> - </form> - $list - - <div style="background: #f4f4f4; padding: 10px; border-radius: 5px; font-family: monospace; font-size: 0.85em; margin-top: 20px; border: 1px solid #ddd;"> - <strong>Performance Metrics:</strong><br> - Total Time: @{[ sprintf("%.4f", $elapsed) ]} seconds<br> - User CPU: $user_cpu s<br> - System CPU: $system_cpu s<br> - Peak RAM: $max_rss KB<br> - Files Read: $files_read (IO Activity) - </div> - </div> - </main> - <div class="footer"> - <div class="container"> - <div class="twelve columns right container-2"> - <p id="footer-text">© ASCIIMX - $year</p> - </div> - </div> - </div> -</body> -</html> -HTML - diff --git a/_site/cgi-bin/find_one_file.cgi b/_site/cgi-bin/find_one_file.cgi deleted file mode 100644 index a28f8c4..0000000 --- a/_site/cgi-bin/find_one_file.cgi +++ /dev/null @@ -1,184 +0,0 @@ -#!/usr/bin/perl - -use strict; -use warnings; -use Storable qw(retrieve); -use Encode qw(decode_utf8); -use HTML::Escape qw(escape_html); -use Time::HiRes qw(gettimeofday tv_interval); -use BSD::Resource; - -# 1. Start Benchmark Timer -my $start_time = [gettimeofday]; -my $files_read = 0; # Track IO Activity - -# Configuration -my $max_parallel = 100; -my $lock_timeout = 30; -my $max_results = 1000; -my $min_query_len = 3; -my $index_file = 'search_index.dat'; -my $lock_dir = '/tmp/search_locks'; - -# Concurrency control -mkdir $lock_dir, 0777 unless -d $lock_dir; -my $active_count = 0; -my $now = time(); - -opendir(my $dh, $lock_dir); -while (my $file = readdir($dh)) { - next unless $file =~ /\.lock$/; - my $path = "$lock_dir/$file"; - my $mtime = (stat($path))[9] || 0; - ( $now - $mtime > $lock_timeout ) ? unlink($path) : $active_count++; -} -closedir($dh); - -# Too many search requests -if ($active_count >= $max_parallel) { - print "Content-Type: text/html\n\n"; - render_html("<p>Server busy. Please try again in a few seconds.</p>", "", (localtime)[5]+1900); - exit; -} - -my $lock_file = "$lock_dir/$$.lock"; -open(my $fh_lock, '>', $lock_file); -$files_read++; # IO for lock creation - -my $search_text = ''; -if (($ENV{QUERY_STRING} || '') =~ /^q=([^&]*)/) { - $search_text = decode_utf8($1 // ""); - $search_text =~ s/\P{Print}//g; - $search_text = substr($search_text, 0, 64); - $search_text =~ s/^\s+|\s+$//g; -} - -my $safe_search_text = escape_html($search_text); -my $year = (localtime)[5] + 1900; - -print "Content-Type: text/html\n\n"; - -if ($search_text eq '') { - final_output("<p>Please enter a search term above.</p>"); -} - -if (length($search_text) < $min_query_len) { - final_output("<p>Search term is too short. Please enter at least $min_query_len characters.</p>"); -} - -if (!-f $index_file) { - final_output("<p>Search temporarily unavailable.</p>"); -} - -# IO for index retrieval -my $index = retrieve($index_file); -$files_read++; - -my @results; -my $found = 0; - -foreach my $url (sort keys %$index) { - last if $found >= $max_results; - my $data = $index->{$url}; - - next unless $data->{c} =~ /(.{0,40})(\Q$search_text\E)(.{0,40})/is; - my ($before, $actual, $after) = ($1, $2, $3); - $found++; - - $after =~ s/\s\S*$// if length($after) > 25; - $before =~ s/^.*?\s// if length($before) > 25; - - $before = ($before =~ /\S/) ? ucfirst($before) : ""; - $actual = ($before eq "") ? ucfirst($actual) : $actual; - - my $snippet = escape_html($before) . "<b>" . escape_html($actual) . "</b>" . escape_html($after) . "..."; - - push @results, { - path => $url, - title => escape_html($data->{t}), - snippet => $snippet - }; -} - -my $list_html = ""; -if (@results == 0) { - $list_html = "<p>No results found for \"<b>$safe_search_text</b>\".</p>"; -} else { - $list_html = "<ul>" . join('', map { - "<li><a href=\"/$_->{path}\">$_->{title}</a><br><small>$_->{snippet}</small></li>" - } @results) . "</ul>"; -} - -final_output($list_html); - -sub final_output { - my ($content) = @_; - - # 2. Calculate Metrics just before rendering - my $elapsed = tv_interval($start_time, [gettimeofday]); - my $rusage = getrusage(); - my $user_cpu = $rusage->utime; - my $system_cpu = $rusage->stime; - my $max_rss = $rusage->maxrss; - - my $bench_html = <<"BENCH"; -<div style="background: #f4f4f4; padding: 10px; border-radius: 5px; font-family: monospace; font-size: 0.85em; margin-top: 20px; border: 1px solid #ddd;"> - <strong>Performance Metrics:</strong><br> - Total Time: @{[ sprintf("%.4f", $elapsed) ]} seconds<br> - User CPU: $user_cpu s<br> - System CPU: $system_cpu s<br> - Peak RAM: $max_rss KB<br> - Files Read: $files_read (IO Activity) -</div> -BENCH - - render_html($content . $bench_html, $safe_search_text, $year); - close($fh_lock) if $fh_lock; - unlink($lock_file) if -f $lock_file; - exit; -} - -sub render_html { - my ($content, $q_val, $yr) = @_; - print <<"HTML"; -<!DOCTYPE html> -<html lang="en-us"> -<head> - <meta charset="utf-8"> - <meta name="viewport" content="width=device-width, initial-scale=1"> - <title>Search</title> - <link rel="stylesheet" href="/assets/css/main.css"> - <link rel="stylesheet" href="/assets/css/skeleton.css"> -</head> -<body> - <div id="nav-container" class="container"> - <ul id="navlist" class="left"> - <li><a href="/" class="link-decor-none">hme</a></li> - <li><a href="/log/" class="link-decor-none">log</a></li> - <li><a href="/projects/" class="link-decor-none">poc</a></li> - <li><a href="/about/" class="link-decor-none">abt</a></li> - <li class="active"><a href="/cgi-bin/find.cgi" class="link-decor-none">sws</a></li> - <li><a href="/feed.xml" class="link-decor-none">rss</a></li> - </ul> - </div> - <main class="container" id="main"> - <div class="container"> - <h2>Search</h2> - <form action="" method="GET"> - <input id="search-box" type="text" name="q" value="$q_val"> - <input id="search-btn" type="submit" value="Search"> - </form> - $content - </div> - </main> - <div class="footer"> - <div class="container"> - <div class="twelve columns right container-2"> - <p id="footer-text">© ASCIIMX - $yr</p> - </div> - </div> - </div> -</body> -</html> -HTML -} diff --git a/_site/cgi-bin/find_sa.cgi b/_site/cgi-bin/find_sa.cgi deleted file mode 100644 index 6b608a7..0000000 --- a/_site/cgi-bin/find_sa.cgi +++ /dev/null @@ -1,173 +0,0 @@ -#!/usr/bin/perl - -use strict; -use warnings; -use Storable qw(retrieve); -use Encode qw(decode_utf8); -use HTML::Escape qw(escape_html); -use Time::HiRes qw(gettimeofday tv_interval); -use BSD::Resource; - -# 1. Start Benchmark Timer -my $start_time = [gettimeofday]; -my $files_read = 0; # Track IO Activity - -# Decode search text -my $search_text = ''; -if (($ENV{QUERY_STRING} || '') =~ /^q=([^&]*)/) { - $search_text = decode_utf8($1 // ""); - $search_text =~ s/\P{Print}//g; - $search_text = substr($search_text, 0, 64); - $search_text =~ s/^\s+|\s+$//g; -} - -# We search using lowercase for the case-insensitive index -my $query = lc($search_text); -my $query_len = length($query); -my @results; - -if ($query_len >= 3 && -f 'sa.bin' && -f 'corpus.bin') { - open(my $fh_sa, '<', 'sa.bin') or die $!; - open(my $fh_cp, '<', 'corpus.bin') or die $!; - my $file_map = retrieve('file_map.dat'); - $files_read += 3; - - my $total_suffixes = (-s 'sa.bin') / 4; - - # Helper for binary search comparisons - sub compare_at { - my ($idx, $fh_sa, $fh_cp, $q, $len) = @_; - seek($fh_sa, $idx * 4, 0); - read($fh_sa, my $bin_off, 4); - my $off = unpack("L", $bin_off); - - seek($fh_cp, $off, 0); - read($fh_cp, my $text, $len); - return ($text cmp $q, $off); - } - - # Range Search: Find Left and Right boundaries - my ($low, $high) = (0, $total_suffixes - 1); - my $first_hit = -1; - while ($low <= $high) { - my $mid = int(($low + $high) / 2); - my ($cmp) = compare_at($mid, $fh_sa, $fh_cp, $query, $query_len); - if ($cmp >= 0) { $first_hit = $mid if $cmp == 0; $high = $mid - 1; } - else { $low = $mid + 1; } - } - - if ($first_hit != -1) { - ($low, $high) = ($first_hit, $total_suffixes - 1); - my $last_hit = $first_hit; - while ($low <= $high) { - my $mid = int(($low + $high) / 2); - my ($cmp) = compare_at($mid, $fh_sa, $fh_cp, $query, $query_len); - if ($cmp <= 0) { $last_hit = $mid if $cmp == 0; $low = $mid + 1; } - else { $high = $mid - 1; } - } - - # Collect unique file results - my %seen; - for my $i ($first_hit .. $last_hit) { - my (undef, $offset) = compare_at($i, $fh_sa, $fh_cp, $query, $query_len); - foreach my $m (@$file_map) { - if ($offset >= $m->{start} && $offset < $m->{end}) { - if (!$seen{$m->{path}}++) { - my $snip_start = ($offset - 30 < $m->{start}) ? $m->{start} : $offset - 30; - seek($fh_cp, $snip_start, 0); - read($fh_cp, my $raw_snip, 80); - - push @results, { - path => $m->{path}, - title => "Result: " . (split('/', $m->{path}))[-2], - snippet => "..." . escape_html($raw_snip) . "..." - }; - } - last; - } - } - last if @results >= 20; - } - } - close($fh_sa); - close($fh_cp); -} - -# 2. Calculate Metrics -my $end_time = [gettimeofday]; -my $elapsed = tv_interval($start_time, $end_time); - -my $rusage = getrusage(); -my $user_cpu = $rusage->utime; -my $system_cpu = $rusage->stime; -my $max_rss = $rusage->maxrss; - -# 3. Output -print "Content-Type: text/html\n\n"; - -my $list; -if ($search_text eq '') { - $list = "<p>Please enter a search term above.</p>"; -} elsif (@results == 0) { - $list = "<p>No results found for \"<b>" . escape_html($search_text) . "</b>\".</p>"; -} else { - $list = "<ul>"; - foreach my $res (@results) { - $list .= "<li><a href=\"/$res->{path}\">$res->{title}</a><br><small>$res->{snippet}</small></li>"; - } - $list .= "</ul>"; -} - -my $safe_search_text = escape_html($search_text); -my $year = (localtime)[5] + 1900; - -print <<"HTML"; -<!DOCTYPE html> -<html lang="en-us"> -<head> - <meta charset="utf-8"> - <meta name="viewport" content="width=device-width, initial-scale=1"> - <title>Search</title> - <link rel="stylesheet" href="/assets/css/main.css"> - <link rel="stylesheet" href="/assets/css/skeleton.css"> -</head> -<body> - <div id="nav-container" class="container"> - <ul id="navlist" class="left"> - <li><a href="/" class="link-decor-none">hme</a></li> - <li><a href="/log/" class="link-decor-none">log</a></li> - <li><a href="/projects/" class="link-decor-none">poc</a></li> - <li><a href="/about/" class="link-decor-none">abt</a></li> - <li class="active"><a href="/cgi-bin/find.cgi" class="link-decor-none">sws</a></li> - <li><a href="/feed.xml" class="link-decor-none">rss</a></li> - </ul> - </div> - <main class="container" id="main"> - <div class="container"> - <h2>Search</h2> - <form action="" method="GET"> - <input id="search-box" type="text" name="q" value="$safe_search_text"> - <input id="search-btn" type="submit" value="Search"> - </form> - $list - - <div style="background: #f4f4f4; padding: 10px; border-radius: 5px; font-family: monospace; font-size: 0.85em; margin-top: 20px; border: 1px solid #ddd;"> - <strong>Performance Metrics:</strong><br> - Total Time: @{[ sprintf("%.4f", $elapsed) ]} seconds<br> - User CPU: $user_cpu s<br> - System CPU: $system_cpu s<br> - Peak RAM: $max_rss KB<br> - Files Read: $files_read (IO Activity) - </div> - </div> - </main> - <div class="footer"> - <div class="container"> - <div class="twelve columns right container-2"> - <p id="footer-text">© ASCIIMX - $year</p> - </div> - </div> - </div> -</body> -</html> -HTML diff --git a/_site/cgi-bin/find_sa_mmap.cgi b/_site/cgi-bin/find_sa_mmap.cgi deleted file mode 100644 index 979f4d5..0000000 --- a/_site/cgi-bin/find_sa_mmap.cgi +++ /dev/null @@ -1,212 +0,0 @@ -#!/usr/bin/perl - -use strict; -use warnings; -use Storable qw(retrieve); -use Encode qw(decode_utf8); -use HTML::Escape qw(escape_html); -use Time::HiRes qw(gettimeofday tv_interval); -use BSD::Resource; -use Sys::Mmap; - -my $sa_file = 'sa.bin'; # Suffix Array index -my $cp_file = 'corpus.bin'; # Raw text corpus -my $map_file = 'file_map.dat'; # File metadata - -# 1. Start Benchmark Timer -my $start_time = [gettimeofday]; -my $files_read = 0; # Track IO Activity - -# Decode search text -my $search_text = ''; -if (($ENV{QUERY_STRING} || '') =~ /^q=([^&]*)/) { - $search_text = decode_utf8($1 // ""); - $search_text =~ s/\P{Print}//g; - $search_text = substr($search_text, 0, 64); - $search_text =~ s/^\s+|\s+$//g; -} - -# We search using lowercase for the case-insensitive index -my $query = lc($search_text); -my $query_len = length($query); -my @results; - -if ($query_len >= 3 && -f 'sa.bin' && -f 'corpus.bin') { - open(my $fh_sa, '<', $sa_file) or die $!; - open(my $fh_cp, '<', $cp_file) or die $!; - binmode($fh_sa); - binmode($fh_cp); - - # Memory map files - my ($sa_mapped, $cp_mapped); - mmap($sa_mapped, 0, PROT_READ, MAP_SHARED, $fh_sa) or die "Could not map SA: $!"; - mmap($cp_mapped, 0, PROT_READ, MAP_SHARED, $fh_cp) or die "Could not map Corpus: $!"; - - my $file_map = retrieve($map_file); - $files_read += 3; - my $total_suffixes = (-s $sa_file) / 4; - - # Range Search: Find Left and Right boundaries - my ($low, $high) = (0, $total_suffixes - 1); - my $first_hit = -1; - while ($low <= $high) { - my $mid = int(($low + $high) / 2); - my $off = unpack("L", substr($sa_mapped, $mid * 4, 4)); - my $text = substr($cp_mapped, $off, $query_len); - my $cmp = $text cmp $query; - if ($cmp >= 0) { - $first_hit = $mid if $cmp == 0; - $high = $mid - 1; - } else { - $low = $mid + 1; - } - } - - if ($first_hit != -1) { - ($low, $high) = ($first_hit, $total_suffixes - 1); - my $last_hit = $first_hit; - while ($low <= $high) { - my $mid = int(($low + $high) / 2); - my $off = unpack("L", substr($sa_mapped, $mid * 4, 4)); - my $text = substr($cp_mapped, $off, $query_len); - if (($text cmp $query) <= 0) { - $last_hit = $mid if $text eq $query; - $low = $mid + 1; - } else { - $high = $mid - 1; - } - } - - # Collect unique file results - my %seen; - for my $i ($first_hit .. $last_hit) { - my $offset = unpack("L", substr($sa_mapped, $i * 4, 4)); - foreach my $m (@$file_map) { - if ($offset >= $m->{start} && $offset < $m->{end}) { - if (!$seen{$m->{path}}++) { - # Capture more than 50 chars for trimming - my $snip_start = ($offset - 30 < $m->{start}) ? $m->{start} : $offset - 30; - my $max_len = $m->{end} - $snip_start; - my $read_len = ($max_len > 120) ? 120 : $max_len; - my $raw_snip = substr($cp_mapped, $snip_start, $read_len); - my $snippet = decode_utf8($raw_snip, Encode::FB_QUIET) // $raw_snip; - $snippet =~ s/\s+/ /g; # Normalize whitespace - - # Trim start: Partial word removal - if ($snip_start > $m->{start}) { - $snippet =~ s/^[^\s]*\s//; - } - - # Trim end: Length limit and partial word removal - my $has_more = 0; - if (length($snippet) > 50) { - $snippet = substr($snippet, 0, 50); - $has_more = 1 if $snippet =~ s/\s+[^\s]*$//; - } - elsif ($snip_start + $read_len < $m->{end}) { - # This check handles snippets that are naturally short but - # there's still more text in the article we didn't read - $has_more = 1; - } - - # Cleanup & capitalize - $snippet = ucfirst($snippet); - $snippet = escape_html($snippet) . ($has_more ? "..." : ""); - - my $clean_path = $m->{path}; - $clean_path =~ s|^\.\./_site/||; - - push @results, { - path => $clean_path, - title => $m->{title},, - snippet => $snippet - }; - } - last; - } - } - last if scalar @results >= 1000; - } - } - close($fh_sa); - close($fh_cp); -} - -# 2. Calculate Metrics -my $end_time = [gettimeofday]; -my $elapsed = tv_interval($start_time, $end_time); - -my $rusage = getrusage(); -my $user_cpu = $rusage->utime; -my $system_cpu = $rusage->stime; -my $max_rss = $rusage->maxrss; - -# 3. Output -print "Content-Type: text/html\n\n"; - -my $list; -if ($search_text eq '') { - $list = "<p>Please enter a search term above.</p>"; -} elsif (@results == 0) { - $list = "<p>No results found for \"<b>" . escape_html($search_text) . "</b>\".</p>"; -} else { - $list = "<ul>"; - foreach my $res (@results) { - $list .= "<li><a href=\"/$res->{path}\">$res->{title}</a><br><small>$res->{snippet}</small></li>"; - } - $list .= "</ul>"; -} - -my $safe_search_text = escape_html($search_text); -my $year = (localtime)[5] + 1900; - -print <<"HTML"; -<!DOCTYPE html> -<html lang="en-us"> -<head> - <meta charset="utf-8"> - <meta name="viewport" content="width=device-width, initial-scale=1"> - <title>Search</title> - <link rel="stylesheet" href="/assets/css/main.css"> - <link rel="stylesheet" href="/assets/css/skeleton.css"> -</head> -<body> - <div id="nav-container" class="container"> - <ul id="navlist" class="left"> - <li><a href="/" class="link-decor-none">hme</a></li> - <li><a href="/log/" class="link-decor-none">log</a></li> - <li><a href="/projects/" class="link-decor-none">poc</a></li> - <li><a href="/about/" class="link-decor-none">abt</a></li> - <li class="active"><a href="/cgi-bin/find.cgi" class="link-decor-none">sws</a></li> - <li><a href="/feed.xml" class="link-decor-none">rss</a></li> - </ul> - </div> - <main class="container" id="main"> - <div class="container"> - <h2>Search</h2> - <form action="" method="GET"> - <input id="search-box" type="text" name="q" value="$safe_search_text"> - <input id="search-btn" type="submit" value="Search"> - </form> - $list - - <div style="background: #f4f4f4; padding: 10px; border-radius: 5px; font-family: monospace; font-size: 0.85em; margin-top: 20px; border: 1px solid #ddd;"> - <strong>Performance Metrics:</strong><br> - Total Time: @{[ sprintf("%.4f", $elapsed) ]} seconds<br> - User CPU: $user_cpu s<br> - System CPU: $system_cpu s<br> - Peak RAM: $max_rss KB<br> - Files Read: $files_read (IO Activity) - </div> - </div> - </main> - <div class="footer"> - <div class="container"> - <div class="twelve columns right container-2"> - <p id="footer-text">© ASCIIMX - $year</p> - </div> - </div> - </div> -</body> -</html> -HTML diff --git a/_site/cgi-bin/indexer.pl b/_site/cgi-bin/indexer.pl deleted file mode 100644 index 0dcd7e2..0000000 --- a/_site/cgi-bin/indexer.pl +++ /dev/null @@ -1,34 +0,0 @@ -#!/usr/bin/perl - -use strict; -use warnings; -use Storable qw(nstore); -use HTML::Entities qw(decode_entities); - -# --- Configuration --- -my $built_site_dir = '../log'; -my $output_file = 'search_index.dat'; -my %index; - -print "Building search index from $built_site_dir...\n"; - -foreach my $path (glob("$built_site_dir/*/index.html")) { - next unless open(my $fh, '<:utf8', $path); - my $html = do { local $/; <$fh> }; - close($fh); - - # Extract Title and Main Content - my ($title) = $html =~ m|<title>(.*?)</title>|is || "Unknown"; - my ($main) = $html; - - # Normalize path - my $url = $path; - - $index{$url} = { - t => $title || "Untitled", - c => $main - }; -} - -nstore(\%index, $output_file); -printf("Index complete: %d files (%.2f KB)\n", scalar(keys %index), (-s $output_file) / 1024); diff --git a/_site/cgi-bin/sa_indexer.pl b/_site/cgi-bin/sa_indexer.pl deleted file mode 100644 index 2395dac..0000000 --- a/_site/cgi-bin/sa_indexer.pl +++ /dev/null @@ -1,86 +0,0 @@ -#!/usr/bin/perl - -use strict; -use warnings; -use File::Find; -use Storable qw(store); -use Time::HiRes qw(gettimeofday tv_interval); - -# Configuration -my $directory = '../log'; -my $corpus_file = 'corpus.bin'; -my $sa_file = 'sa.bin'; -my $map_file = 'file_map.dat'; - -# Start timing -my $t0 = [gettimeofday]; - -my $corpus = ""; -my @file_map; - -print "1. Building Case-Insensitive Corpus...\n"; -find({ - wanted => sub { - return unless -f $_ && $_ eq 'index.html'; - if (open my $fh, '<:encoding(UTF-8)', $_) { - my $content = do { local $/; <$fh> }; - close $fh; - - my ($text) = $content =~ m|<main>(.*?)</main>|is; - $text //= $content; - $text =~ s|<[^>]+>| |g; - $text =~ s|\s+| |g; - - my $start = length($corpus); - $corpus .= lc($text) . "\0"; - push @file_map, { start => $start, end => length($corpus), path => $File::Find::name }; - } - }, - no_chdir => 0, -}, $directory); - -print "2. Sorting Suffixes (Two-Pass Cache-Optimized)...\n"; -my @sa = 0 .. (length($corpus) - 1); - -@sa = sort { - (substr($corpus, $a, 64) cmp substr($corpus, $b, 64)) - || - (substr($corpus, $a) cmp substr($corpus, $b)) -} @sa; - -print "3. Writing Index Files to Disk...\n"; -open my $cfh, '>', $corpus_file or die $!; -print $cfh $corpus; -close $cfh; - -open my $sfh, '>', $sa_file or die $!; -binmode($sfh); -print $sfh pack("L*", @sa); -close $sfh; - -store \@file_map, $map_file; - -# End timing -my $elapsed = tv_interval($t0); - -# Calculate Sizes -my $c_size = -s $corpus_file; -my $s_size = -s $sa_file; -my $m_size = -s $map_file; -my $total = $c_size + $s_size + $m_size; - -# --- Final Report --- -print "\n" . "="x35 . "\n"; -print " INDEX BUILDING COMPLETE\n"; -print "="x35 . "\n"; -printf "Total Time: %.4f seconds\n", $elapsed; -print "Files Processed: " . scalar(@file_map) . "\n"; -print "-"x35 . "\n"; -print "File Sizes (KB):\n"; -printf " %-14s %10.2f KB\n", $corpus_file, $c_size / 1024; -printf " %-14s %10.2f KB\n", $sa_file, $s_size / 1024; -printf " %-14s %10.2f KB\n", $map_file, $m_size / 1024; -print "-"x35 . "\n"; -printf " TOTAL INDEX: %10.2f KB\n", $total / 1024; -print "="x35 . "\n"; - diff --git a/_site/cgi-bin/seed.sh b/_site/cgi-bin/seed.sh deleted file mode 100755 index 5ae14df..0000000 --- a/_site/cgi-bin/seed.sh +++ /dev/null @@ -1,28 +0,0 @@ -#!/bin/ksh - -# Set the number of files/dirs -TOTAL=500 -# Approximate size in blocks -BLOCK_SIZE=16 -COUNT=1 - -for i in $(seq 1 $TOTAL); do - # Create a unique directory name - DIR="site_$i" - mkdir -p "$DIR" - - # 1. Generate random valid ASCII (valid UTF-8) text - # We read more from urandom than needed because tr will filter some out - dd if=/dev/urandom bs=1024 count=$BLOCK_SIZE 2>/dev/null | tr -dc 'a-zA-Z0-9 \n' > "$DIR/index.html" - - # 2. Append the necessary HTML structure so your Perl regexes work - # This adds the <title> and <main> tags your script looks for - echo "<html><head><title>Site $i</title></head><body><main><p>Searchable content here for keyword_$i. Lorem ipsum text follows.</p></main></body></html>" >> "$DIR/index.html" - - # Optional: print progress every 100 files - if [ $((i % 100)) -eq 0 ]; then - echo "Created $i files..." - fi -done - -echo "Done! 10000 directories created with valid text." |
