All Downloads are FREE. Search and download functionalities are using the official Maven repository.

nextflow.executor.GgConnector.groovy Maven / Gradle / Ivy

Go to download

A DSL modelled around the UNIX pipe concept, that simplifies writing parallel and scalable pipelines in a portable manner

There is a newer version: 0.15.6
Show newest version
/*
 * Copyright (c) 2013-2015, Centre for Genomic Regulation (CRG).
 * Copyright (c) 2013-2015, Paolo Di Tommaso and the respective authors.
 *
 *   This file is part of 'Nextflow'.
 *
 *   Nextflow is free software: you can redistribute it and/or modify
 *   it under the terms of the GNU General Public License as published by
 *   the Free Software Foundation, either version 3 of the License, or
 *   (at your option) any later version.
 *
 *   Nextflow is distributed in the hope that it will be useful,
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *   GNU General Public License for more details.
 *
 *   You should have received a copy of the GNU General Public License
 *   along with Nextflow.  If not, see .
 */

package nextflow.executor

import groovy.transform.Memoized
import groovy.util.logging.Slf4j
import nextflow.Session
import nextflow.file.FileHelper
import nextflow.file.ggfs.GgFileSystemProvider
import nextflow.file.ggfs.GgPath
import nextflow.processor.TaskPollingMonitor
import nextflow.util.Duration
import nextflow.util.KryoHelper
import nextflow.util.PathSerializer
import nextflow.util.RemoteSession
import org.gridgain.grid.Grid
import org.gridgain.grid.GridNode
import org.gridgain.grid.GridProjection
import org.gridgain.grid.cache.GridCache
import org.gridgain.grid.events.GridEventType
import org.gridgain.grid.spi.discovery.GridDiscoverySpiListener
import org.jetbrains.annotations.Nullable
/**
 * Creates an instance of the GridGain node
 *
 * @author Paolo Di Tommaso 
 */
@Slf4j
class GgConnector implements GridDiscoverySpiListener {

    @Memoized
    static GgConnector create(TaskPollingMonitor monitor) {
        new GgConnector(monitor)
    }

    final private TaskPollingMonitor monitor

    final private Session session

    private Grid grid

    private GridCache allSessions

    private Thread watcher

    private GgConnector(TaskPollingMonitor monitor) {
        log.debug "Create GridGain master node"
        this.monitor = monitor
        this.session = monitor.session

        initialize()
    }

    private initialize() {

        /*
         * Register the path serializer
         */
        KryoHelper.register(GgPath, PathSerializer)

        /*
         * access to the GridGain file system to force the instantiation of a GridGain instance
         * if it is not already available
         */
        def fs = FileHelper.getOrCreateFileSystemFor(URI.create('ggfs:///'))
        grid = (fs.provider() as GgFileSystemProvider).getGrid()

        // thread to watch for topology changes and update the scheduler queue accordingly
        watcher = topologyWatcher()

        /*
         * setup the session cache
         */
        allSessions = grid.cache(GgGridFactory.SESSIONS_CACHE)
        allSessions.put( session.uniqueId, new RemoteSession(session) )

        /*
         * shutdown the instance on session termination
         */
        monitor.session.onShutdown {
            if( watcher ) watcher.interrupt()
            allSessions.remove(session.uniqueId)
            grid.close()
        }
    }

    /**
     * Launch a thread that will watch for added/removed cluster members increasing/decreasing accordingly
     * the monitor queue
     */
    private Thread topologyWatcher() {

        def result = Thread.start {

            float xFactor = 1.4
            int slots = cluster.metrics().getTotalCpus()
            log.debug "Cluster metrics >> slots: $slots"
            int value = (slots * xFactor) + 1
            monitor.capacitySet(value)

            def max = Duration.of('10sec').toMillis()
            while( true ) {
                try {
                    Thread.sleep(max)
                }
                catch( InterruptedException e ) {
                    break
                }
                catch( Throwable e ) {
                    log.debug("Error on topology watcher",e)
                }

                slots = cluster.metrics().getTotalCpus()
                log.debug "Cluster metrics >> cpus: $slots"
                value = (slots * xFactor) + 1
                monitor.capacitySet(value)
            }
        }

        result.setName('Topology watcher')
        return result
    }

    def GridProjection getCluster() {
        def result = grid.forAttribute("ROLE", "worker")
        log.trace "Grid nodes: ${grid.nodes().size()} -- as worker: ${result.nodes().size()}"
        return result
    }

    @Override
    @Deprecated // this could be removed
    void onDiscovery(int type, long topVer, GridNode node, Collection topSnapshot, @Nullable Map> topHist) {
        log.debug "Discovery event >> ${nodeEvents.get(type)?:type} [$node]"
    }

    static nodeEvents = [
            (GridEventType.EVT_NODE_FAILED): 'NODE_FAILED',
            (GridEventType.EVT_NODE_JOINED): 'NODE_JOINED',
            (GridEventType.EVT_NODE_LEFT):   'NODE_LEFT',
            (GridEventType.EVT_NODE_METRICS_UPDATED): 'EVT_NODE_METRICS_UPDATED',
            (GridEventType.EVT_NODE_RECONNECTED):     'EVT_NODE_RECONNECTED',
            (GridEventType.EVT_NODE_SEGMENTED):       'EVT_NODE_SEGMENTED'
    ]

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy