# -*- coding: utf-8; mode: tcl; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- vim:fenc=utf-8:ft=tcl:et:sw=4:ts=4:sts=4

PortSystem          1.0

name                hadoop
version             1.2.1
revision            1
categories          java devel science
maintainers         nomaintainer

description         Open-source software for reliable, scalable, distributed computing
long_description    Hadoop is a distributed computing platform written in Java. \
                    It incorporates features similar to those of the Google File System \
                    and of MapReduce.

homepage            https://hadoop.apache.org/
platforms           darwin
license             Apache-2

master_sites        apache:hadoop/common/${distname}
checksums           rmd160  6330ded6043a1c8dd8597910e77f3dedf249a807 \
                    sha256  94a1181771f173bdb55c8f901722825866396091f0516bdd12b34dc3de1706a1

patchfiles          patch-conf-hadoop-env.sh.diff \
                    patch-src-native.diff \
                    patch-src-c++.diff

depends_build       bin:ant:apache-ant \
                    port:autoconf port:automake port:libtool
depends_lib         port:zlib \
                    port:snappy

set java_home       /System/Library/Frameworks/JavaVM.framework/Versions/1.6/Home

# This port works on Mac OS X 10.6 or later, because 'sudo option -E'
# is not available on Mac OS X 10.5 or earlier. See #34665.
if {${os.platform} eq "darwin" && ${os.major} <= 9} {
    known_fail      yes
    pre-fetch {
        ui_error "This port works on Mac OS X 10.6 (Snow Leopard) or later"
        return -code error "Mac OS X 10.6 (Snow Leopard) or later is required"
    }
}
pre-fetch {
    if {![file exists ${java_home}]} {
        ui_error "Java 1.6 is required, but not located at ${java_home}"
        return -code error "Java 1.6 missing"
    }
}

# Fix a file permission to build c++-libhdfs.
post-extract {
    file attributes ${worksrcpath}/src/c++/libhdfs/install-sh -permissions 0755
}

variant universal {}

use_configure       no

set java_include    -I/System/Library/Frameworks/JavaVM.framework/Headers
set cflags          "${configure.cflags} [get_canonical_archflags]"
set cxxflags        "${configure.cxxflags} [get_canonical_archflags cxx]"
set ldflags         "${configure.ldflags} [get_canonical_archflags] -framework JavaVM"
set cppflags        "${configure.cppflags} ${java_include}"

# Set configure args to build native and c++-libhdfs.
post-patch {
    set libs  "-ldl -lz -lsnappy"
    reinplace "s|@cc@|${configure.cc}|g"      ${worksrcpath}/build.xml
    reinplace "s|@cflags@|${cflags}|g"        ${worksrcpath}/build.xml
    reinplace "s|@cxx@|${configure.cxx}|g"    ${worksrcpath}/build.xml
    reinplace "s|@cxxflags@|${cxxflags}|g"    ${worksrcpath}/build.xml
    reinplace "s|@ldflags@|${ldflags}|g"      ${worksrcpath}/build.xml
    reinplace "s|@libs@|${libs}|g"            ${worksrcpath}/build.xml
    reinplace "s|@cppflags@|${cppflags}|g"    ${worksrcpath}/build.xml
    reinplace "s|@args@|--prefix=${prefix}|g" ${worksrcpath}/build.xml
}

# Build native and c++-libhdfs.
build.cmd           ant
build.args          -Dcompile.native=true \
                    -Dsnappy.prefix=${prefix} \
                    -Dcompile.c++=true \
                    -Dlibhdfs=true
build.target        compile-native compile-c++-libhdfs
build.env           JAVA_HOME=${java_home}

# Fix install_name of dylib.
pre-destroot {
    foreach file [glob ${worksrcpath}/build/native/**/lib/*.dylib \
                       ${worksrcpath}/build/c++/**/lib/*.dylib] {
        if {[file isfile ${file}]} {
            set libname [file tail ${file}]
            system "install_name_tool -id ${prefix}/lib/${libname} ${file}"
        }
    }
}

# Hadoop home and conf directories.
set hadoop_basedir  ${prefix}/share/java
set hadoop_home     ${hadoop_basedir}/${distname}
set hadoop_conf_dir ${hadoop_home}/conf

# Document directory.
set hadoop_doc_dir  ${prefix}/share/doc/${distname}

# Working directories.
set hadoop_var_dir  ${prefix}/var/${name}
set hadoop_log_dir  ${hadoop_var_dir}/log
set hadoop_pid_dir  ${hadoop_var_dir}/run

set hadoopuser      hadoop

add_users ${hadoopuser} \
    group=${hadoopuser} \
    realname=Hadoop\ Server \
    home=${hadoop_var_dir} \
    shell=/bin/bash

variant fusedfs description {Add Fuse-DFS} {
    depends_lib-append port:osxfuse

    patchfiles-append  patch-src-contrib-fusedfs.diff

    # libhdfs.dylib must be built before configuring fuse-dfs.
    post-build {
        set libs  "-lfuse -lhdfs"
        # "$@" is replaced with "${hadoop.root}/build/c++/${build.platform}/lib".
        # See files/patch-src-contrib-fusedfs.diff.
        set args  "--prefix=${prefix} \
                   CC=${configure.cc} \
                   CFLAGS=\"${cflags}\" \
                   LDFLAGS=\"${ldflags} -L$@\" \
                   LIBS=\"${libs}\" \
                   CPPFLAGS=\"${cppflags}\""
        set sh ${worksrcpath}/src/contrib/fuse-dfs/bootstrap.sh
        reinplace "s|\./configure|\./configure ${args}|" ${sh}
        # Build fusedfs.
        system -W ${worksrcpath} "ant compile-contrib -Dlibhdfs=1 -Dfusedfs=1"
    }

    post-destroot {
        xinstall -m 755 \
            ${worksrcpath}/build/contrib/fuse-dfs/fuse_dfs \
            ${destroot}${prefix}/bin
        # Fix install_name in fuse_dfs.
        set bin ${destroot}${prefix}/bin/fuse_dfs
        regexp {(\S+\/libhdfs\S+dylib)} [exec otool -L ${bin}] path
        system "install_name_tool -change ${path} ${prefix}/lib/libhdfs.dylib ${bin}"
        # Install fuse_dfs_wrapper.sh.
        xinstall -m 755 ${filespath}/fuse_dfs_wrapper.sh ${destroot}${hadoop_home}/bin
        set sh ${destroot}${hadoop_home}/bin/fuse_dfs_wrapper.sh
        reinplace "s|@hadoop_home@|${hadoop_home}|" ${sh}
        reinplace "s|@java_home@|${java_home}|"     ${sh}
        reinplace "s|@prefix@|${prefix}|"           ${sh}
    }
}

destroot {
    # Copy the distribution to Hadoop home directory.
    xinstall -m 755 -d  ${destroot}${hadoop_home}
    foreach dir {bin conf contrib lib libexec sbin share webapps} {
        copy ${worksrcpath}/${dir} ${destroot}${hadoop_home}
    }
    foreach file [glob ${worksrcpath}/hadoop-*] {
        xinstall -m 644 ${file} ${destroot}${hadoop_home}
    }
    delete ${destroot}${hadoop_home}/lib/native
    delete ${destroot}${hadoop_home}/libexec/jsvc.amd64

    # Patch for Mahout 0.4 to suppress warnings.
    set webinf ${destroot}${hadoop_home}/webapps/secondary/WEB-INF
    xinstall -m 755 -d ${webinf}
    destroot.keepdirs-append ${webinf}

    # Install native and c++ libraries.
    foreach file [glob ${worksrcpath}/build/native/**/lib/* \
                       ${worksrcpath}/build/c++/**/lib/*] {
        xinstall -m 644 ${file} ${destroot}${prefix}/lib
    }
    
    # Copy extra documents.
    xinstall -m 755 -d  ${destroot}${hadoop_doc_dir}
    copy ${worksrcpath}/docs ${destroot}${hadoop_doc_dir}
    foreach file [glob ${worksrcpath}/*.txt] {
        xinstall -m 644 ${file} ${destroot}${hadoop_doc_dir}
    }

    # Install an extra script for this port.
    set hadoop_bin ${destroot}${prefix}/bin/hadoop-bin
    xinstall -m 755 ${filespath}/hadoop-bin      ${hadoop_bin}
    reinplace "s|@hadoop_home@|${hadoop_home}|g" ${hadoop_bin}
    reinplace "s|@java_home@|${java_home}|g"     ${hadoop_bin}
    reinplace "s|@hadoopuser@|${hadoopuser}|g"   ${hadoop_bin}

    # Setup 'hadoop-env.sh' in conf.
    set env_sh ${destroot}${hadoop_conf_dir}/hadoop-env.sh
    reinplace "s|@java_home@|${java_home}|g"           ${env_sh}
    reinplace "s|@hadoop_log_dir@|${hadoop_log_dir}|g" ${env_sh}
    reinplace "s|@hadoop_pid_dir@|${hadoop_pid_dir}|g" ${env_sh}

    # Create working directories.
    xinstall -m 755 -o ${hadoopuser} -g ${hadoopuser} -d \
        ${destroot}${hadoop_var_dir} \
        ${destroot}${hadoop_log_dir} \
        ${destroot}${hadoop_pid_dir}
    destroot.keepdirs-append \
        ${destroot}${hadoop_var_dir} \
        ${destroot}${hadoop_log_dir} \
        ${destroot}${hadoop_pid_dir}
}

post-deactivate {
    ui_msg "********************************************************"
    ui_msg "* To revert the system after uninstalling the port:"
    ui_msg "* 1) Delete Hadoop working directory:"
    ui_msg "*  $ sudo rm -rf ${hadoop_var_dir}"
    ui_msg "* 2) Delete Hadoop user and group:"
    ui_msg "*  $ sudo dscl . -delete /Users/${hadoopuser}"
    ui_msg "*  $ sudo dscl . -delete /Groups/${hadoopuser}"
    ui_msg "********************************************************"
}

default_variants    +pseudo

set hadoop_tmp_dir  ${hadoop_var_dir}/cache

variant pseudo description {Run on a single-node in a pseudo-distributed mode} {
    patchfiles-append  patch-pseudo.diff

    post-destroot {
        # Set conf directory for a pseudo-distributed mode.
        copy ${destroot}${hadoop_conf_dir} ${destroot}${hadoop_conf_dir}.pseudo
        move ${destroot}${hadoop_conf_dir} ${destroot}${hadoop_conf_dir}.local
        ln -s conf.pseudo ${destroot}${hadoop_conf_dir}

        # Set the maximum number of tasks based on the number of the CPUs (cores).
        regexp {\d+} [exec sysctl hw.ncpu] ncpu
        set tasks_max [expr $ncpu + 2]

        # Setup configuration files.
        reinplace "s|@tasks_max@|${tasks_max}|g" \
            ${destroot}${hadoop_conf_dir}.pseudo/mapred-site.xml
        reinplace "s|@hadoop_tmp_dir@|${hadoop_tmp_dir}|" \
            ${destroot}${hadoop_conf_dir}.pseudo/core-site.xml

        # Create a temporary directory.
        xinstall -m 755 -o ${hadoopuser} -g ${hadoopuser} -d \
            ${destroot}${hadoop_tmp_dir}
        destroot.keepdirs-append \
            ${destroot}${hadoop_tmp_dir}
    }

    post-activate {
        # Setup passphraseless ssh.
        set ssh_dir ${hadoop_var_dir}/.ssh
        if {![file exists ${ssh_dir}]} {
            xinstall -m 700 -o ${hadoopuser} -g ${hadoopuser} -d ${ssh_dir}
            system "sudo -u ${hadoopuser} ssh-keygen -t rsa -P '' -f ${ssh_dir}/id_rsa"
            xinstall -m 644 -o ${hadoopuser} -g ${hadoopuser} \
                ${ssh_dir}/id_rsa.pub \
                ${ssh_dir}/authorized_keys
        }

        ui_msg "********************************************************"
        ui_msg "* To run on a single-node in a pseudo-distributed mode:"
        ui_msg "* 1) Turn on Remote Login (sshd):"
        ui_msg "*  check 'System Preferences > Sharing > Remote Login'"
        ui_msg "* 2) Format a new distributed-filesystem:"
        ui_msg "*  $ hadoop-bin hadoop namenode -format"
        ui_msg "* 3) Start the hadoop daemons:"
        ui_msg "*  $ hadoop-bin start-all.sh"
        ui_msg "* 4) Perform operations you like. To see examples:"
        ui_msg "*  $ open file://${hadoop_home}/docs/single_node_setup.html"
        ui_msg "* 5) When you're done, stop the daemons with:"
        ui_msg "*  $ hadoop-bin stop-all.sh"
        ui_msg "********************************************************"
    }
}

livecheck.type      regex
livecheck.url       https://www.apache.org/dist/hadoop/common/stable1/
livecheck.regex     ${name}-(\[0-9.\]+).tar
