head	1.3;
access;
symbols
	TIGRIS_1_1_0RC2:1.2
	TIGRIS_1_1_0RC1:1.2
	TIGRIS_1_1:1.2.0.14
	TIGRIS_1_0_8:1.2
	TIGRIS_1_0_8RC3:1.2
	TIGRIS_1_0_8RC2:1.2
	TIGRIS_1_0_8RC1:1.2
	TIGRIS_1_0_7:1.2
	TIGRIS_1_0_7RC3:1.2
	TIGRIS_1_0_7RC2:1.2
	TIGRIS_1_0_7RC1:1.2
	TIGRIS_1_0_6:1.2
	TIGRIS_1_0_6RC5:1.2
	TIGRIS_1_0_6RC4:1.2
	TIGRIS_1_0_6RC3:1.2
	TIGRIS_1_0_6RC2:1.2
	TIGRIS_1_0_6RC1:1.2
	TIGRIS_1_0_5:1.2
	TIGRIS_1_0_5RC6:1.2
	TIGRIS_1_0_5RC5:1.2
	TIGRIS_1_0_5RC4:1.2
	TIGRIS_1_0_5RC3:1.2
	TIGRIS_1_0_5RC2:1.2
	TIGRIS_1_0_5RC1:1.2
	TIGRIS_1_0_4:1.2
	TIGRIS_1_0_3:1.2
	TIGRIS_1_0_2:1.2
	TIGRIS_1_0_1:1.2
	TIGRIS_1_0:1.2.0.16
	TIGRIS_1_0_0:1.2
	TIGRIS_1_0_0_RC1:1.2.0.12
	dlr:1.1.1
	TIGRIS_0_9_2_4:1.2
	TIGRIS_0_9_2_3:1.2
	HELM_PEER_PORT_BRANCH:1.1.1.1
	TURBINE_PEER:1.2
	TIGRIS_0_9_2_1:1.2
	TIGRIS_0_9_2:1.2.0.10
	TIGRIS_0_9_0:1.2.0.8
	TIGRIS_0_8_4:1.2.0.6
	NEWHELM:1.1.1.1
	TIGRIS_NOV_12_2000:1.1.1
	OLDHELM:1.2.0.4
	TIGRIS_NOV_11_2000:1.2
	TIGRIS_SEP_13_2000:1.2.0.2
	TIGRIS_BASELINE:1.2;
locks; strict;
comment	@# @;


1.3
date	2001.08.14.21.57.24;	author edk;	state dead;
branches;
next	1.2;

1.2
date	2000.02.03.04.21.34;	author jrobbins;	state Exp;
branches;
next	1.1;

1.1
date	2000.01.30.03.22.37;	author jrobbins;	state Exp;
branches
	1.1.1.1;
next	;

1.1.1.1
date	2000.11.12.21.17.08;	author dlr;	state Exp;
branches;
next	;


desc
@@


1.3
log
@remove obsolete/non-functional scripts
@
text
@# ================================================================
# Copyright (c) 2000 Collab.Net.  All rights reserved.
# 
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met:
# 
# 1. Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# 
# 2. Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
# 
# 3. The end-user documentation included with the redistribution, if
# any, must include the following acknowlegement: "This product includes
# software developed by Collab.Net (http://www.Collab.Net/)."
# Alternately, this acknowlegement may appear in the software itself, if
# and wherever such third-party acknowlegements normally appear.
# 
# 4. The hosted project names must not be used to endorse or promote
# products derived from this software without prior written
# permission. For written permission, please contact info@@collab.net.
# 
# 5. Products derived from this software may not use the "Tigris" name
# nor may "Tigris" appear in their names without prior written
# permission of Collab.Net.
# 
# THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
# WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
# IN NO EVENT SHALL COLLAB.NET OR ITS CONTRIBUTORS BE LIABLE FOR ANY
# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
# GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
# IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
# OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
# ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
# ====================================================================
# 
# This software consists of voluntary contributions made by many
# individuals on behalf of Collab.Net.
#


# Helm/TableSync.pm
# -------------------
# There are a lot of places in Helm where a set of files (or directories
# or something else filesystem-like) is created based on the entries
# of a table. This function makes this behavior generic. It takes care of
# mapping changes in the database to changes in the filesystem.
#
# It does this by keeping a file in the filesystem that keeps track
# of which files are under control of the table, and checking them out
# for each update to that table.

package Helm::TableSync;
require Exporter;
@@ISA = qw(Exporter);

use strict;

# $tablesync = new TableSync $db, $table, $col, $file, \&map_fn, \@@cols
#
# $db: Helm::Database object representing the database
# $table: the table in the database to sync
# \@@cols: the columns to sync on (i.e., the ones that map directly to
#         files, not extra data - see the $xcols parameter later.
# $file: the full path to the table sync file to use (must have write access)
# &map_fn: a function that will map a database name (from a cell)
#          to a fully-qualified filesystem path (i.e., the file). Called as
#          $fs_name = &$map_fn($cookie, $db, $cols_ref); If
#          undef, "$file/../$db_name" is used. $cookie is an opaque option
#          passed to the check, et al, methods.
sub new {
    my $class = shift;
    my $self = {};
    bless $self, $class;
    $self->_initialize(@@_);
    return $self;
}

sub _initialize {
    my $self = shift;
    ($self->{db}, $self->{table}, $self->{cols}, $self->{file},
     $self->{map_fn}) = @@_;

    # Turn a string into a list of one string
    unless (ref $self->{cols}) {
	$self->{cols} = [ $self->{cols} ];
    }
}

# Default mapping function - map $name to $file/../$name
sub _def_map_fn {
    my ($self, $name) = @@_;

    if ($self->{file} =~ m#(^.*/)[^/]+#) {
	return $1 . $name;
    } else {
	die "Illegal file path $self->{file}\n";
    }
}

# Map using the proper map function
sub _map {
    my ($self, $cookie, $cols) = @@_;;

    if ($self->{map_fn}) {
	return &{$self->{map_fn}}($cookie, $self->{db}, $cols);
    } else {
	return $self->_def_map_fn($cols->[0]);
    }
}

# Default delete function - remove the file
sub _def_del_fn {
    my $file = shift;
    unlink $file or die "Could not remove $file: $!\n";
}

# Default add function - put the key into the file
# self->_str_add_fn($row_cols->[0], $filename, $add_key);
sub _str_add_fn {
    my ($self, $row, $filename, $add_key) = @@_;

    open ADD, ">$filename"
	or die "Could not open $filename for writing: $!\n";
    print ADD $add_key ? "$add_key\n" : "\n";
    close ADD;
}

# Default modification function - alter the file if it's changed
# self->_str_mod_fn($row_cols->[0], $filename, $mod_key);
sub _str_mod_fn {
    my ($self, $row, $filename, $mod_key) = @@_;
    my $exist_key;

    open MOD, $filename or die "Could not open $filename: $!\n";
    $exist_key = <MOD>;
    close MOD;

    chomp $exist_key;
    $mod_key ||= "";
    
    if ($exist_key ne $mod_key) {
	# The add code will also overwrite, so we just use it.
	$self->_str_add_fn($row, $filename, $mod_key);
    }
}

# Check the file and database for needed updates.
# This is the main point of TableSync.
#
# $tablesync->check($cookie, \&add_fn, \&del_fn, \&mod_fn, \@@xcols);
#
# The following are all called as
#     &fn($cookie, $db, $cols_ref, $fs_path, [$xcols_ref]);
#
# &add_fn: the function to call when there is a new database row to
#          be created in the filesystem. If, instead of a fn ref, a string
#          is passed, the file will simply be created with the entry
#          from the first listed column in the table of that name for the
#          row.
# &del_fn: the function to call when a row in the database has been
#          deleted (undef to simply delete the file - only for plain files)
# &mod_fn: the function to call when the row and file existed and continue
#          to exist - i.e., the fn can check for changes and make them
#          if necessary. If a string instead of a reference, same semantics
#          as for $add_fn. If undef, nothing is done.
# \@@xcols: reference to a list of column names to be selected from the database
#          and passed on to the functions as list reference $cols_ref, in
#          order, to add_fn and mod_fn (not del_fn, as the database entry
#          no longer exists).

sub check {
    my ($self, $cookie, $add_fn, $del_fn, $mod_fn, $xcols) = @@_;
    my %filedb;
    # temp vars used for three different things, but always a row and
    # a filename. Odd how that works out. Note that sometimes we need
    # a scalar row and sometimes a list. Isn't it nice how Perl's namespace
    # lets us do this?
    my (@@row, $row, $filename);

    # Since we need to compare both lists (file and db) against each
    # other, we need to either read one of them twice or store one in
    # memory. We choose to read the file list into a hash and compare
    # it there against the database. This way is best, especially since
    # we need to re write out the file, which is cleaner (although, in Unix
    # technically just fine) if we're not writing to it at the time.
    if (-e $self->{file}) {
	open FILE, $self->{file} or die "Could not open $self->{file}: $!\n";
	
	while (<FILE>) {
	    next if /^#/;
	    ($filename, @@row) = split ' ';
	    $filedb{$filename} = [ @@row ];
	}
	close FILE;
    }

    # Re-open file to write into it
    open FILE, ">$self->{file}" or die "Could not open $self->{file}: $!\n";
    print FILE "# THIS FILE WAS AUTOMATICALLY GENERATED - DO NOT EDIT\n";
    print FILE "# output from Helm::TableSync for $self->{table}\n";

    # Now scan through the database
    my $statement = "SELECT " . join(',', @@{$self->{cols}});
    $statement .= ",$add_fn" if $add_fn && !(ref $add_fn);
    $statement .= ",$mod_fn" if $mod_fn && !(ref $mod_fn);
    if ($xcols && @@$xcols) {
	$statement .= "," . join(',', @@$xcols);
	foreach (@@$xcols) {
	    $statement .= ",$_";
	}
    }

    $statement .= " FROM $self->{table}";

    my $sth = $self->{db}->dbh->prepare($statement);
    $sth->execute;

    while (@@row = $sth->fetchrow_array) {
	my ($row_cols, $add_key, $mod_key);

	$row_cols = [ splice(@@row, 0, scalar @@{$self->{cols}}) ];
	$add_key = shift @@row if $add_fn && !(ref $add_fn);
	$mod_key = shift @@row if $mod_fn && !(ref $mod_fn);

	# Note that what's left in @@row is the answer to the $xcols

	$filename = $self->_map($cookie, $row_cols);

	if ($filedb{$filename}) {
	    if (ref $mod_fn) {
		&$mod_fn($cookie, $self->{db}, $row_cols, $filename, \@@row);
	    } elsif ($mod_fn) {
		$self->_str_mod_fn($row_cols->[0], $filename, $mod_key);
	    }
	    # Remove the hash index (we sweep up the leftovers below)
	    delete $filedb{$filename};
	} else {
	    if (ref $add_fn) {
		&$add_fn($cookie, $self->{db}, $row_cols, $filename, \@@row);
	    } else {
		$self->_str_add_fn($row_cols->[0], $filename, $add_key);
	    }
	}
	print FILE join(' ', $filename, map { $_ || "" } @@$row_cols), "\n";
    }
    
    close FILE;

    # All rows that are in the database we delete from the hash,
    # so any still left must be removed.
    while (($filename, $row) = each %filedb) {
	if ($del_fn) {
	    &$del_fn($cookie, $self->{db}, $row, $filename);
	} else {
	    &_def_del_fn($filename);
	}
    }
}

# $ts->execute($cookie, \&fn);
#
# Execute some function for each entry of the table. Called as
# &fn($cookie, $db, $db_name, $filename).
sub execute {
    my ($self, $cookie, $fn) = @@_;

    my $sth = $self->{db}->dbh->prepare(
				    "SELECT $self->{col} FROM $self->{table}");
    $sth->execute;

    my $row;
    while ($row = $sth->fetchrow_arrayref) {
	&$fn($cookie, $self->{db}, $row->[0], $self->_map($cookie, $row->[0]));
    }
}

# $ts->delete(\&del_fn, $cookie);
#
# Remove the Helm tablesync file. If the function reference given is
# not undef, it is called first on each entry in the file - not the
# database. The same symantics are used for &del_fn here as in
# check(). If \&del_fn is undefined, the files are simply deleted.
sub del_file {
    my ($self, $del_fn, $cookie) = @@_;

    open FILE, $self->{file} or die "Could not open $self->{file}: $!\n";

    my ($filename, $row);
    while (<FILE>) {
	next if /^#/;
	($filename, $row) = split ' ';
	if ($del_fn) {
	    &$del_fn($cookie, $self->{db}, $row, $filename);
	} else {
	    # Not being able to remove a row-file is not really a fatal
	    # error.
	    unlink $filename or warn "Could not delete $filename: $!\n";
	}
    }
    close FILE;

    # Not being able to remove the table-file is.
    unlink $self->{file} or die "Could not delete $self->{file}: $!\n";
}
@


1.2
log
@Added tigris.org license
PR:
Obtained from:
Submitted by:
Reviewed by:
@
text
@@


1.1
log
@initial checkin
@
text
@d1 46
a46 1
# Copyright (c) 2000 Collab.Net, Inc.
@


1.1.1.1
log
@Merging newhelm tree into helm, as per IZ issue #557.  Previous major version of helm is tagged TIGRIS_NOV_11_2000.
@
text
@d1 1
a1 46
# ================================================================
# Copyright (c) 2000 Collab.Net.  All rights reserved.
# 
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met:
# 
# 1. Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# 
# 2. Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
# 
# 3. The end-user documentation included with the redistribution, if
# any, must include the following acknowlegement: "This product includes
# software developed by Collab.Net (http://www.Collab.Net/)."
# Alternately, this acknowlegement may appear in the software itself, if
# and wherever such third-party acknowlegements normally appear.
# 
# 4. The hosted project names must not be used to endorse or promote
# products derived from this software without prior written
# permission. For written permission, please contact info@@collab.net.
# 
# 5. Products derived from this software may not use the "Tigris" name
# nor may "Tigris" appear in their names without prior written
# permission of Collab.Net.
# 
# THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
# WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
# IN NO EVENT SHALL COLLAB.NET OR ITS CONTRIBUTORS BE LIABLE FOR ANY
# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
# GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
# IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
# OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
# ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
# ====================================================================
# 
# This software consists of voluntary contributions made by many
# individuals on behalf of Collab.Net.
#

@


