Package: vim
Version: 2:7.3.035+hg~8fdc12103333-1
Severity: normal

Recently (in the past half year or so), editing perl code in vim has begun to
drag horribly. There are sometimes pauses of many seconds, and often vim
responds as if it were on the other side of a transatlantic link.

I commented out perl_fold=1 in my vimrc and this went away.

I have attached enough vimrc to see it, and a sample perl file. I don't think 
there's anything special about this file; I've seen the slowdown in 
many different files. Open the file, then:

/early
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

You should see what I mean; each character deleted takes enough time to
feel painfully slow when the action is repeated.

Seems likely it is reprocessing the whole file for folds after each
modification.

-- System Information:
Debian Release: wheezy/sid
  APT prefers unstable
  APT policy: (500, 'unstable'), (1, 'experimental')
Architecture: i386 (i686)

Kernel: Linux 2.6.32-5-686 (SMP w/2 CPU cores)
Locale: LANG=en_US.UTF-8, LC_CTYPE=en_US.UTF-8 (charmap=UTF-8)
Shell: /bin/sh linked to /bin/dash

Versions of packages vim depends on:
ii  libacl1      2.2.49-4                    Access control list shared library
ii  libc6        2.11.2-11                   Embedded GNU C Library: Shared lib
ii  libgpm2      1.20.4-3.3                  General Purpose Mouse - shared lib
ii  libncurses5  5.8+20110307-1              shared libraries for terminal hand
ii  libselinux1  2.0.98-1                    SELinux runtime shared libraries
ii  vim-common   2:7.3.035+hg~8fdc12103333-1 Vi IMproved - Common files
ii  vim-runtime  2:7.3.035+hg~8fdc12103333-1 Vi IMproved - Runtime files

vim recommends no packages.

Versions of packages vim suggests:
pn  ctags                         <none>     (no description available)
pn  vim-doc                       <none>     (no description available)
pn  vim-scripts                   <none>     (no description available)

-- no debconf information

-- 
see shy jo
#!/usr/bin/perl
# Allows do=makesite to be used to create a new site, and do=branchsite
# to branch an existing site.
#
# Should only be enabled on the controlsite.
package IkiWiki::Plugin::makesite;

use warnings;
use strict;
use IkiWiki 3.00;
use IkiWiki::Hosting;
use IkiWiki::Business;
use HTML::Entities;

our $DNS_READY=1;
our $DNS_NEEDED=2;
our $DNS_WRONG=3;

my @themes=(
	{name => "none",        description => "Simple"},
	{name => "blueview",    description => "BlueView"},
	{name => "actiontabs",  description => "ActionTabs"},
	{name => "goldtype",    description => "GoldType"},
);

sub import {
	hook(type => "sessioncgi", id => "makesite", call => \&sessioncgi);
}

sub sessioncgi ($$) {
	my $cgi=shift;
	my $session=shift;

	return unless defined $cgi->param("do");
	
	if ($cgi->param("do") eq "makesite") {
		makesite($cgi, $session);
	}
	elsif ($cgi->param("do") eq "branchsite") {
		makesite($cgi, $session, 1);
	}
}

sub makesite ($$;$) {
	my $cgi=shift;
	my $session=shift;
	my $branching=shift;

	IkiWiki::needsignin($cgi, $session);

	# Drop ikiwiki lock to avoid blocking other users during site
	# creation.
	IkiWiki::unlockwiki();

	# Only openid logins are supported.
	my $openid=$session->param("name");
	if (! defined IkiWiki::openiduser($session->param("name"))) {
		error "not logged in using openid"
	}

	my $internal_branchof;
	if ($branching) {
		$internal_branchof=$cgi->param("branchof");

		my $branchable=IkiWiki::Hosting::getshell("ikisite",
			"getsetup", $internal_branchof, "branchable");
		if (! $branchable) {
			my $admins=IkiWiki::Hosting::yamlgetshell("ikisite",
				"getsetup", $internal_branchof, "adminuser");
			if (! ref $admins ||
			    ! grep { $_ eq $session->param("name") } @$admins) {
				error "You are not allowed to branch this site.";
			}
		}
	}
	
	# Get values from form and validate.
	my ($dns_state, $internal_hostname,
	    $external_hostname, $wikiname, @alias) =
		gen_hostnames($cgi->param("hostname"),
			$cgi->param("domain"),
			$cgi->param("internal_hostname"));
	my $type=lc($cgi->param("type")) if defined $cgi->param("type");
	my $nonce=$cgi->param("nonce");
	my $creating=$cgi->param("creating");
	my $ready=$cgi->param("ready");
	my $site_theme=$cgi->param("site_theme");
	my $dns_ok=1 if (($dns_state == $DNS_READY) || $cgi->param("submit_nodns"));
	# The session may have an email address, taken from openid.
	my $email=$session->param("email");
	if (defined $cgi->param("email")) {
		$email=$cgi->param("email");
	}
	else {
		eval q{use IkiWiki::Customer};
		error $@ if $@;
		$email=IkiWiki::Customer::customer_get($openid, "email");
	}
	if (defined $email) {
		eval q{use Email::Address};
		if (! $@) {
			# This email address parser should be fully RFC822
			# compliant,  and can even extract email addresses
			# out of longer strings.
			# (But no check is done that the domain is valid.)
			$email = (Email::Address->parse($email))[0];
		}
		else {
			# Most stupid fallback imaginable.
			($email) = $email=~/(.*@.*)/;
		}
		$email=undef unless defined $email && length $email;
	}

	my $acceptplan=$cgi->param("acceptplan");
	my $newplan=undef;
	if (! IkiWiki::Business::needchangeplan($openid, $internal_hostname)) {
		$acceptplan=1;
	}
	else {
		# Determine price plan. For now, the user doesn't choose a
		# plan, but is just set to the cheapest plan suitable for
		# the sites they have plus the one we're making.
		$newplan=IkiWiki::Business::suggestedplan($openid, $internal_hostname);
		if (defined $cgi->param("suggestedplan") &&
		    $cgi->param("suggestedplan") ne $newplan) {
			# User accepted previously suggested plan,
			# but it's changed somehow.
			$acceptplan=0;
		}
	}

	# Since site creation takes a while, it will be done in the
	# background, while the user is presented with a setup screen.
	if (! $ready && ! $creating) {
		$creating=1;

		# Precalculate a nonce to use when the site is
		# created. This allows it to be modified to
		# finalize its setup later.
		$nonce=time().':'.`uuid -v4`;
		chomp $nonce;
			
		my $pid=IkiWiki::Hosting::daemonize();
		if (!$pid) {
			# Now we're a daemon..
			my @action=("create", $internal_hostname);
			if (defined $internal_branchof) {
				@action=("branch", $internal_branchof, $internal_hostname);
			}
			$ENV{IKISITE_NONCE}=$nonce;
			IkiWiki::Hosting::getshell("ikisite-wrapper",
				@action,
				"--owner=$openid",
				"--admin=http://none/";, # temporary admin until setup finishes
				"--wikiname=$wikiname",
				"--createnonce",
				((defined $type && length $type) ? "--type=$type" : ()),
				((defined $email && length $email) ? "--adminemail=$email" : ()),
				);
			if ($? != 0) {
				error sprintf("failure creating %s",	
					encode_entities($internal_hostname));
			}
			else {
				exit(0);
			}
		}
	}
	else {
		# If all required user input is done, just wait for the
		# background site creation to finish.
		my $canwait=$acceptplan && $dns_ok && defined $email;

		# Check if background site creation is done by checking if
		# the site exists and is no longer locked. 
		IkiWiki::Hosting::getshell("ikisite-wrapper", "checklock", $internal_hostname,
			($canwait ? "--wait" : ()));
		if ($? == 0) {
			# If site creation failed (ie, ikiwiki crashed),
			# the nonce file will not exist.
			if (! -e "/.ikisite-nonce") {
				error sprintf("failure creating %s (late term)",
					encode_entities($internal_hostname));
			}
			$creating=0;
			$ready=1;
		}
		elsif ($canwait) {
			# Only way checklock --wait can fail is if the
			# site doesn't exist.
			error sprintf("failure creating %s (term)",	
				encode_entities($internal_hostname));
		}
	}

	# Modify site, setting alias and/or external hostname.
	if ($ready && ! $creating && $acceptplan && defined $email &&
	    ((@alias || ($dns_state == $DNS_READY && defined $external_hostname)))) {
		$ENV{IKISITE_NONCE}=$nonce;
		# This rebuilds the site; pretty slow. But, not as slow as
		# site creation, so I have not tried to background it yet.
		IkiWiki::Hosting::getshell("ikisite-wrapper", "domains", $internal_hostname,
			(($dns_state == $DNS_READY && defined $external_hostname) ? "--external=$external_hostname" : ()),
			map { "--alias=$_" } @alias,
		);
		if ($dns_state == $DNS_READY && defined $external_hostname && $? != 0) {
			# Above can fail, if the DNS is not set right etc.
			$dns_state=$DNS_NEEDED 
		}
	}

	# Record when a customer signs up.
	if ($acceptplan && defined $email) {
		eval q{use IkiWiki::Customer};
		error $@ if $@;
		IkiWiki::Customer::customer_lock_write($openid, sub {
			IkiWiki::Customer::customer_set($openid, "currentplan", $newplan)
				if defined $newplan;
			IkiWiki::Customer::customer_set($openid, "email", $email);
			# Ikiwiki also collect a nickname from openid.
			# (We'd rather have a full name, but it will do.)
			# Avoid overwriting name if it's already set, as
			# the value from openid is not very good.
			if (defined $session->param("nickname") &&
			    ! defined IkiWiki::Customer::customer_get($openid, "name")) {
				IkiWiki::Customer::customer_set($openid, "name",
					$session->param("nickname"));
			}
			my %emails=map { $_ => 1 } (IkiWiki::Customer::customer_get($openid, "email_list"), $email);
			IkiWiki::Customer::customer_set($openid, "email_list", keys %emails);
			my %openids=map { $_ => 1 } IkiWiki::Customer::openid_list($openid);
			IkiWiki::Customer::customer_set($openid, "openid_list", keys %openids);
			my $startdate=IkiWiki::Customer::customer_get($openid, "startdate");
			if (! defined $startdate || $startdate == 0) {
				IkiWiki::Customer::customer_set($openid, "startdate", time);
			}
			my $balance=IkiWiki::Customer::customer_get($openid, "balance");
			if (! defined $balance) {
				IkiWiki::Customer::customer_set($openid, "balance", 0);
			}
			IkiWiki::Customer::customer_commit($openid);
		});
	}
	
	# Redirect to newly created site once everything is ok.
	if ($ready && ! $creating && $acceptplan && defined $email && $dns_ok) {
		# But first, save the email address, which may have been
		# changed since site creation was started. And set the
		# openid as the site admin  now that they have signed up.
		# And if a theme was selected, set it.
		$ENV{IKISITE_NONCE}=$nonce;
		eval q{use YAML::Syck};
		die $@ if $@;
		IkiWiki::Hosting::getshell("ikisite-wrapper", "changesetup",
			$internal_hostname, "--set", "adminemail=$email",
			"--set-yaml", "adminuser=".Dump([$openid]),
			((defined $site_theme && length $site_theme &&
			  $site_theme ne "none")
				? ("--set", "theme=$site_theme") : ()),
		);

		my $redir_url;
		if (defined $external_hostname && $dns_state == $DNS_READY) {
			$redir_url="http://$external_hostname/";;
		}
		else {
			$redir_url="http://$internal_hostname/";;
		}

		if (! $branching) {
			IkiWiki::Hosting::readconfig();
			my $r=$config{"welcome_redir_$type"} || $config{"welcome_redir"};
			$redir_url.=$r if defined $r;
		}

		IkiWiki::redirect($cgi, $redir_url);
		
		# Setup complete; nonce no longer needed.
		if (defined $nonce && length $nonce) {
			IkiWiki::Hosting::getshell("ikisite-wrapper", "deletenonce",
				$internal_hostname, "--nonce=$nonce");
		}
		exit(0);
	}

	# Display site setup screen.
	my $template=IkiWiki::Hosting::ikisite_template("makesite.tmpl");

	# If necessary prompt user to set up DNS for their site.
	# FIXME: It would be better if the user logged in as admin to their
	# new site, and finished the DNS setup in there, rather than
	# it all happening in here. But that needs openid singlesignin
	# for the user to not have to manually login, so I hacked this
	# into here in the meantime.
	if ($dns_state == $DNS_NEEDED) {
		$template->param(dns_needed => 1);
	}
	elsif ($dns_state == $DNS_WRONG) {
		$template->param(dns_wrong => 1);
	}
	else {
		$template->param(dns_ok => 1);
	}

	$template->param(wikiname => $wikiname);
	$template->param(hostname => $cgi->param("hostname"));
	$template->param(domain => $cgi->param("domain"));
	$template->param(internal_hostname => $internal_hostname);
	$template->param(external_hostname => $external_hostname);
	$template->param(nonce => $nonce) if length $nonce;
	$template->param(creating => $creating);
	$template->param(ready => $ready);
	$template->param(retried => 1) if $cgi->param("retry");
	$template->param(type => $type) if defined $type;
	$template->param(branching => 1) if $branching;
	$template->param(branchof => $internal_branchof) if $branching;
	if (defined $newplan) {
		$template->param(suggestedplan => $newplan);
		$template->param(suggestedplan_description =>
			IkiWiki::Business::planinfo($newplan)->{description});
		$template->param(suggestedplan_name =>
			IkiWiki::Business::planinfo($newplan)->{name});
		my $trial=IkiWiki::Business::planinfo($newplan)->{monthsfreetrial};
		$template->param(suggestedplan_monthsfreetrial => $trial)
			if $trial;
	}
	$template->param(acceptplan => $acceptplan ? 1 : 0);
	if (! $acceptplan && $cgi->param("retry")) {
		$template->param(acceptplan_error => "Required");
	}
	if (defined $site_theme && length $site_theme) {
		$template->param(site_theme => $site_theme);
	}
	else {
		$template->param(themes => [
			# Add type parameter to theme list to allow
			# links to example sites of the right type.
			map {
				$_->{type}=defined $type ? $type : "wiki";
				$_;
			} @themes
		]);
	}
	if (defined $email && $acceptplan) {
		$template->param(billing_ok => 1);
	}
	if (defined $email) {
		$template->param(email => $email);
	}
	else {
		$template->param(email_error => "Required");
	}
	
	IkiWiki::printheader($session);
	print IkiWiki::cgitemplate($cgi, "site setup", $template->output);
	exit(0);
}

sub unique_internal_hostname {
	my ($base, $defaultdomain)=@_;

	my $counter=0;
	while (1) {
		my $try=$base.($counter ? ($counter+1) : "").".".$defaultdomain;
		# ikisite sitexists does not need to run as root
		IkiWiki::Hosting::getshell("ikisite", "siteexists",  $try);
		if ($? == 0) {
			$counter++;
		}
		elsif ($? == 255) {
			# 255 is what ikisite siteexists throws on data validation error
			error sprintf("not allowed to use domain name %s",
				encode_entities($base));
		}
		else {
			return $try;
		}
	}
}

sub gen_hostnames {
	# The "hostname" can be any of: A FQDN, a hostname under
	# the defaultdomain, or a wikiname. From this, derive an internal
	# hostname, an external hostname and other aliases, and look up
	# dns state.
	#
	# If an internal hostname has already been allocated, it can
	# optionally be provided.
	my ($hostname, $defaultdomain, $internal_hostname, $force_www)=@_;
	
	my $orig_hostname=$hostname;

	my ($dns_state, $external_hostname, $wikiname, @alias);

	# ikisite validates all data later, but early cleanup and validation
	# of user-supplied data allows nicer error messages.
	$hostname =~ s/^\s+//;
	$hostname =~ s/\s+$//;
	my $www_stripped=($hostname =~ s/^www\.//i) unless $force_www;
	$wikiname=$hostname;
	$wikiname=~s/^([^.]+).*/$1/;
	$hostname=lc($hostname);
	$defaultdomain=lc($defaultdomain);
	if (! length $hostname) {
		error "hostname not set";
	}
	if (! length $defaultdomain) {
		error "empty defaultdomain";
	}
	$hostname =~ s/(^|\.)\Q$defaultdomain\E$//;
	if (! length $hostname) {
		error "illegal hostname";
	}
	$defaultdomain =~ s/[^-.a-z0-9]//g;
	if (! length $defaultdomain) {
		error "illegal defaultdomain";
	}

	if (! defined $internal_hostname) {
		# Base internal hostname on what the user entered, but with
		# anything problimatic munged. If they entered a FQDN like
		# example.com, it will be example-com. A wikiname of "My Wiki"
		# will yield mywiki.
		my $base=$hostname;
		$base =~ s/\./-/g;
		$base =~ s/[^-a-z0-9]//g;
		if (! length $base) {
			error "illegal hostname";
		}

		$internal_hostname=unique_internal_hostname($base, $defaultdomain);
	}

	my $address=IkiWiki::Hosting::host_address_or_cname($hostname, $internal_hostname);
	if (defined $address && ($address eq $internal_hostname ||
	    grep { $_ eq $address } IkiWiki::Hosting::site_addresses())) {
		# Hostname already exists, and its address is already
		# pointed at internal_hostname.
		$external_hostname=$hostname;
		$dns_state=$DNS_READY;
	}
	elsif (defined $address) {
		# Hostname already exists, addresss is not set right.
		$external_hostname=$hostname;
		$dns_state=$DNS_WRONG;
	}
	elsif ($hostname=~/([^.]+)\.(.+)$/ &&
	       defined IkiWiki::Hosting::host_address_or_cname($2)) {
		# Hostname does not exist, but looks like it was intended
		# to be a DNS address under a domain that has DNS
		$external_hostname=$hostname;
		$dns_state=$DNS_NEEDED;
	}
	elsif ($hostname=~/(.+)\.\w+$/) {
		# Hostname does not exist, but it seems to be a DNS address
		# with a TLD.
		$external_hostname=$hostname;
		$dns_state=$DNS_NEEDED;
	}
	else {
		# No separate external hostname.
		$external_hostname=undef;
		$dns_state=$DNS_READY;
	}

	if ($www_stripped && $dns_state != $DNS_READY) {
		# Retry without stripping www, just in case
		# www.hostname.com is set up right and hostname.com is not.
		my ($dns_state2, @rest) = gen_hostnames(
			$orig_hostname, $defaultdomain, $internal_hostname, 1);
		if ($dns_state2 == $DNS_READY) {
			return ($dns_state2, @rest);
		}
	}

	if ($www_stripped) {
		@alias=$external_hostname;
		$external_hostname="www.$external_hostname";
	}
	else {
		push @alias, "www.$external_hostname" if defined $external_hostname;
	}

	return ($dns_state, $internal_hostname,
		$external_hostname, $wikiname, @alias);
}

1
syntax on
let perl_fold=1 " slow!!
let perl_nofold_packages=1

Attachment: signature.asc
Description: Digital signature

Reply via email to