#!/usr/bin/perl use strict; use FindBin qw($Bin); use Getopt::Long; require "$Bin/misc/devlib.pl"; require "$Bin/misc/get_closure.pl"; sub usage { die "Usage: dev-server [--wipe] [--mongo|--mysql|--postgres] [--tls] " . "[--all] [--nobuild] [--staticres] [--offline] [--KBps] " . "[--latency_ms] [--fast] [--verbose] [--hostname] [--compile-js]" . " -- [other_blobserver_opts]"; } chdir $Bin or die; my $opt_KBps = 150; # if non-zero, kBps to throttle connections my $opt_latency_ms = 90; # added latency in millisecond my $opt_fast; # shortcut to disable throttling my $opt_all; # listen on all interfaces my $opt_hostname; # hostname to advertise, else `hostname` is used my $opt_nobuild; my $opt_offline; # don't use the network ("airplane mode") my $opt_staticres; # use static resources, not those on disk my $opt_tls; my $opt_wipe; my $opt_verbose; # keep indexes in memory only. often used with --wipe, but not # necessarily. if --wipe isn't used, all blobs are re-indexed # on start-up. my $opt_memory; my $opt_mongo; my $opt_postgres; my $opt_mysql; GetOptions("wipe" => \$opt_wipe, "tls" => \$opt_tls, "all" => \$opt_all, "nobuild" => \$opt_nobuild, "memory" => \$opt_memory, "mongo" => \$opt_mongo, "postgres" => \$opt_postgres, "mysql" => \$opt_mysql, "staticres" => \$opt_staticres, "offline" => \$opt_offline, "KBps=i" => \$opt_KBps, "latency_ms=i" => \$opt_latency_ms, "fast" => \$opt_fast, "verbose" => \$opt_verbose, "hostname=s" => \$opt_hostname, ) or usage(); $opt_memory = 1 unless $opt_memory || $opt_mongo || $opt_postgres || $opt_mysql; my $port = shift; $port = "3179" unless defined($port); usage() unless $port =~ /^\d+$/; unless ($ENV{GOPATH}) { warn "WARNING: Your GOPATH isn't set; attempting workaround, but you should really set a GOPATH. See https://plus.google.com/106356964679457436995/posts/ftJaqe9sbS2 and make your working directory be \$GOPATH/src/camlistore.org for best results.\n"; $ENV{GOPATH} = "$Bin/gopath" } unless ($opt_fast) { $ENV{DEV_THROTTLE_KBPS} = $opt_KBps; $ENV{DEV_THROTTLE_LATENCY_MS} = $opt_latency_ms; } $ENV{CAMLI_HTTP_DEBUG} = 1 if $opt_verbose; my $camlistored; my $camtool; # closure to return path if ($opt_nobuild) { $camlistored = find_bin("./server/camlistored"); $camtool = sub { scalar find_bin("./cmd/camtool") }; } else { $camlistored = build_bin("./server/camlistored"); $camtool = sub { scalar build_bin("./cmd/camtool") }; } my $root = "/tmp/camliroot-$ENV{USER}/port$port/"; if ($opt_wipe && -d $root) { print "Wiping $root\n"; system("rm", "-rf", $root) and die "Failed to wipe $root.\n"; } my $suffixdir = sub { my $suffix = shift; my $root = "$root/$suffix"; unless (-d $root) { system("mkdir", "-p", $root) and die "Failed to create $root.\n"; } return $root; }; my $DBNAME = "devcamli$ENV{USER}"; my @opts; if ($opt_wipe) { push @opts, "-wipe"; } else { push @opts, "-ignoreexists"; } $ENV{"CAMLI_MYSQL_ENABLED"} = "false"; $ENV{"CAMLI_MONGO_ENABLED"} = "false"; $ENV{"CAMLI_POSTGRES_ENABLED"} = "false"; if ($opt_memory) { $ENV{"CAMLI_INDEXER_PATH"} = "/index-mem/"; } elsif ($opt_mongo) { $ENV{"CAMLI_MONGO_ENABLED"} = "true"; $ENV{"CAMLI_INDEXER_PATH"} = "/index-mongo/"; if ($opt_wipe) { $ENV{"CAMLI_MONGO_WIPE"} = "true"; } else { $ENV{"CAMLI_MONGO_WIPE"} = "false"; } } elsif ($opt_postgres) { $ENV{"CAMLI_POSTGRES_ENABLED"} = "true"; $ENV{"CAMLI_INDEXER_PATH"} = "/index-postgres/"; system($camtool->(), "dbinit", "-postgres", "-user=postgres", "-password=postgres", "-host=localhost", "-dbname=$DBNAME", @opts) and die "Failed to run camtool dbinit.\n"; } else { $ENV{"CAMLI_MYSQL_ENABLED"} = "true"; $ENV{"CAMLI_INDEXER_PATH"} = "/index-mysql/"; system($camtool->(), "dbinit", "-user=root", "-password=root", "-host=localhost", "-dbname=$DBNAME", @opts) and die "Failed to run camtool dbinit.\n"; } my $base = "http://localhost:$port"; my $listen = "127.0.0.1:$port"; if ($opt_all) { $listen = "0.0.0.0:$port"; my $host = $opt_hostname || `hostname`; chomp $host; $base = "http://$host:$port"; } if ($opt_tls) { $base =~ s/^http/https/; } $ENV{CAMLI_TLS} = "false"; if ($opt_tls) { $ENV{CAMLI_TLS} = "true"; } $ENV{CAMLI_BASEURL} = $base; $ENV{CAMLI_AUTH} = "userpass:camlistore:pass$port:+localhost"; $ENV{CAMLI_ADVERTISED_PASSWORD} = "pass$port"; # public password $ENV{CAMLI_ROOT} = $suffixdir->("bs"); $ENV{CAMLI_ROOT_SHARD1} = $suffixdir->("s1"); $ENV{CAMLI_ROOT_SHARD2} = $suffixdir->("s2"); $ENV{CAMLI_ROOT_REPLICA1} = $suffixdir->("r1"); $ENV{CAMLI_ROOT_REPLICA2} = $suffixdir->("r2"); $ENV{CAMLI_ROOT_REPLICA3} = $suffixdir->("r3"); $ENV{CAMLI_ROOT_CACHE} = $suffixdir->("cache"); $ENV{CAMLI_ROOT_ENCMETA} = $suffixdir->("encmeta"); $ENV{CAMLI_ROOT_ENCBLOB} = $suffixdir->("encblob"); $ENV{CAMLI_PORT} = $port; $ENV{CAMLI_SECRET_RING} = "$Bin/pkg/jsonsign/testdata/test-secring.gpg"; $ENV{CAMLI_DBNAME} = $DBNAME; my $templatedir = "$Bin/dev-server-template"; if ($opt_wipe && -d $templatedir) { my $blobs = "$ENV{CAMLI_ROOT}/sha1"; system("cp", "-a", $templatedir, $blobs) and die "Failed to cp template blobs.\n"; } # To use resources from disk, instead of the copies linked into the # binary: unless ($opt_staticres) { unless ($opt_offline) { if (-e "$Bin/tmp/closure-lib/.svn") { system("rm", "-rf", "$Bin/tmp/closure-lib") and die "Failed to remove the svn checkout of the closure-lib.\n"; } get_closure_lib(); get_closure_compiler(); chdir $Bin or die; } $ENV{CAMLI_DEV_CAMLI_ROOT} = $Bin; $ENV{CAMLI_DEV_CLOSURE_ROOT} = "$Bin/tmp/closure-lib"; # TODO: delete CAMLI_DEV_UI_FILES here and in # server/ui/fileembed_normal.go, once ui.go is updated to use # camliRoot. This is just here transitionally: $ENV{CAMLI_DEV_UI_FILES} = "$Bin/server/camlistored/ui"; } print "Starting dev server on $base/ui/ with password \"pass$port\"\n"; exec("$camlistored", "-configfile=$Bin/config/dev-server-config.json", "-listen=$listen", @ARGV); die "exec failure: $!\n";