1#!/usr/bin/perl 2##!~_~perlpath~_~ 3# 4# Interchange database builder and indexer 5# 6# $Id: offline.PL,v 2.7 2007-08-09 13:40:57 pajamian Exp $ 7# 8# Copyright (C) 2002-2007 Interchange Development Group 9# Copyright (C) 1996-2002 Red Hat, Inc. 10# 11# This program was originally based on Vend 0.2 and 0.3 12# Copyright 1995-96 by Andrew M. Wilcox <amw@wilcoxsolutions.com> 13# 14# This program is free software; you can redistribute it and/or modify 15# it under the terms of the GNU General Public License as published by 16# the Free Software Foundation; either version 2 of the License, or 17# (at your option) any later version. 18# 19# This program is distributed in the hope that it will be useful, 20# but WITHOUT ANY WARRANTY; without even the implied warranty of 21# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 22# GNU General Public License for more details. 23# 24# You should have received a copy of the GNU General Public 25# License along with this program; if not, write to the Free 26# Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, 27# MA 02110-1301 USA. 28 29use lib '/usr/local/interchange/lib'; 30#use lib '~_~INSTALLPRIVLIB~_~'; 31use lib '/usr/local/interchange'; 32#use lib '~_~INSTALLARCHLIB~_~'; 33 34use strict; 35use Fcntl; 36use Vend::Util; 37use Vend::Config; 38use Vend::Data; 39use Getopt::Long; 40use Data::Dumper; 41use File::Copy; 42 43$Data::Dumper::Terse = 1; 44$Data::Dumper::Indent = 2; 45 46BEGIN { 47 eval { 48 require 5.004; 49 require FindBin; 50 1 and $Global::VendRoot = $FindBin::RealBin; 51 1 and $Global::VendRoot =~ s/.bin$//; 52 }; 53 ($Global::VendRoot = $ENV{MINIVEND_ROOT}) 54 if defined $ENV{MINIVEND_ROOT}; 55 56 $Global::VendRoot = $Global::VendRoot || '/usr/local/interchange'; 57# $Global::VendRoot = $Global::VendRoot || '~_~INSTALLARCHLIB~_~'; 58 59 if(-f "$Global::VendRoot/interchange.cfg") { 60 $Global::ExeName = 'interchange'; 61 $Global::ConfigFile = 'interchange.cfg'; 62 } 63 elsif(-f "$Global::VendRoot/minivend.cfg") { 64 $Global::ExeName = 'minivend'; 65 $Global::ConfigFile = 'minivend.cfg'; 66 } 67 elsif(-f "$Global::VendRoot/interchange.cfg.dist") { 68 $Global::ExeName = 'interchange'; 69 $Global::ConfigFile = 'interchange.cfg'; 70 } 71} 72 73### END CONFIGURATION VARIABLES 74 75$Global::ErrorFile = "$Global::VendRoot/error.log"; 76$Vend::ExternalProgram = 1; 77 78#select a DBM 79 80BEGIN { 81 82 $ENV{MINIVEND_STORABLE_DB} = 1 if -e "$Global::VendRoot/_db_storable"; 83 $Global::GDBM = $Global::DB_File = $Global::DBI = 0; 84 # Now can use any type of database 85 AUTO: { 86 last AUTO if 87 (defined $ENV{MINIVEND_DBFILE} and $Global::DB_File = 1); 88 last AUTO if 89 (defined $ENV{MINIVEND_NODBM}); 90 eval {require GDBM_File and $Global::GDBM = 1}; 91 last AUTO if 92 (defined $ENV{MINIVEND_GDBM} and $Global::GDBM = 1); 93 eval {require DB_File and $Global::DB_File = 1}; 94 } 95 96 if($Global::GDBM) { 97 require Vend::Table::GDBM; 98 import GDBM_File; 99 $Global::GDBM = 1; 100 $Global::Default_database = 'GDBM' 101 unless defined $Global::Default_database; 102 } 103 if($Global::DB_File) { 104 require Vend::Table::DB_File; 105 import DB_File; 106 $Global::DB_File = 1; 107 $Global::Default_database = 'DB_FILE' 108 unless defined $Global::Default_database; 109 } 110 111 unless($Global::GDBM || $Global::DB_File || $Global::DBI) { 112 die "No DBM or DBI defined! Offline import not necessary.\n"; 113 } 114} 115 116my $USAGE = <<EOF; 117usage: offline -c catalog [-d offline_dir] 118 119If specifying a subcatalog, make sure the databases to be built 120are defined in the subcatalog definition. If they are in the base 121catalog, use that catalog as the parameter for the -c directive. 122EOF 123 124my ($catalog,$directory,$delimiter); 125my (@Catalogs); 126my (@Directories); 127my ($Live, $NoBackup, $Verbose, $BackupExt); 128 129my %optctl = ( 130 catalog => \@Catalogs, 131 directory => \@Directories, 132 live => \$Live, 133 backup => \$BackupExt, 134 verbose => \$Verbose, 135 nobackup => \$NoBackup, 136 ); 137 138my @options = qw( 139 catalog|c=s 140 directory|d=s 141 live|l 142 backup|b=s 143 nobackup|n 144 verbose|v 145 ); 146GetOptions(\%optctl, @options) 147 or die "$@\n\n$USAGE\n"; 148 149$BackupExt = '.bak' unless $BackupExt; 150 151die "$USAGE\n" unless @Catalogs; 152 153chdir $Global::VendRoot; 154 155global_config(); 156 157$| = 1; 158 159foreach my $name (@Catalogs) { 160 my $directory = shift @Directories; 161 my $g = $Global::Catalog{$name}; 162 die "No catalog named $_.\n" 163 unless($g); 164 165 my ($dir, $subconfig) = @{$g}{qw/dir base/}; 166 warn "Probably hard to offline build a subcatalog, but we will try.\n" 167 if $subconfig; 168 chdir $dir or die "Couldn't change directory to $dir: $!\n"; 169 $Vend::Cfg = config($name, $dir, 'config', $subconfig || undef); 170 $::Variable = $Vend::Cfg->{Variable}; 171 chdir $dir or die "Couldn't change directory to $dir: $!\n"; 172 173 my $realprod = $Vend::Cfg->{ProductDir}; 174 $Vend::Cfg->{ProductDir} = $directory || $Vend::Cfg->{OfflineDir}; 175 176 open_database(); 177 178 my $db; 179 my $obj; 180 $Vend::Quiet = 1; 181 foreach $db (keys %{$Vend::Cfg->{Database}}) { 182 # Skip SQL and MEMORY databases 183 my $config = $Vend::Cfg->{Database}->{$db}; 184 next if $config->{Class} =~ /MEMORY|DBI/; 185 print "Checking $db...."; 186 eval { 187 $obj = database_exists_ref($db) 188 or die "Trouble importing $db: $!\n"; 189 $obj = $obj->ref(); 190 }; 191 if($@) { 192 my $msg = "Trouble importing $db: $@\n\n"; 193 if($msg =~ /source.*exist|no.*such.*file/i) { 194 print "no source file, skipping.\n"; 195 next; 196 } 197 $msg .= Dumper($config) if $Verbose; 198 warn "$msg\n"; 199 next; 200 } 201 if($Live) { 202 print "taking $db live...."; 203 my $asc_src = "$config->{dir}/$config->{file}"; 204 my $dbm_src = "$config->{db_file}"; 205 my $asc_targ = "$realprod/$config->{file}"; 206 my $dbm_targ = $dbm_src; 207 $dbm_targ =~ s{^$config->{dir}}{$realprod} 208 or die "Couldn't derive DBM target name.\n"; 209 open(TARG, "+<$asc_targ") 210 or die "Couldn't open ASCII file $asc_targ read/write: $!\n"; 211 lockfile(\*TARG, 1, 1) 212 or die "Couldn't lock ASCII file $asc_targ: $!\n"; 213 open(SRC, "+<$asc_src") 214 or die "Couldn't open ASCII file $asc_src read/write: $!\n"; 215 lockfile(\*SRC, 1, 1) 216 or die "Couldn't lock ASCII file $asc_src: $!\n"; 217 218 #DBM 219 File::Copy::move($dbm_targ, "$dbm_targ$BackupExt") 220 or warn "move $dbm_targ --> $dbm_targ$BackupExt: $!\n" 221 unless $NoBackup; 222 File::Copy::move($dbm_src, $dbm_targ) 223 or die "move $dbm_src --> $dbm_targ: $!\n"; 224 225 my $now = time(); 226 #ASC 227 File::Copy::move($asc_targ, "$asc_targ$BackupExt") 228 or warn "move $asc_targ --> $asc_targ$BackupExt: $!\n" 229 unless $NoBackup; 230 # Possible race condition, but oh well 231 File::Copy::move($asc_src, $asc_targ) 232 or die "move $asc_src --> $asc_targ: $!\n"; 233 utime $now, $now, $asc_targ, $dbm_targ; 234 unlockfile(\*TARG); 235 unlockfile(\*SRC); 236 close SRC; 237 close TARG; 238 } 239 print "done with $db.\n"; 240 } 241 242 close_database(); 243} 244 245=head1 NAME 246 247offline -- Interchange offline database builder 248 249=head1 VERSION 250 251# $Id: offline.PL,v 2.7 2007-08-09 13:40:57 pajamian Exp $ 252 253=head1 DESCRIPTION 254 255Skeleton POD to avoid make errors. 256 257=head1 SEE ALSO 258 259interchange(1), http://www.icdevgroup.org/ 260 261=cut 262