… | |
… | |
665 | _attach $registry, $klass, @attach; |
665 | _attach $registry, $klass, @attach; |
666 | } |
666 | } |
667 | |
667 | |
668 | $obj->{$name} = \%arg; |
668 | $obj->{$name} = \%arg; |
669 | } else { |
669 | } else { |
670 | warn "object uses attachment '$name' that is not available, postponing.\n"; |
670 | warn "object uses attachment '$name' which is not available, postponing.\n"; |
671 | } |
671 | } |
672 | |
672 | |
673 | $obj->{_attachment}{$name} = undef; |
673 | $obj->{_attachment}{$name} = undef; |
674 | } |
674 | } |
675 | |
675 | |
… | |
… | |
943 | |
943 | |
944 | cf::override; |
944 | cf::override; |
945 | }, |
945 | }, |
946 | ); |
946 | ); |
947 | |
947 | |
948 | sub load_extension { |
|
|
949 | my ($path) = @_; |
|
|
950 | |
|
|
951 | $path =~ /([^\/\\]+)\.ext$/ or die "$path"; |
|
|
952 | my $base = $1; |
|
|
953 | my $pkg = $1; |
|
|
954 | $pkg =~ s/[^[:word:]]/_/g; |
|
|
955 | $pkg = "ext::$pkg"; |
|
|
956 | |
|
|
957 | warn "... loading '$path' into '$pkg'\n"; |
|
|
958 | |
|
|
959 | open my $fh, "<:utf8", $path |
|
|
960 | or die "$path: $!"; |
|
|
961 | |
|
|
962 | my $source = |
|
|
963 | "package $pkg; use strict; use utf8;\n" |
|
|
964 | . "#line 1 \"$path\"\n{\n" |
|
|
965 | . (do { local $/; <$fh> }) |
|
|
966 | . "\n};\n1"; |
|
|
967 | |
|
|
968 | unless (eval $source) { |
|
|
969 | my $msg = $@ ? "$path: $@\n" |
|
|
970 | : "extension disabled.\n"; |
|
|
971 | if ($source =~ /^#!.*perl.*#.*MANDATORY/m) { # ugly match |
|
|
972 | warn $@; |
|
|
973 | warn "mandatory extension failed to load, exiting.\n"; |
|
|
974 | exit 1; |
|
|
975 | } |
|
|
976 | die $@; |
|
|
977 | } |
|
|
978 | |
|
|
979 | push @EXTS, $pkg; |
|
|
980 | } |
|
|
981 | |
|
|
982 | sub load_extensions { |
948 | sub load_extensions { |
|
|
949 | cf::sync_job { |
|
|
950 | my %todo; |
|
|
951 | |
983 | for my $ext (<$LIBDIR/*.ext>) { |
952 | for my $path (<$LIBDIR/*.ext>) { |
984 | next unless -r $ext; |
953 | next unless -r $path; |
985 | eval { |
954 | |
986 | load_extension $ext; |
955 | $path =~ /([^\/\\]+)\.ext$/ or die "$path"; |
|
|
956 | my $base = $1; |
|
|
957 | my $pkg = $1; |
|
|
958 | $pkg =~ s/[^[:word:]]/_/g; |
|
|
959 | $pkg = "ext::$pkg"; |
|
|
960 | |
|
|
961 | open my $fh, "<:utf8", $path |
|
|
962 | or die "$path: $!"; |
|
|
963 | |
|
|
964 | my $source = do { local $/; <$fh> }; |
|
|
965 | |
|
|
966 | my %ext = ( |
|
|
967 | path => $path, |
|
|
968 | base => $base, |
|
|
969 | pkg => $pkg, |
|
|
970 | ); |
|
|
971 | |
|
|
972 | $ext{meta} = { map { (split /=/, $_, 2)[0, 1] } split /\s+/, $1 } |
|
|
973 | if $source =~ /\A#!.*?perl.*?#\s*(.*)$/m; |
|
|
974 | |
|
|
975 | $ext{source} = |
|
|
976 | "package $pkg; use strict; use utf8;\n" |
|
|
977 | . "#line 1 \"$path\"\n{\n" |
|
|
978 | . $source |
|
|
979 | . "\n};\n1"; |
|
|
980 | |
|
|
981 | $todo{$base} = \%ext; |
|
|
982 | } |
|
|
983 | |
|
|
984 | my %done; |
|
|
985 | while (%todo) { |
|
|
986 | my $progress; |
|
|
987 | |
|
|
988 | while (my ($k, $v) = each %todo) { |
|
|
989 | for (split /,\s*/, $v->{meta}{depends}) { |
|
|
990 | goto skip |
|
|
991 | unless exists $done{$_}; |
|
|
992 | } |
|
|
993 | |
|
|
994 | warn "... loading '$k' into '$v->{pkg}'\n"; |
|
|
995 | |
|
|
996 | unless (eval $v->{source}) { |
|
|
997 | my $msg = $@ ? "$v->{path}: $@\n" |
|
|
998 | : "$v->{base}: extension inactive.\n"; |
|
|
999 | |
|
|
1000 | if (exists $v->{meta}{mandatory}) { |
|
|
1001 | warn $msg; |
|
|
1002 | warn "mandatory extension failed to load, exiting.\n"; |
|
|
1003 | exit 1; |
|
|
1004 | } |
|
|
1005 | |
|
|
1006 | warn $msg; |
|
|
1007 | } |
|
|
1008 | |
|
|
1009 | $done{$k} = delete $todo{$k}; |
|
|
1010 | push @EXTS, $v->{pkg}; |
|
|
1011 | $progress = 1; |
987 | 1 |
1012 | } |
988 | } or warn "$ext not loaded: $@"; |
1013 | |
|
|
1014 | skip: |
|
|
1015 | die "cannot load " . (join ", ", keys %todo) . ": unable to resolve dependencies\n" |
|
|
1016 | unless $progress; |
|
|
1017 | } |
989 | } |
1018 | }; |
990 | } |
1019 | } |
991 | |
1020 | |
992 | ############################################################################# |
1021 | ############################################################################# |
993 | |
1022 | |
994 | =head2 CORE EXTENSIONS |
1023 | =head2 CORE EXTENSIONS |
… | |
… | |
1776 | $cf::MAP{$self->path} = $self; |
1805 | $cf::MAP{$self->path} = $self; |
1777 | |
1806 | |
1778 | $self->reset; # polite request, might not happen |
1807 | $self->reset; # polite request, might not happen |
1779 | } |
1808 | } |
1780 | |
1809 | |
|
|
1810 | =item $maps = cf::map::tmp_maps |
|
|
1811 | |
|
|
1812 | Returns an arrayref with all map paths of currently instantiated and saved |
|
|
1813 | maps. May block. |
|
|
1814 | |
|
|
1815 | =cut |
|
|
1816 | |
|
|
1817 | sub tmp_maps() { |
|
|
1818 | [ |
|
|
1819 | map { |
|
|
1820 | utf8::decode $_; |
|
|
1821 | /\.map$/ |
|
|
1822 | ? normalise $_ |
|
|
1823 | : () |
|
|
1824 | } @{ aio_readdir $TMPDIR or [] } |
|
|
1825 | ] |
|
|
1826 | } |
|
|
1827 | |
|
|
1828 | =item $maps = cf::map::random_maps |
|
|
1829 | |
|
|
1830 | Returns an arrayref with all map paths of currently instantiated and saved |
|
|
1831 | random maps. May block. |
|
|
1832 | |
|
|
1833 | =cut |
|
|
1834 | |
|
|
1835 | sub random_maps() { |
|
|
1836 | [ |
|
|
1837 | map { |
|
|
1838 | utf8::decode $_; |
|
|
1839 | /\.map$/ |
|
|
1840 | ? normalise "?random/$_" |
|
|
1841 | : () |
|
|
1842 | } @{ aio_readdir $RANDOMDIR or [] } |
|
|
1843 | ] |
|
|
1844 | } |
|
|
1845 | |
1781 | =item cf::map::unique_maps |
1846 | =item cf::map::unique_maps |
1782 | |
1847 | |
1783 | Returns an arrayref of paths of all shared maps that have |
1848 | Returns an arrayref of paths of all shared maps that have |
1784 | instantiated unique items. May block. |
1849 | instantiated unique items. May block. |
1785 | |
1850 | |
1786 | =cut |
1851 | =cut |
1787 | |
1852 | |
1788 | sub unique_maps() { |
1853 | sub unique_maps() { |
1789 | my $files = aio_readdir $UNIQUEDIR |
1854 | [ |
1790 | or return; |
1855 | map { |
1791 | |
|
|
1792 | my @paths; |
|
|
1793 | |
|
|
1794 | for (@$files) { |
|
|
1795 | utf8::decode $_; |
1856 | utf8::decode $_; |
1796 | next if /\.pst$/; |
1857 | /\.map$/ |
1797 | next unless /^$PATH_SEP/o; |
1858 | ? normalise $_ |
1798 | |
1859 | : () |
1799 | push @paths, cf::map::normalise $_; |
1860 | } @{ aio_readdir $UNIQUEDIR or [] } |
1800 | } |
1861 | ] |
1801 | |
|
|
1802 | \@paths |
|
|
1803 | } |
1862 | } |
1804 | |
1863 | |
1805 | package cf; |
1864 | package cf; |
1806 | |
1865 | |
1807 | =back |
1866 | =back |