text:
require 'spec_helper'

describe Octoshark::ConnectionPoolsManager do
  describe "#initialize" do
    it "initializes connection manager with default connection" do
      manager = Octoshark::ConnectionPoolsManager.new

      expect(manager.connection_pools.length).to eq(0)
      expect(manager.connection_pools[:default]).to be_nil
    end

    it "initializes connection manager with custom connections" do
      manager = Octoshark::ConnectionPoolsManager.new(configs)

      expect(manager.connection_pools.length).to eq(2)
      expect(manager.connection_pools[:db1]).to be_an_instance_of(ActiveRecord::ConnectionAdapters::ConnectionPool)
      expect(manager.connection_pools[:db2]).to be_an_instance_of(ActiveRecord::ConnectionAdapters::ConnectionPool)
    end

    it "accepts configs with string keys" do
      configs = { 'db1' => { 'adapter' => "sqlite3", 'database' => "tmp/db1.sqlite" } }
      manager = Octoshark::ConnectionPoolsManager.new(configs)

      expect { manager.connection_pools[:db1].connection }.not_to raise_error
    end
  end

  describe '#find_connection_pool' do
    it "can find connection pool by name" do
      manager = Octoshark::ConnectionPoolsManager.new(configs)
      expect(manager.find_connection_pool(:db1)).to be_an_instance_of(ActiveRecord::ConnectionAdapters::ConnectionPool)
    end

    it "raises Octoshark::Error::NoConnection when no pool with that name" do
      manager = Octoshark::ConnectionPoolsManager.new({})
      expect { manager.find_connection_pool(:invalid) }.to raise_error(Octoshark::Error::NoConnection)
    end
  end

  describe '#with_connection' do
    it "can use multiple connections" do
      manager = Octoshark::ConnectionPoolsManager.new(configs)

      manager.with_connection(:db1) do
        expect(db(manager.current_connection)).to eq("db1")
      end

      manager.with_connection(:db2) do
        expect(db(manager.current_connection)).to eq("db2")
      end
    end

    it "can nest connection" do
      manager = Octoshark::ConnectionPoolsManager.new(configs)

      manager.with_connection(:db1) do
        expect(db(manager.current_connection)).to eq("db1")

        manager.with_connection(:db2) do
          expect(db(manager.current_connection)).to eq("db2")
        end

        expect(db(manager.current_connection)).to eq("db1")
      end
    end

    it "returns value from execution" do
      manager = Octoshark::ConnectionPoolsManager.new(configs)
      result = manager.with_connection(:db1) { |connection| connection.execute("SELECT 1") }
      expect(result.first['1']).to eq(1)
    end

    it "raises Octoshark::Error::NoConnection" do
      manager = Octoshark::ConnectionPoolsManager.new({})

      expect { manager.with_connection(:invalid) }.to raise_error(Octoshark::Error::NoConnection)
    end

    context "using specific database", mysql2: true do
      it "can use specific database" do
        manager = Octoshark::ConnectionPoolsManager.new(mysql2_configs)

        db1 = mysql2_configs[:db1]['database']
        db2 = mysql2_configs[:db2]['database']

        manager.with_connection(:db1, db1) do
          expect(db(manager.current_connection)).to eq(db1)

          manager.with_connection(:db2, db2) do
            expect(db(manager.current_connection)).to eq(db2)
          end

          expect(db(manager.current_connection)).to eq(db1)
        end
      end

      it "sets database name on the connection" do
        manager = Octoshark::ConnectionPoolsManager.new(mysql2_configs)

        db1 = mysql2_configs[:db1]['database']

        manager.with_connection(:db1, db1) do |connection|
          expect(connection.database_name).to eq('octoshark_db1')
        end
      end

      it "returns value from execution" do
        manager = Octoshark::ConnectionPoolsManager.new(mysql2_configs)
        db1 = mysql2_configs[:db1]['database']
        result = manager.with_connection(:db1, db1) { |connection| connection.execute("SELECT 1") }.to_a
        expect(result).to eq([[1]])
      end
    end
  end

  describe "#disconnect!" do
    it "removes all connections from connection pools" do
      manager = Octoshark::ConnectionPoolsManager.new(configs)

      manager.with_connection(:db1) { |connection| connection.execute("SELECT 1") }
      expect(manager.find_connection_pool(:db1)).to be_connected

      manager.disconnect!

      expect(manager.find_connection_pool(:db1)).to_not be_connected
    end
  end

  describe ".reset!" do
    it "gets new connection pools ready to rock" do
      manager = Octoshark::ConnectionPoolsManager.new(configs)

      manager.with_connection(:db1) { |connection| connection.execute("SELECT 1") }
      expect(manager.connection_pools[:db1].connections.count).to eq(1)

      manager.reset!

      expect(manager.connection_pools[:db1].connections.count).to eq(0)

      manager.with_connection(:db1) { |connection| connection.execute("SELECT 1") }
      expect(manager.connection_pools[:db1].connections.count).to eq(1)
    end
  end

  describe ".reset_connection_managers!" do
    it "resets connection managers" do
      manager = Octoshark::ConnectionPoolsManager.new(configs)
      old_pools = manager.connection_pools.map(&:object_id)

      Octoshark::ConnectionPoolsManager.reset_connection_managers!

      new_pools = manager.connection_pools.map(&:object_id)
      expect(new_pools).to_not eq(old_pools)
    end
  end

  describe ".disconnect!" do
    it "disconnects connection managers" do
      manager = Octoshark::ConnectionPoolsManager.new(configs)

      Octoshark::ConnectionPoolsManager.disconnect!

      expect(Octoshark::ConnectionPoolsManager.connection_managers).to be_blank
    end

    it "cleans old connections" do
      manager = Octoshark::ConnectionPoolsManager.new(configs)

      manager.with_connection(:db1) { |connection| connection.execute("SELECT 1") }
      manager.with_connection(:db2) { |connection| connection.execute("SELECT 1") }
      expect(manager.connection_pools[:db1].connections.count).to eq(1)
      expect(manager.connection_pools[:db2].connections.count).to eq(1)

      Octoshark::ConnectionPoolsManager.disconnect!

      expect(manager.connection_pools[:db1].connections.count).to eq(0)
      expect(manager.connection_pools[:db2].connections.count).to eq(0)
    end
  end
end


text:
import {$} from '../common/vendor';

declare var jQuery;

$(function () {
    $('.changelog-page .info-page').each(function () {
        // show/hide tabs
        $('ul.nav-tabs a').click(function (e) {
            e.preventDefault();
            (<any>$(this)).tab('show');
        });

        function skipKey(key) {
            var ignore = ['ArrowRight', 'ArrowLeft', 'Home', 'End', 'ArrowUp', 'ArrowDown', 'ArrowRight', 'Shift', 'Control', 'Alt', 'Meta'];
            return ignore.indexOf(key) >= 0;
        }

        function displayFixVersionInformation(fixVersion) {
            $("[fixVersionNote]").hide()

            const underscoredId = fixVersion.split('.').join('_');
            if(fixVersion !== 'All Versions') {
                $(`#fix_version_${underscoredId}`).show()
            }
        }

        function processSearchValue() {
            var value = (<any>document.getElementById('global_search')).value;
            var searchCriteria = (<any>$).trim(value).replace(/ +/g, ' ').toLowerCase();

            var reportTable = $("table[id^=content_]")[0];

            // hide the more info rows
            $(reportTable).find("tr.jira-more-info").hide();

            var tableRows = $(reportTable).find("tr.jira[jira_data]");

            // 1) filter out rows that DON'T match the current search
            tableRows
                .show()
                .filter(function () {
                    var selectedFixVersion = $('#fixVersionFilter').find(":selected").text();
                    selectedFixVersion = selectedFixVersion === 'All Versions' ? '' : selectedFixVersion;

                    var breakingChangesFail = (<HTMLInputElement>document.getElementById('breaking')).checked && $(this).attr("breaking") === undefined;
                    var deprecationsFail = (<HTMLInputElement>document.getElementById('deprecation')).checked && $(this).attr("deprecation") === undefined;

                    var text = $(this).text().replace(/\s+/g, ' ').toLowerCase();
                    var searchTextFails = !~text.indexOf(searchCriteria);

                    var fixVersionFails = false;
                    if (!searchTextFails) {
                        var text = $(this).text().replace(/\s+/g, ' ').toLowerCase();
                        fixVersionFails = !~text.indexOf(selectedFixVersion);
                    }

                    return fixVersionFails || breakingChangesFail || deprecationsFail || searchTextFails;
                })
                .hide();
        }

        // global issue search
        $('#global_search').keyup(function (event) {
            if (skipKey(event.key)) {
                return;
            }

            processSearchValue();
        });

        $("#fixVersionFilter").change(function () {
            processSearchValue();
            displayFixVersionInformation($("#fixVersionFilter").val())
        });

        $("#breaking").click(function () {
            processSearchValue();
        });
        $("#deprecation").click(function () {
            processSearchValue();
        });
        $("span[more-info]").click(function () {
            toggleMoreInfo($(this).attr("data-key"))
        });

        // clearable input (x in global search input)
        jQuery(function ($) {
            function tog(v) {
                return v ? 'addClass' : 'removeClass';
            }

            $(document).on('input', '.clearable', function () {
                $(this)[tog(this.value)]('x');
            }).on('mousemove', '.x', function (e) {
                $(this)[tog(this.offsetWidth - 18 < e.clientX - this.getBoundingClientRect().left)]('onX');
            }).on('touchstart click', '.onX', function (ev) {
                ev.preventDefault();
                $(this).removeClass('x onX').val('').change();
                processSearchValue();
            });
        });

        // more info rows
        function toggleMoreInfo(id) {
            $("#" + id).toggle();
        }

        processSearchValue();
        displayFixVersionInformation($("#fixVersionFilter").val())
    });
});

redpajama_set_name: RedPajamaGithub


text:
#include "mkbp_event.h"

const struct mkbp_event_source *zephyr_find_mkbp_event_source(uint8_t type)
{
	STRUCT_SECTION_FOREACH(mkbp_event_source, evtsrc)
	{
		if (evtsrc->event_type == type)
			return evtsrc;
	}

	return NULL;
}


text:
package global

import (
	"github.com/docker/swarmkit/api"
	"github.com/docker/swarmkit/log"
	"github.com/docker/swarmkit/manager/constraint"
	"github.com/docker/swarmkit/manager/orchestrator"
	"github.com/docker/swarmkit/manager/orchestrator/restart"
	"github.com/docker/swarmkit/manager/orchestrator/taskinit"
	"github.com/docker/swarmkit/manager/orchestrator/update"
	"github.com/docker/swarmkit/manager/state/store"
	"golang.org/x/net/context"
)

type globalService struct {
	*api.Service

	// Compiled constraints
	constraints []constraint.Constraint
}

// Orchestrator runs a reconciliation loop to create and destroy tasks as
// necessary for global services.
type Orchestrator struct {
	store *store.MemoryStore
	// nodes is the set of non-drained nodes in the cluster, indexed by node ID
	nodes map[string]*api.Node
	// globalServices has all the global services in the cluster, indexed by ServiceID
	globalServices map[string]globalService
	restartTasks   map[string]struct{}

	// stopChan signals to the state machine to stop running.
	stopChan chan struct{}
	// doneChan is closed when the state machine terminates.
	doneChan chan struct{}

	updater  *update.Supervisor
	restarts *restart.Supervisor

	cluster *api.Cluster // local instance of the cluster
}

// NewGlobalOrchestrator creates a new global Orchestrator
func NewGlobalOrchestrator(store *store.MemoryStore) *Orchestrator {
	restartSupervisor := restart.NewSupervisor(store)
	updater := update.NewSupervisor(store, restartSupervisor)
	return &Orchestrator{
		store:          store,
		nodes:          make(map[string]*api.Node),
		globalServices: make(map[string]globalService),
		stopChan:       make(chan struct{}),
		doneChan:       make(chan struct{}),
		updater:        updater,
		restarts:       restartSupervisor,
		restartTasks:   make(map[string]struct{}),
	}
}

func (g *Orchestrator) initTasks(ctx context.Context, readTx store.ReadTx) error {
	return taskinit.CheckTasks(ctx, g.store, readTx, g, g.restarts)
}

// Run contains the global orchestrator event loop
func (g *Orchestrator) Run(ctx context.Context) error {
	defer close(g.doneChan)

	// Watch changes to services and tasks
	queue := g.store.WatchQueue()
	watcher, cancel := queue.Watch()
	defer cancel()

	// lookup the cluster
	var err error
	g.store.View(func(readTx store.ReadTx) {
		var clusters []*api.Cluster
		clusters, err = store.FindClusters(readTx, store.ByName("default"))

		if len(clusters) != 1 {
			return // just pick up the cluster when it is created.
		}
		g.cluster = clusters[0]
	})
	if err != nil {
		return err
	}

	// Get list of nodes
	var nodes []*api.Node
	g.store.View(func(readTx store.ReadTx) {
		nodes, err = store.FindNodes(readTx, store.All)
	})
	if err != nil {
		return err
	}
	for _, n := range nodes {
		g.updateNode(n)
	}

	// Lookup global services
	var existingServices []*api.Service
	g.store.View(func(readTx store.ReadTx) {
		existingServices, err = store.FindServices(readTx, store.All)
	})
	if err != nil {
		return err
	}

	var reconcileServiceIDs []string
	for _, s := range existingServices {
		if orchestrator.IsGlobalService(s) {
			g.updateService(s)
			reconcileServiceIDs = append(reconcileServiceIDs, s.ID)
		}
	}

	// fix tasks in store before reconciliation loop
	g.store.View(func(readTx store.ReadTx) {
		err = g.initTasks(ctx, readTx)
	})
	if err != nil {
		return err
	}

	g.tickTasks(ctx)
	g.reconcileServices(ctx, reconcileServiceIDs)

	for {
		select {
		case event := <-watcher:
			// TODO(stevvooe): Use ctx to limit running time of operation.
			switch v := event.(type) {
			case api.EventUpdateCluster:
				g.cluster = v.Cluster
			case api.EventCreateService:
				if !orchestrator.IsGlobalService(v.Service) {
					continue
				}
				g.updateService(v.Service)
				g.reconcileServices(ctx, []string{v.Service.ID})
			case api.EventUpdateService:
				if !orchestrator.IsGlobalService(v.Service) {
					continue
				}
				g.updateService(v.Service)
				g.reconcileServices(ctx, []string{v.Service.ID})
			case api.EventDeleteService:
				if !orchestrator.IsGlobalService(v.Service) {
					continue
				}
				orchestrator.DeleteServiceTasks(ctx, g.store, v.Service)
				// delete the service from service map
				delete(g.globalServices, v.Service.ID)
				g.restarts.ClearServiceHistory(v.Service.ID)
			case api.EventCreateNode:
				g.updateNode(v.Node)
				g.reconcileOneNode(ctx, v.Node)
			case api.EventUpdateNode:
				g.updateNode(v.Node)
				g.reconcileOneNode(ctx, v.Node)
			case api.EventDeleteNode:
				g.foreachTaskFromNode(ctx, v.Node, g.deleteTask)
				delete(g.nodes, v.Node.ID)
			case api.EventUpdateTask:
				g.handleTaskChange(ctx, v.Task)
			}
		case <-g.stopChan:
			return nil
		}
		g.tickTasks(ctx)
	}
}

// FixTask validates a task with the current cluster settings, and takes
// action to make it conformant to node state and service constraint
// it's called at orchestrator initialization
func (g *Orchestrator) FixTask(ctx context.Context, batch *store.Batch, t *api.Task) {
	if _, exists := g.globalServices[t.ServiceID]; !exists {
		return
	}
	// if a task's DesiredState has past running, the task has been processed
	if t.DesiredState > api.TaskStateRunning {
		return
	}

	var node *api.Node
	if t.NodeID != "" {
		node = g.nodes[t.NodeID]
	}
	// if the node no longer valid, remove the task
	if t.NodeID == "" || orchestrator.InvalidNode(node) {
		g.shutdownTask(ctx, batch, t)
		return
	}

	// restart a task if it fails
	if t.Status.State > api.TaskStateRunning {
		g.restartTasks[t.ID] = struct{}{}
	}
}

// handleTaskChange defines what orchestrator does when a task is updated by agent
func (g *Orchestrator) handleTaskChange(ctx context.Context, t *api.Task) {
	if _, exists := g.globalServices[t.ServiceID]; !exists {
		return
	}
	// if a task's DesiredState has passed running, it
	// means the task has been processed
	if t.DesiredState > api.TaskStateRunning {
		return
	}

	// if a task has passed running, restart it
	if t.Status.State > api.TaskStateRunning {
		g.restartTasks[t.ID] = struct{}{}
	}
}

// Stop stops the orchestrator.
func (g *Orchestrator) Stop() {
	close(g.stopChan)
	<-g.doneChan
	g.updater.CancelAll()
	g.restarts.CancelAll()
}

func (g *Orchestrator) foreachTaskFromNode(ctx context.Context, node *api.Node, cb func(context.Context, *store.Batch, *api.Task)) {
	var (
		tasks []*api.Task
		err   error
	)
	g.store.View(func(tx store.ReadTx) {
		tasks, err = store.FindTasks(tx, store.ByNodeID(node.ID))
	})
	if err != nil {
		log.G(ctx).WithError(err).Errorf("global orchestrator: foreachTaskFromNode failed finding tasks")
		return
	}

	err = g.store.Batch(func(batch *store.Batch) error {
		for _, t := range tasks {
			// Global orchestrator only removes tasks from globalServices
			if _, exists := g.globalServices[t.ServiceID]; exists {
				cb(ctx, batch, t)
			}
		}
		return nil
	})
	if err != nil {
		log.G(ctx).WithError(err).Errorf("global orchestrator: foreachTaskFromNode failed batching tasks")
	}
}

func (g *Orchestrator) reconcileServices(ctx context.Context, serviceIDs []string) {
	nodeTasks := make(map[string]map[string][]*api.Task)

	g.store.View(func(tx store.ReadTx) {
		for _, serviceID := range serviceIDs {
			service := g.globalServices[serviceID].Service
			if service == nil {
				continue
			}

			tasks, err := store.FindTasks(tx, store.ByServiceID(serviceID))
			if err != nil {
				log.G(ctx).WithError(err).Errorf("global orchestrator: reconcileServices failed finding tasks for service %s", serviceID)
				continue
			}

			// nodeID -> task list
			nodeTasks[serviceID] = make(map[string][]*api.Task)

			for _, t := range tasks {
				nodeTasks[serviceID][t.NodeID] = append(nodeTasks[serviceID][t.NodeID], t)
			}

			// Keep all runnable instances of this service,
			// and instances that were not be restarted due
			// to restart policy but may be updated if the
			// service spec changed.
			for nodeID, slot := range nodeTasks[serviceID] {
				updatable := g.restarts.UpdatableTasksInSlot(ctx, slot, g.globalServices[serviceID].Service)
				if len(updatable) != 0 {
					nodeTasks[serviceID][nodeID] = updatable
				} else {
					delete(nodeTasks[serviceID], nodeID)
				}
			}

		}
	})

	updates := make(map[*api.Service][]orchestrator.Slot)

	err := g.store.Batch(func(batch *store.Batch) error {
		for _, serviceID := range serviceIDs {
			var updateTasks []orchestrator.Slot

			if _, exists := nodeTasks[serviceID]; !exists {
				continue
			}

			service := g.globalServices[serviceID]

			for nodeID, node := range g.nodes {
				meetsConstraints := constraint.NodeMatches(service.constraints, node)
				ntasks := nodeTasks[serviceID][nodeID]
				delete(nodeTasks[serviceID], nodeID)

				if !meetsConstraints {
					g.shutdownTasks(ctx, batch, ntasks)
					continue
				}

				if node.Spec.Availability == api.NodeAvailabilityPause {
					// the node is paused, so we won't add or update
					// any tasks
					continue
				}

				// this node needs to run 1 copy of the task
				if len(ntasks) == 0 {
					g.addTask(ctx, batch, service.Service, nodeID)
				} else {
					updateTasks = append(updateTasks, ntasks)
				}
			}

			if len(updateTasks) > 0 {
				updates[service.Service] = updateTasks
			}

			// Remove any tasks assigned to nodes not found in g.nodes.
			// These must be associated with nodes that are drained, or
			// nodes that no longer exist.
			for _, ntasks := range nodeTasks[serviceID] {
				g.shutdownTasks(ctx, batch, ntasks)
			}
		}
		return nil
	})

	if err != nil {
		log.G(ctx).WithError(err).Errorf("global orchestrator: reconcileServices transaction failed")
	}

	for service, updateTasks := range updates {
		g.updater.Update(ctx, g.cluster, service, updateTasks)
	}
}

// updateNode updates g.nodes based on the current node value
func (g *Orchestrator) updateNode(node *api.Node) {
	if node.Spec.Availability == api.NodeAvailabilityDrain || node.Status.State == api.NodeStatus_DOWN {
		delete(g.nodes, node.ID)
	} else {
		g.nodes[node.ID] = node
	}
}

// updateService updates g.globalServices based on the current service value
func (g *Orchestrator) updateService(service *api.Service) {
	var constraints []constraint.Constraint

	if service.Spec.Task.Placement != nil && len(service.Spec.Task.Placement.Constraints) != 0 {
		constraints, _ = constraint.Parse(service.Spec.Task.Placement.Constraints)
	}

	g.globalServices[service.ID] = globalService{
		Service:     service,
		constraints: constraints,
	}
}

// reconcileOneNode checks all global services on one node
func (g *Orchestrator) reconcileOneNode(ctx context.Context, node *api.Node) {
	if node.Spec.Availability == api.NodeAvailabilityDrain {
		log.G(ctx).Debugf("global orchestrator: node %s in drain state, shutting down its tasks", node.ID)
		g.foreachTaskFromNode(ctx, node, g.shutdownTask)
		return
	}

	if node.Status.State == api.NodeStatus_DOWN {
		log.G(ctx).Debugf("global orchestrator: node %s is down, shutting down its tasks", node.ID)
		g.foreachTaskFromNode(ctx, node, g.shutdownTask)
		return
	}

	if node.Spec.Availability == api.NodeAvailabilityPause {
		// the node is paused, so we won't add or update tasks
		return
	}

	node, exists := g.nodes[node.ID]
	if !exists {
		return
	}

	// tasks by service
	tasks := make(map[string][]*api.Task)

	var (
		tasksOnNode []*api.Task
		err         error
	)

	g.store.View(func(tx store.ReadTx) {
		tasksOnNode, err = store.FindTasks(tx, store.ByNodeID(node.ID))
	})
	if err != nil {
		log.G(ctx).WithError(err).Errorf("global orchestrator: reconcile failed finding tasks on node %s", node.ID)
		return
	}

	for serviceID, service := range g.globalServices {
		for _, t := range tasksOnNode {
			if t.ServiceID != serviceID {
				continue
			}
			tasks[serviceID] = append(tasks[serviceID], t)
		}

		// Keep all runnable instances of this service,
		// and instances that were not be restarted due
		// to restart policy but may be updated if the
		// service spec changed.
		for serviceID, slot := range tasks {
			updatable := g.restarts.UpdatableTasksInSlot(ctx, slot, service.Service)

			if len(updatable) != 0 {
				tasks[serviceID] = updatable
			} else {
				delete(tasks, serviceID)
			}
		}
	}

	err = g.store.Batch(func(batch *store.Batch) error {
		for serviceID, service := range g.globalServices {
			if !constraint.NodeMatches(service.constraints, node) {
				continue
			}

			if len(tasks) == 0 {
				g.addTask(ctx, batch, service.Service, node.ID)
			} else {
				// If task is out of date, update it. This can happen
				// on node reconciliation if, for example, we pause a
				// node, update the service, and then activate the node
				// later.

				// We don't use g.updater here for two reasons:
				// - This is not a rolling update. Since it was not
				//   triggered directly by updating the service, it
				//   should not observe the rolling update parameters
				//   or show status in UpdateStatus.
				// - Calling Update cancels any current rolling updates
				//   for the service, such as one triggered by service
				//   reconciliation.

				var (
					dirtyTasks []*api.Task
					cleanTasks []*api.Task
				)

				for _, t := range tasks[serviceID] {
					if orchestrator.IsTaskDirty(service.Service, t) {
						dirtyTasks = append(dirtyTasks, t)
					} else {
						cleanTasks = append(cleanTasks, t)
					}
				}

				if len(cleanTasks) == 0 {
					g.addTask(ctx, batch, service.Service, node.ID)
				} else {
					dirtyTasks = append(dirtyTasks, cleanTasks[1:]...)
				}
				g.shutdownTasks(ctx, batch, dirtyTasks)
			}
		}
		return nil
	})
	if err != nil {
		log.G(ctx).WithError(err).Errorf("global orchestrator: reconcileServiceOneNode batch failed")
	}
}

func (g *Orchestrator) tickTasks(ctx context.Context) {
	if len(g.restartTasks) == 0 {
		return
	}
	err := g.store.Batch(func(batch *store.Batch) error {
		for taskID := range g.restartTasks {
			err := batch.Update(func(tx store.Tx) error {
				t := store.GetTask(tx, taskID)
				if t == nil || t.DesiredState > api.TaskStateRunning {
					return nil
				}

				service := store.GetService(tx, t.ServiceID)
				if service == nil {
					return nil
				}

				node, nodeExists := g.nodes[t.NodeID]
				serviceEntry, serviceExists := g.globalServices[t.ServiceID]
				if !nodeExists || !serviceExists {
					return nil
				}

				if node.Spec.Availability == api.NodeAvailabilityPause ||
					!constraint.NodeMatches(serviceEntry.constraints, node) {
					t.DesiredState = api.TaskStateShutdown
					return store.UpdateTask(tx, t)
				}

				return g.restarts.Restart(ctx, tx, g.cluster, service, *t)
			})
			if err != nil {
				log.G(ctx).WithError(err).Errorf("orchestrator restartTask transaction failed")
			}
		}
		return nil
	})
	if err != nil {
		log.G(ctx).WithError(err).Errorf("global orchestrator: restartTask transaction failed")
	}
	g.restartTasks = make(map[string]struct{})
}

func (g *Orchestrator) shutdownTask(ctx context.Context, batch *store.Batch, t *api.Task) {
	// set existing task DesiredState to TaskStateShutdown
	// TODO(aaronl): optimistic update?
	err := batch.Update(func(tx store.Tx) error {
		t = store.GetTask(tx, t.ID)
		if t != nil && t.DesiredState < api.TaskStateShutdown {
			t.DesiredState = api.TaskStateShutdown
			return store.UpdateTask(tx, t)
		}
		return nil
	})
	if err != nil {
		log.G(ctx).WithError(err).Errorf("global orchestrator: shutdownTask failed to shut down %s", t.ID)
	}
}

func (g *Orchestrator) addTask(ctx context.Context, batch *store.Batch, service *api.Service, nodeID string) {
	task := orchestrator.NewTask(g.cluster, service, 0, nodeID)

	err := batch.Update(func(tx store.Tx) error {
		if store.GetService(tx, service.ID) == nil {
			return nil
		}
		return store.CreateTask(tx, task)
	})
	if err != nil {
		log.G(ctx).WithError(err).Errorf("global orchestrator: failed to create task")
	}
}

func (g *Orchestrator) shutdownTasks(ctx context.Context, batch *store.Batch, tasks []*api.Task) {
	for _, t := range tasks {
		g.shutdownTask(ctx, batch, t)
	}
}

func (g *Orchestrator) deleteTask(ctx context.Context, batch *store.Batch, t *api.Task) {
	err := batch.Update(func(tx store.Tx) error {
		return store.DeleteTask(tx, t.ID)
	})
	if err != nil {
		log.G(ctx).WithError(err).Errorf("global orchestrator: deleteTask failed to delete %s", t.ID)
	}
}

// IsRelatedService returns true if the service should be governed by this orchestrator
func (g *Orchestrator) IsRelatedService(service *api.Service) bool {
	return orchestrator.IsGlobalService(service)
}

// SlotTuple returns a slot tuple for the global service task.
func (g *Orchestrator) SlotTuple(t *api.Task) orchestrator.SlotTuple {
	return orchestrator.SlotTuple{
		ServiceID: t.ServiceID,
		NodeID:    t.NodeID,
	}
}

func isTaskCompleted(t *api.Task, restartPolicy api.RestartPolicy_RestartCondition) bool {
	if t == nil || t.DesiredState <= api.TaskStateRunning {
		return false
	}
	return restartPolicy == api.RestartOnNone ||
		(restartPolicy == api.RestartOnFailure && t.Status.State == api.TaskStateCompleted)
}


text:
require 'zlib'

require 'perobs/BTree'
require 'perobs/BTreeNodeLink'

module PEROBS

  # The BTreeNode class manages more or less standard BTree nodes. All nodes
  # contain BTree.order number of keys. Leaf node contain BTree.order number
  # of values and no child references. Branch nodes only contain BTree.order +
  # 1 number of child references but no values. The is_leaf flag is used to
  # mark a node as leaf or branch node.
  class BTreeNode

    Stats = Struct.new(:branch_depth, :nodes_count, :leave_nodes, :leaves)

    attr_reader :node_address, :parent, :is_leaf, :next_sibling, :prev_sibling,
      :keys, :values, :children

    # Create a new BTreeNode object for the given tree with the given parent
    # or recreate the node with the given node_address from the backing store.
    # If node_address is nil a new node will be created. If not, node_address
    # must be an existing address that can be found in the backing store to
    # restore the node.
    # @param tree [BTree] The tree this node is part of
    # @param parent [BTreeNode] reference to parent node
    # @param prev_sibling [BTreeNode] reference to previous sibling node
    # @param next_sibling [BTreeNode] reference to next sibling node
    # @param node_address [Integer] the address of the node to read from the
    #        backing store
    # @param is_leaf [Boolean] true if the node should be a leaf node, false
    #        if not
    def initialize(tree, node_address = nil, parent = nil, is_leaf = true,
                   prev_sibling = nil, next_sibling = nil,
                   keys = nil, values = nil, children = nil)
      @tree = tree
      if node_address == 0
        PEROBS.log.fatal "Node address may not be 0"
      end
      @node_address = node_address
      @parent = link(parent)
      @prev_sibling = link(prev_sibling)
      @next_sibling = link(next_sibling)
      @keys = keys || []
      if (@is_leaf = is_leaf)
        @values = values || []
        @children = nil
      else
        @children = children || []
        @values = nil
      end
    end

    # Create a new BTreeNode. This method should be used for the creation
    # of new nodes instead of calling the constructor directly.
    # @param tree [BTree] The tree the new node should belong to
    # @param parent [BTreeNode] The parent node
    # @param is_leaf [Boolean] True if the node has no children, false
    #        otherwise
    # @param prev_sibling [BTreeNode] reference to previous sibling node
    # @param next_sibling [BTreeNode] reference to next sibling node
    def BTreeNode::create(tree, parent = nil, is_leaf = true,
                          prev_sibling = nil, next_sibling = nil)
      unless parent.nil? || parent.is_a?(BTreeNode) ||
             parent.is_a?(BTreeNodeLink)
        PEROBS.log.fatal "Parent node must be a BTreeNode but is of class " +
          "#{parent.class}"
      end

      address = tree.nodes.free_address
      node = BTreeNode.new(tree, address, parent, is_leaf, prev_sibling,
                           next_sibling)
      # This is a new node. Make sure the data is written to the file.
      tree.node_cache.insert(node)

      # Insert the newly created node into the existing node chain.
      if (node.prev_sibling = prev_sibling)
        node.prev_sibling.next_sibling = BTreeNodeLink.new(tree, node)
      end
      if (node.next_sibling = next_sibling)
        node.next_sibling.prev_sibling = BTreeNodeLink.new(tree, node)
      end

      BTreeNodeLink.new(tree, node)
    end

    # Restore a node from the backing store at the given address and tree.
    # @param tree [BTree] The tree the node belongs to
    # @param address [Integer] The address in the blob file.
    def BTreeNode::load(tree, address, unused = nil)
      unless address.is_a?(Integer)
        PEROBS.log.fatal "address is not Integer: #{address.class}"
      end

      unless (bytes = tree.nodes.retrieve_blob(address))
        PEROBS.log.fatal "SpaceTree node at address #{address} " +
          "does not exist"
      end

      unless Zlib::crc32(bytes) != 0
        PEROBS.log.fatal "Checksum failure in BTreeNode entry @#{address}"
      end
      ary = bytes.unpack(BTreeNode::node_bytes_format(tree))
      # Read is_leaf
      if ary[0] != 0 && ary[0] != 1
        PEROBS.log.fatal "First byte of a BTreeNode entry at address " +
          "#{address} must be 0 or 1 but is #{ary[0]}"
      end
      is_leaf = ary[0] == 0 ? false : true
      # This is the number of keys this node has.
      key_count = ary[1]
      data_count = ary[2]
      # Read the parent node address
      parent = ary[3] == 0 ? nil : BTreeNodeLink.new(tree, ary[3])
      prev_sibling = ary[4] == 0 ? nil : BTreeNodeLink.new(tree, ary[4])
      next_sibling = ary[5] == 0 ? nil : BTreeNodeLink.new(tree, ary[5])
      # Read the keys
      keys = ary[6, key_count]

      children = nil
      values = nil
      if is_leaf
        # Read the values
        values = ary[6 + tree.order, data_count]
      else
        # Read the child addresses
        children = []
        data_count.times do |i|
          child_address = ary[6 + tree.order + i]
          unless child_address > 0
            PEROBS.log.fatal "Child address must be larger than 0"
          end
          children << BTreeNodeLink.new(tree, child_address)
        end
      end

      node = BTreeNode.new(tree, address, parent, is_leaf,
                           prev_sibling, next_sibling, keys, values,
                           children)
      tree.node_cache.insert(node, false)

      node
    end

    # This is a wrapper around BTreeNode::load() that returns a BTreeNodeLink
    # instead of the actual node.
    # @param tree [BTree] The tree the node belongs to
    # @param address [Integer] The address in the blob file.
    # @return [BTreeNodeLink] Link to loaded noded
    def BTreeNode::load_and_link(tree, address)
      BTreeNodeLink.new(tree, BTreeNode::load(tree, address))
    end

    # @return [String] The format used for String.pack.
    def BTreeNode::node_bytes_format(tree)
      # This does not include the 4 bytes for the CRC32 checksum
      "CSSQQQQ#{tree.order}Q#{tree.order + 1}"
    end

    # @return [Integer] The number of bytes needed to store a node.
    def BTreeNode::node_bytes(order)
      1 + # is_leaf
      2 + # actual key count
      2 + # actual value or children count (aka data count)
      8 + # parent address
      8 + # previous sibling address
      8 + # next sibling address
      8 * order + # keys
      8 * (order + 1) + # values or child addresses
      4 # CRC32 checksum
    end

    # Save the node into the blob file.
    def save
      write_node
    end

    # The node address uniquely identifies a BTreeNode.
    def uid
      @node_address
    end

    # Insert or replace the given value by using the key as unique address.
    # @param key [Integer] Unique key to retrieve the value
    # @param value [Integer] value to insert
    def insert(key, value)
      node = self

      # Traverse the tree to find the right node to add or replace the value.
      while node do
        # All nodes that we find on the way that are full will be split into
        # two half-full nodes.
        if node.keys.size >= @tree.order
          node = node.split_node
        end

        # Once we have reached a leaf node we can insert or replace the value.
        if node.is_leaf
          return node.insert_element(key, value)
        else
          # Descend into the right child node to add the value to.
          node = node.children[node.search_key_index(key)]
          node = node.get_node if node
        end
      end

      PEROBS.log.fatal 'Could not find proper node to add to'
    end

    # Return the value that matches the given key or return nil if they key is
    # unknown.
    # @param key [Integer] key to search for
    # @return [Integer or nil] value that matches the key
    def get(key)
      node = self

      while node do
        # Find index of the entry that best fits the key.
        i = node.search_key_index(key)
        if node.is_leaf
          # This is a leaf node. Check if there is an exact match for the
          # given key and return the corresponding value or nil.
          return node.keys[i] == key ? node.values[i] : nil
        end

        # Descend into the right child node to continue the search.
        node = node.children[i]
        node = node.get_node if node
      end

      PEROBS.log.fatal "Could not find proper node to get from while " +
        "looking for key #{key}"
    end

    # Return the key/value pair that matches the given key or the next larger
    # key/value pair with a key that is at least as large as key +
    # min_miss_increment.
    # @param key [Integer] key to search for
    # @param min_miss_increment [Integer] minimum required key increment in
    #        case an exact key match could not be found
    # @return [Integer or nil] value that matches the key
    def get_best_match(key, min_miss_increment)
      node = self

      while node do
        # Find index of the entry that best fits the key.
        i = node.search_key_index(key)
        if node.is_leaf
          # This is a leaf node. Check if there is an exact match for the
          # given key.
          if node.keys[i] == key
            # Return the corresponding value/value pair.
            return [ key, node.values[i] ]
          else
            # No exact key match. Now search the larger keys for the first
            # that is at least key + min_miss_increment large.
            keys = node.keys
            keys_length = keys.length
            while node
              if i >= keys_length
                # We've reached the end of a node. Continue search in next
                # sibling.
                return nil unless (node = node.next_sibling)
                node = node.get_node
                keys = node.keys
                keys_length = keys.length
                i = -1
              elsif keys[i] >= key + min_miss_increment
                # We've found a key that fits the critera. Return the
                # corresponding key/value pair.
                return [ keys[i], node.values[i] ]
              end

              i += 1
            end

            return nil
          end
        end

        # Descend into the right child node to continue the search.
        node = node.children[i]
        node = node.get_node if node
      end

      PEROBS.log.fatal "Could not find proper node to get from while " +
        "looking for key #{key}"
    end

    # Return the value that matches the given key and remove the value from
    # the tree. Return nil if the key is unknown.
    # @param key [Integer] key to search for
    # @return [Integer or nil] value that matches the key
    def remove(key)
      node = self

      while node do
        # Find index of the entry that best fits the key.
        i = node.search_key_index(key)
        if node.is_leaf
          # This is a leaf node. Check if there is an exact match for the
          # given key and return the corresponding value or nil.
          if node.keys[i] == key
            return node.remove_element(i)
          else
            return nil
          end
        end

        # Descend into the right child node to continue the search.
        node = node.children[i]
        node = node.get_node if node
      end

      PEROBS.log.fatal 'Could not find proper node to remove from'
    end

    # Split the current node into two nodes. The upper half of the elements
    # will be moved into a newly created node. This node will retain the lower
    # half.
    # @return [BTreeNodeLink] common parent of the two nodes
    def split_node
      unless @parent
        # The node is the root node. We need to create a parent node first.
        self.parent = link(BTreeNode::create(@tree, nil, false))
        @tree.node_cache.insert(self)
        @parent.set_child(0, self)
        @tree.set_root(@parent)
      end

      # Create the new sibling that will take the 2nd half of the
      # node content.
      sibling = BTreeNode::create(@tree, @parent, @is_leaf, link(self),
                                  @next_sibling)
      # Determine the index of the middle element that gets moved to the
      # parent. The order must be an uneven number, so adding 1 will get us
      # the middle element.
      mid = @tree.order / 2
      # Insert the middle element key into the parent node
      @parent.insert_element(@keys[mid], sibling)
      copy_elements(mid + (@is_leaf ? 0 : 1), sibling)
      trim(mid)

      @parent
    end

    # Insert the given value or child into the current node using the key as
    # index.
    # @param key [Integer] key to address the value or child
    # @param value_or_child [Integer or BTreeNode] value or BTreeNode
    #        reference
    # @return true for insert, false for overwrite
    def insert_element(key, value_or_child)
      if @keys.size >= @tree.order
        PEROBS.log.fatal "Cannot insert into a full BTreeNode"
      end

      i = search_key_index(key)
      @tree.node_cache.insert(self)
      if @keys[i] == key
        # Overwrite existing entries
        @keys[i] = key
        if is_leaf
          @values[i] = value_or_child
        else
          @children[i + 1] = link(value_or_child)
        end

        return false
      else
        # Create a new entry
        @keys.insert(i, key)
        if is_leaf
          @values.insert(i, value_or_child)
        else
          @children.insert(i + 1, link(value_or_child))
        end

        return true
      end
    end

    # Remove the element at the given index.
    def remove_element(index)
      # Delete the key at the specified index.
      unless (key = @keys.delete_at(index))
        PEROBS.log.fatal "Could not remove element #{index} from BigTreeNode " +
          "@#{@node_address}"
      end
      update_branch_key(key) if index == 0

      # Delete the corresponding value.
      @tree.node_cache.insert(self)
      removed_value = @values.delete_at(index)

      if @keys.length < min_keys
        if @prev_sibling && @prev_sibling.parent == @parent
          borrow_from_previous_sibling(@prev_sibling) ||
            @prev_sibling.merge_with_leaf_node(self)
        elsif @next_sibling && @next_sibling.parent == @parent
          borrow_from_next_sibling(@next_sibling) ||
            merge_with_leaf_node(@next_sibling)
        elsif @parent
          PEROBS.log.fatal "Cannot not find adjecent leaf siblings"
        end
      end

      # The merge has potentially invalidated this node. After this method has
      # been called this copy of the node should no longer be used.
      removed_value
    end

    def remove_child(node)
      unless (index = search_node_index(node))
        PEROBS.log.fatal "Cannot remove child #{node.node_address} " +
          "from node #{@node_address}"
      end

      @tree.node_cache.insert(self)
      if index == 0
        # Removing the first child is a bit more complicated as the
        # corresponding branch key is in a parent node.
        key = @keys.shift
        update_branch_key(key)
      else
        # For all other children we can just remove the corresponding key.
        @keys.delete_at(index - 1)
      end

      # Remove the child node link.
      child = @children.delete_at(index)
      # Unlink the neighbouring siblings from the child
      child.prev_sibling.next_sibling = child.next_sibling if child.prev_sibling
      child.next_sibling.prev_sibling = child.prev_sibling if child.next_sibling

      if @keys.length < min_keys
        # The node has become too small. Try borrowing a node from an adjecent
        # sibling or merge with an adjecent node.
        if @prev_sibling && @prev_sibling.parent == @parent
          borrow_from_previous_sibling(@prev_sibling) ||
            @prev_sibling.merge_with_branch_node(self)
        elsif @next_sibling && @next_sibling.parent == @parent
          borrow_from_next_sibling(@next_sibling) ||
            merge_with_branch_node(@next_sibling)
        end
      end

      # Delete the node from the cache and backing store.
      @tree.delete_node(node.node_address)
    end

    def merge_with_leaf_node(node)
      if @keys.length + node.keys.length > @tree.order
        PEROBS.log.fatal "Leaf nodes are too big to merge"
      end

      @tree.node_cache.insert(self)
      @keys += node.keys
      @values += node.values

      node.parent.remove_child(node)
    end

    def merge_with_branch_node(node)
      if @keys.length + 1 + node.keys.length > @tree.order
        PEROBS.log.fatal "Branch nodes are too big to merge"
      end

      index = @parent.search_node_index(node) - 1
      @tree.node_cache.insert(self)
      @keys << @parent.keys[index]
      @keys += node.keys
      node.children.each { |c| c.parent = link(self) }
      @children += node.children

      node.parent.remove_child(node)
    end

    def search_node_index(node)
      index = search_key_index(node.keys.first)
      unless @children[index] == node
        raise RuntimeError, "Child at index #{index} is not the requested node"
      end

      index
    end

    def copy_elements(src_idx, dest_node, dst_idx = 0, count = nil)
      dest_node = dest_node.get_node
      unless count
        count = @tree.order - src_idx
      end
      if dst_idx + count > @tree.order
        PEROBS.log.fatal "Destination too small for copy operation"
      end
      if dest_node.is_leaf != @is_leaf
        PEROBS.log.fatal "Source #{@is_leaf} and destination " +
          "#{dest_node.is_leaf} node must be of same kind"
      end

      @tree.node_cache.insert(dest_node)
      dest_node.keys[dst_idx, count] = @keys[src_idx, count]
      if @is_leaf
        # For leaves we copy the keys and corresponding values.
        dest_node.values[dst_idx, count] = @values[src_idx, count]
      else
        # For branch nodes we copy all but the first specified key (that
        # one moved up to the parent) and all the children to the right of the
        # moved-up key.
        (count + 1).times do |i|
          dest_node.set_child(dst_idx + i, @children[src_idx + i])
        end
      end
    end

    def parent=(p)
      @tree.node_cache.insert(self)
      @parent = p

      p
    end

    def prev_sibling=(node)
      @tree.node_cache.insert(self)
      @prev_sibling = node
      if node.nil? && @is_leaf
        # If this node is a leaf node without a previous sibling we need to
        # register it as the first leaf node.
        @tree.set_first_leaf(BTreeNodeLink.new(@tree, self))
      end

      node
    end

    def next_sibling=(node)
      @tree.node_cache.insert(self)
      @next_sibling = node
      if node.nil? && @is_leaf
        # If this node is a leaf node without a next sibling we need to
        # register it as the last leaf node.
        @tree.set_last_leaf(BTreeNodeLink.new(@tree, self))
      end

      node
    end

    def set_child(index, child)
      @tree.node_cache.insert(self)
      if child
        @children[index] = link(child)
        @children[index].parent = link(self)
      else
        @children[index] = nil
      end

      child
    end

    def trim(idx)
      @tree.node_cache.insert(self)
      @keys.slice!(idx, @keys.length - idx)
      if @is_leaf
        @values.slice!(idx, @values.length - idx)
      else
        @children.slice!(idx + 1, @children.length - idx - 1)
      end
    end

    # Search the keys of the node that fits the given key. The result is
    # either the index of an exact match or the index of the position where
    # the given key would have to be inserted.
    # @param key [Integer] key to search for
    # @return [Integer] Index of the matching key or the insert position.
    def search_key_index(key)
      (@is_leaf ? @keys.bsearch_index { |x| x >= key } :
                  @keys.bsearch_index { |x| x > key }) || @keys.length
    end

    # Iterate over all the key/value pairs in this node and all sub-nodes.
    # @yield [key, value]
    def each
      traverse do |node, position, stack|
        if node.is_leaf && position < node.keys.size
          yield(node.keys[position], node.values[position])
        end
      end
    end

    # This is a generic tree iterator. It yields before it descends into the
    # child node and after (which is identical to before the next child
    # descend). It yields the node, the position and the stack of parent
    # nodes.
    # @yield [node, position, stack]
    def traverse
      # We use a non-recursive implementation to traverse the tree. This stack
      # keeps track of all the known still to be checked nodes.
      stack = [ [ self, 0 ] ]

      while !stack.empty?
        node, position = stack.pop

        # Call the payload method. The position marks where we are in the node
        # with respect to the traversal. 0 means we've just entered the node
        # for the first time and are about to descent to the first child.
        # Position 1 is after the 1st child has been processed and before the
        # 2nd child is being processed. If we have N children, the last
        # position is N after we have processed the last child and are about
        # to return to the parent node.
        yield(node, position, stack)

        if position <= @tree.order
          # Push the next position for this node onto the stack.
          stack.push([ node, position + 1 ])

          if !node.is_leaf && node.children[position]
            # If we have a child node for this position, push the linked node
            # and the starting position onto the stack.
            stack.push([ node.children[position], 0 ])
          end
        end
      end
    end

    # Check consistency of the node and all subsequent nodes. In case an error
    # is found, a message is logged and false is returned.
    # @yield [key, value]
    # @return [nil or Hash] nil in case of errors or a hash with some
    #         statistical information about the tree
    def check(&block)
      stats = Stats.new(nil, 0, 0, 0)

      traverse do |node, position, stack|
        if position == 0
          stats.nodes_count += 1
          if node.parent
            unless node.parent.is_a?(BTreeNodeLink)
              node.error "parent is a #{node.parent.class} instead of a " +
                "BTreeNodeLink"
              return nil
            end
            # After a split the nodes will only have half the maximum keys.
            # For branch nodes one of the split nodes will have even 1 key
            # less as this will become the branch key in a parent node.
            if node.keys.size < min_keys - (node.is_leaf ? 0 : 1)
              node.error "BTreeNode #{node.node_address} has too few keys"
              return nil
            end
          end

          if node.keys.size > @tree.order
            node.error "BTreeNode must not have more then #{@tree.order} " +
              "keys, but has #{node.keys.size} keys"
            return nil
          end

          last_key = nil
          node.keys.each do |key|
            if last_key && key < last_key
              node.error "Keys are not increasing monotoneously: " +
                "#{node.keys.inspect}"
              return nil
            end
            last_key = key
          end

          if node.is_leaf
            if stats.branch_depth
              unless stats.branch_depth == node.tree_level
                node.error "All leaf nodes must have same distance from root "
                return nil
              end
            else
              stats.branch_depth = node.tree_level
            end
            if node.prev_sibling && !node.prev_sibling.is_a?(BTreeNodeLink)
              node.error "prev_sibling is a #{node.prev_sibling.class} " +
                "instead of a BTreeNodeLink"
              return nil
            end
            if node.next_sibling && !node.next_sibling.is_a?(BTreeNodeLink)
              node.error "next_sibling is a #{node.next_sibling.class} " +
                "instead of a BTreeNodeLink"
              return nil
            end
            if node.prev_sibling.nil? && @tree.first_leaf != node
              node.error "Leaf node #{node.node_address} has no previous " +
                "sibling but is not the first leaf of the tree"
              return nil
            end
            if node.next_sibling.nil? && @tree.last_leaf != node
              node.error "Leaf node #{node.node_address} has no next sibling " +
                "but is not the last leaf of the tree"
              return nil
            end
            unless node.keys.size == node.values.size
              node.error "Key count (#{node.keys.size}) and value " +
                "count (#{node.values.size}) don't match"
              return nil
            end
            unless node.children.nil?
              node.error "@children must be nil for a leaf node"
              return nil
            end

            stats.leave_nodes += 1
            stats.leaves += node.keys.length
          else
            unless node.values.nil?
              node.error "@values must be nil for a branch node"
              return nil
            end
            unless node.children.size == node.keys.size + 1
              node.error "Key count (#{node.keys.size}) must be one " +
                "less than children count (#{node.children.size})"
              return nil
            end
            node.children.each_with_index do |child, i|
              unless child.is_a?(BTreeNodeLink)
                node.error "Child #{i} is of class #{child.class} " +
                  "instead of BTreeNodeLink"
                return nil
              end
              unless child.parent.is_a?(BTreeNodeLink)
                node.error "Parent reference of child #{i} is of class " +
                  "#{child.parent.class} instead of BTreeNodeLink"
                return nil
              end
              if child == node
                node.error "Child #{i} points to self"
                return nil
              end
              if stack.include?(child)
                node.error "Child #{i} points to ancester node"
                return nil
              end
              unless child.parent == node
                node.error "Child #{i} does not have parent pointing " +
                  "to this node"
                return nil
              end
              if i > 0
                unless node.children[i - 1].next_sibling == child
                  node.error "next_sibling of node " +
                    "#{node.children[i - 1].node_address} " +
                    "must point to node #{child.node_address}"
                  return nil
                end
              end
              if i < node.children.length - 1
                unless child == node.children[i + 1].prev_sibling
                  node.error "prev_sibling of node " +
                    "#{node.children[i + 1].node_address} " +
                    "must point to node #{child.node_address}"
                  return nil
                end
              end
            end
          end
        elsif position <= node.keys.size
          # These checks are done after we have completed the respective child
          # node with index 'position - 1'.
          index = position - 1
          if !node.is_leaf
            unless node.children[index].keys.last < node.keys[index]
              node.error "Child #{node.children[index].node_address} " +
                "has too large key #{node.children[index].keys.last}. " +
                "Must be smaller than #{node.keys[index]}."
              return nil
            end
            unless node.children[position].keys.first >= node.keys[index]
              node.error "Child #{node.children[position].node_address} " +
                "has too small key #{node.children[position].keys.first}. " +
                "Must be larger than or equal to #{node.keys[index]}."
              return nil
            end
          else
            if block_given?
              # If a block was given, call this block with the key and value.
              unless yield(node.keys[index], node.values[index])
                return nil
              end
            end
          end
        end
      end

      stats
    end

    def is_top?
      @parent.nil? || @parent.parent.nil? || @parent.parent.parent.nil?
    end

    def to_s
      str = ''

      traverse do |node, position, stack|
        if position == 0
          begin
            str += "#{node.parent ? node.parent.tree_prefix + '  +' : 'o'}" +
              "#{node.tree_branch_mark}-" +
              "#{node.keys.first.nil? ? '--' : 'v-'}#{node.tree_summary}\n"
          rescue
            str += "@@@@@@@@@@\n"
          end
        else
          begin
            if node.is_leaf
              if node.keys[position - 1]
                str += "#{node.tree_prefix}  |" +
                  "[#{node.keys[position - 1]}, " +
                  "#{node.values[position - 1]}]\n"
              end
            else
              if node.keys[position - 1]
                str += "#{node.tree_prefix}  #{node.keys[position - 1]}\n"
              end
            end
          rescue
            str += "@@@@@@@@@@\n"
          end
        end
      end

      str
    end

    def tree_prefix
      node = self
      str = ''

      while node
        is_last_child = false
        if node.parent
          is_last_child = node.parent.children.last == node
        else
          # Don't add lines for the top-level.
          break
        end

        str = (is_last_child ? '   ' : '  |') + str
        node = node.parent
        node = node.get_node if node
      end

      str
    end

    def tree_branch_mark
      return '' unless @parent
      '-'
    end

    def tree_summary
      s = " @#{@node_address}"
      if @parent
        begin
          s += " ^#{@parent.node_address}"
        rescue
          s += ' ^@'
        end
      end
      if @prev_sibling
        begin
          s += " <#{@prev_sibling.node_address}"
        rescue
          s += ' <@'
        end
      end
      if @next_sibling
        begin
          s += " >#{@next_sibling.node_address}"
        rescue
          s += ' >@'
        end
      end

      s
    end

    def tree_level
      level = 1
      node = self
      while (node = node.parent)
        level += 1
      end

      level
    end

    def error(msg)
      PEROBS.log.error "Error in BTreeNode @#{@node_address}: #{msg}"
    end

    def write_node
      ary = [
        @is_leaf ? 1 : 0,
        @keys.size,
        @is_leaf ? @values.size : @children.size,
        @parent ? @parent.node_address : 0,
        @prev_sibling ? @prev_sibling.node_address : 0,
        @next_sibling ? @next_sibling.node_address : 0
      ] + @keys + ::Array.new(@tree.order - @keys.size, 0)

      if @is_leaf
        ary += @values + ::Array.new(@tree.order + 1 - @values.size, 0)
      else
        if @children.size != @keys.size + 1
          PEROBS.log.fatal "write_node: Children count #{@children.size} " +
            "is not #{@keys.size + 1}"
        end
        @children.each do |child|
          PEROBS.log.fatal "write_node: Child must not be nil" unless child
        end
        ary += @children.map{ |c| c.node_address } +
          ::Array.new(@tree.order + 1 - @children.size, 0)
      end
      bytes = ary.pack(BTreeNode::node_bytes_format(@tree))
      bytes += [ Zlib::crc32(bytes) ].pack('L')
      @tree.nodes.store_blob(@node_address, bytes)
    end

    private

    def min_keys
      @tree.order / 2
    end

    def link(node)
      return nil if node.nil?

      if node.is_a?(BTreeNodeLink)
        return node
      elsif node.is_a?(BTreeNode) || node.is_a?(Integer)
        return BTreeNodeLink.new(@tree, node)
      else
        PEROBS.log.fatal "Node link must be a BTreeNode, not a #{node.class}"
      end
    end

    # Try to borrow an element from the preceding sibling.
    # @return [True or False] True if an element was borrowed, false
    #         otherwise.
    def borrow_from_previous_sibling(prev_node)
      if prev_node.keys.length - 1 > min_keys
        index = @parent.search_node_index(self) - 1

        @tree.node_cache.insert(self)
        @tree.node_cache.insert(prev_node.get_node)
        @tree.node_cache.insert(@parent.get_node)
        if @is_leaf
          # Move the last key of the previous node to the front of this node
          @keys.unshift(prev_node.keys.pop)
          # Register the new lead key of this node with its parent
          @parent.keys[index] = @keys.first
          # Move the last value of the previous node to the front of this node
          @values.unshift(prev_node.values.pop)
        else
          # For branch nodes the branch key will be the borrowed key.
          @keys.unshift(@parent.keys[index])
          # And the last key of the previous key will become the new branch
          # key for this node.
          @parent.keys[index] = prev_node.keys.pop
          # Move the last child of the previous node to the front of this node
          @children.unshift(node = prev_node.children.pop)
          node.parent = link(self)
        end

        return true
      end

      false
    end

    # Try to borrow an element from the next sibling.
    # @return [True or False] True if an element was borrowed, false
    #         otherwise.
    def borrow_from_next_sibling(next_node)
      if next_node.keys.length - 1 > min_keys
        # The next sibling now has a new lead key that requires the branch key
        # to be updated in the parent node.
        index = next_node.parent.search_node_index(next_node) - 1

        @tree.node_cache.insert(self)
        @tree.node_cache.insert(next_node.get_node)
        @tree.node_cache.insert(next_node.parent.get_node)
        if @is_leaf
          # Move the first key of the next node to the end of the this node
          @keys << next_node.keys.shift
          # Register the new lead key of next_node with its parent
          next_node.parent.keys[index] = next_node.keys.first
          # Move the first value of the next node to the end of this node
          @values << next_node.values.shift
        else
          # For branch nodes we need to get the lead key from the parent of
          # next_node.
          @keys << next_node.parent.keys[index]
          # The old lead key of next_node becomes the branch key in the parent
          # of next_node. And the keys of next_node are shifted.
          next_node.parent.keys[index] = next_node.keys.shift
          # Move the first child of the next node to the end of this node
          @children << (node = next_node.children.shift)
          node.parent = link(self)
        end

        return true
      end

      false
    end

    def update_branch_key(old_key)
      new_key = @keys.first
      return unless (node = @parent)

      while node
        if (index = node.keys.index(old_key))
          node.keys[index] = new_key
          @tree.node_cache.insert(node.get_node)
          return
        end
        node = node.parent
      end

      # The smallest element has no branch key.
    end

  end

end


text:
package com.eaw1805.data.managers.paypal;

import com.eaw1805.data.managers.AbstractManager;
import com.eaw1805.data.managers.beans.PaypalTransactionManagerBean;
import com.eaw1805.data.model.paypal.PaypalTransaction;
import com.eaw1805.data.model.paypal.PaypalUserProfile;
import org.hibernate.Criteria;
import org.hibernate.Session;
import org.hibernate.criterion.Restrictions;

import java.util.List;

/**
 * CRUD operations for PaypalTransaction objects.
 */
public class PaypalTransactionManager extends AbstractManager<PaypalTransaction>
        implements PaypalTransactionManagerBean {

    /**
     * static instance(ourInstance) initialized as null.
     */
    private static PaypalTransactionManager ourInstance = null;

    /**
     * Private constructor suppresses generation of a (public) default constructor.
     */
    public PaypalTransactionManager() {
        // Does nothing
        super();
    }

    /**
     * PaypalTransactionManager is loaded on the first execution of PaypalTransactionManager.getInstance()
     * or the first access to PaypalTransactionManager.ourInstance, not before.
     *
     * @return ourInstance
     */
    public static PaypalTransactionManager getInstance() {
        synchronized (PaypalUserManager.class) {
            if (ourInstance == null) {
                ourInstance = new PaypalTransactionManager();
            }
        }

        return ourInstance;
    }

    /**
     * get the Paypal Transaction from the database that corresponds to the input id.
     *
     * @param entityID the id of the Entity object.
     * @return an Entity object.
     */
    @Override
    public PaypalTransaction getByID(int entityID){
        return super.getByID(new PaypalTransaction(), entityID);
    }

    /**
     * Delete the input PaypalTransaction from the database.
     *
     * @param entity the PaypalTransaction tha we want to delete
     */
    @Override
    public void delete(PaypalTransaction entity){
        super.delete(entity, entity.getId());
    }

    /**
     * Listing all the PaypalTransaction from the database.
     *
     * @return a list of all the PaypalTransaction that exist inside the table Avatar.
     */
    @Override
    public List<PaypalTransaction> list(){
        return super.list(new PaypalTransaction());
    }

    /**
     * get the Paypal Transaction from the database that corresponds to the input id.
     *
     * @param entityID the id of the Entity object.
     * @return an Entity object.
     */
    @Override
    public PaypalTransaction getByPayerID(final PaypalUserProfile entityID){
        final Session session = getSessionFactory().getCurrentSession();
        final Criteria criteria = session.createCriteria(PaypalTransaction.class);
        criteria.add(Restrictions.eq("payer", entityID));
        return (PaypalTransaction) criteria.uniqueResult();
    }

    /**
     * get the Paypal Transaction from the database that corresponds to the input id.
     *
     * @param entityID the String of the Entity object.
     * @return an Entity object.
     */
    @Override
    public  PaypalTransaction getByPaypalTransactionlID(final String entityID){
        final Session session = getSessionFactory().getCurrentSession();
        final Criteria criteria = session.createCriteria(PaypalTransaction.class);
        criteria.add(Restrictions.eq("transactionId", entityID));
        return (PaypalTransaction) criteria.uniqueResult();
    }

}


text: A High Performance Computing implementation of Shear Sort with OpenMPI


text:
package no.antares.dbunit.model

/** Model class that maps to table with some numerical type columns */
case class TstNumerical(
    var colWithInt: java.lang.Integer,
    var colWithFloat: java.lang.Float,
    var colWithDate: java.util.Date
) {
  def this()	= this( null, null, null );	// auxillary constructor
}

object TstNumerical {
  def sqlDropScript	= "drop table tst_numericals"
	def sqlCreateScript	= """create table tst_numericals (
    COL_WITH_INT integer PRIMARY KEY,
    COL_WITH_FLOAT float,
    COL_WITH_DATE date
  );
  """;
  def sqlSelectAll	= "SELECT * FROM tst_numericals"
  def sqlSelectWhereInt( value: java.lang.Integer )	= "SELECT * FROM tst_numericals WHERE COL_WITH_INT=" + value;

	def oldDbUnitXmlTestData	= """<?xml version='1.0' encoding='UTF-8'?>
  <dataset>
    <table name="tst_numericals">
      <column>COL_WITH_INT</column>
      <column>COL_WITH_FLOAT</column>
      <column>COL_WITH_DATE</column>
      <row>
        <value>456</value>
        <value>0.959106</value>
        <value>2004-09-30</value>
      </row>
      <row>
        <value>-1</value>
        <value>3.14</value>
        <value>2005</value>
      </row>
      <!-- row>
        <null/>
        <null/>
        <null/>
      </row> -->
    </table>
  </dataset>"""
  ;

  // below I tried to jog the json producer by switching columns, order etc.
  def jsonTestData	= """{
	"dataset": {
		"tstNumericals": [
        { "colWithInt": 123 },
        { "colWithFloat": 3.141592658,
          "colWithInt": 234
        },
        { "colWithDate": "2004-09-30",
          "colWithInt": -3
        },
        { "colWithInt": 456,
          "colWithFloat": -2,
          "colWithDate": "2114-12-24"
        }
      ]
    }
  }"""
  ;
/* TODO:
 "colWithFloat": null,
  "colWithDate": "2005",
  "colWithInt": 33
*/
}


text:
uitest
======

This framework makes it easier to build web tests for an application in a style similar to traditional unit testing.

By treating the jsp files and their Spring controllers together as the "unit" under test, we can exercise their behaviour from the user's point of view, without needing complex stubbed services to stand-in for the backend.

**Easy to read**
* Everything you see in the test code is directly relevant to the behaviour being exercised
* No "magic numbers" or other special arguments need to be passed in to trigger desired behaviours

**Fast to write**
* Default behaviour is defined outside of the test method, so each test only need specify the things that are different

**High cohesion, loose coupling**
* Default stub behaviour is shared between all tests in a single test class, and set up right there in the test class: nothing is defined outside (unless you want it!)
* Setting up specific stub behaviour needed for just one test has no impact on other tests
* Impact from changes to production code is minimized: only those tests that actually execised the changed code need to be updated

**Fast to execute**
* Tests can run quickly because each one jumps in directly at the page being tested, with the desired state ready to go
* No logging in, or navigating through pages to get there
* It's easy to use HTMLUnit for its greater speed, but swap it for a real browser while debugging

**Familiar syntax**
* Expectations and behaviours are defined with EasyMock
* Selenium WebDriver for navigating in the browser and reading page content

```java

    @Test
    public void showHomePage() throws Exception {
        expect(newsService.getLatestNews()).andReturn("We're now testing with UI Test!");

        replayAll();
        driver.get(getBaseUrl() + "/");
        verifyAll();

        assertThat(driver.getTitle(), is("Home - UI Test Demo"));
        assertThat(driver.findElement(By.id("news")).getText(), is("We're now testing with UI Test!"));
    }
```

Where do I start?
-----------------
Download the source, and you'll find two maven projects.
Install uitest, and then have a look at HomeUITest.java in the uitest-demo project. The test is ready to run direct from your IDE, or via maven.


text:
package com.annimon.ownlang.modules.yaml;

import com.annimon.ownlang.lib.*;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import org.yaml.snakeyaml.DumperOptions;
import org.yaml.snakeyaml.Yaml;

public final class yaml_encode implements Function {

    @Override
    public Value execute(Value... args) {
        Arguments.checkOrOr(1, 2, args.length);
        try {
            final Object root = process(args[0]);
            final DumperOptions options = new DumperOptions();
            if (args.length == 2 && args[1].type() == Types.MAP) {
                configure(options, ((MapValue) args[1]));
            }
            final String yamlRaw = new Yaml(options).dump(root);
            return new StringValue(yamlRaw);
        } catch (Exception ex) {
            throw new RuntimeException("Error while creating yaml", ex);
        }
    }

    private void configure(DumperOptions options, MapValue map) {
        map.ifPresent("allowReadOnlyProperties", value ->
                options.setAllowReadOnlyProperties(value.asInt() != 0));
        map.ifPresent("allowUnicode", value ->
                options.setAllowUnicode(value.asInt() != 0));
        map.ifPresent("canonical", value ->
                options.setCanonical(value.asInt() != 0));
        map.ifPresent("defaultFlowStyle", value ->
                options.setDefaultFlowStyle(DumperOptions.FlowStyle.valueOf(value.asString())));
        map.ifPresent("defaultScalarStyle", value ->
                options.setDefaultScalarStyle(DumperOptions.ScalarStyle.valueOf(value.asString())));
        map.ifPresent("explicitEnd", value ->
                options.setExplicitEnd(value.asInt() != 0));
        map.ifPresent("explicitStart", value ->
                options.setExplicitStart(value.asInt() != 0));
        map.ifPresent("indent", value ->
                options.setIndent(value.asInt()));
        map.ifPresent("indicatorIndent", value ->
                options.setIndicatorIndent(value.asInt()));
        map.ifPresent("lineBreak", value ->
                options.setLineBreak(DumperOptions.LineBreak.valueOf(value.asString())));
        map.ifPresent("prettyFlow", value ->
                options.setPrettyFlow(value.asInt() != 0));
        map.ifPresent("splitLines", value ->
                options.setSplitLines(value.asInt() != 0));
        map.ifPresent("width", value ->
                options.setWidth(value.asInt()));
    }

    private Object process(Value val) {
        switch (val.type()) {
            case Types.ARRAY:
                return process((ArrayValue) val);
            case Types.MAP:
                return process((MapValue) val);
            case Types.NUMBER:
                return val.raw();
            case Types.STRING:
                return val.asString();
            default:
                return null;
        }
    }

    private Object process(MapValue map) {
        final Map<String, Object> result = new LinkedHashMap<>();
        for (Map.Entry<Value, Value> entry : map) {
            final String key = entry.getKey().asString();
            final Object value = process(entry.getValue());
            result.put(key, value);
        }
        return result;
    }

    private Object process(ArrayValue array) {
        final List<Object> result = new ArrayList<>();
        for (Value value : array) {
            result.add(process(value));
        }
        return result;
    }
}


text:
export class Greeting {

  constructor(public message: string) {
  }
}


text:
#include <iostream>

#include "vtrc/server/application.h"
#include "vtrc/server/listener/tcp.h"
#include "vtrc/server/channels.h"

#include "vtrc/common/connection-iface.h"
#include "vtrc/common/closure-holder.h"
#include "vtrc/common/pool-pair.h"
#include "vtrc/common/stub-wrapper.h"

#include "protocol/hello-events.pb.h"   /// hello protocol
#include "google/protobuf/descriptor.h" /// for descriptor( )->full_name( )
#include "boost/lexical_cast.hpp"

#include "vtrc-system.h"
#include "../protocol/http-header.hpp"

#include <set>

using namespace vtrc;

namespace {

namespace vc = vtrc::common;

std::set<std::string> run_params;

class http_lowlevel_server: vc::lowlevel::protocol_layer_iface {

    typedef vc::lowlevel::protocol_layer_iface::message_type message_type;

    typedef http::header_parser             parser_type;
    typedef vtrc::shared_ptr<parser_type>   parser_sptr;
    typedef std::deque<parser_sptr>         requests_container;

    vc::protocol_accessor   *pa_;
    requests_container       container_;
    parser_sptr              current_header_;

public:

    http_lowlevel_server( )
        :pa_(NULL)
    { }

    static
    vc::lowlevel::protocol_layer_iface *create( )
    {
        return new http_lowlevel_server;
    }

    void reset_current( )
    {
        current_header_ = vtrc::make_shared<parser_type>( );
    }

    void init( vc::protocol_accessor *pa,
               vc::system_closure_type ready_cb )
    {
        pa_ = pa;
        reset_current( );
        ready_cb( VTRC_SYSTEM::error_code( ) );
        pa->ready( true );
    }

    std::string serialize_lowlevel( const lowlevel_unit &mess )
    {
        return pack_message( mess );
    }

    std::string serialize_message( const message_type *mess )
    {
        return mess->SerializeAsString( );
    }

    void parse_message( const std::string &data, message_type *mess )
    {
        mess->ParseFromString( data );
    }

    std::string pack_message( const rpc::lowlevel_unit &mess )
    {
        std::string d = http::lowlevel2http( mess );
        if( run_params.find( "-d" ) != run_params.end( ) ) {
            std::cout << "========\n" << d << "\n";
        }
        return d;
    }

    void process_data( const char *data, size_t length )
    {
        bool ok = false;

        //std::cout << std::string( data, length );

        while( length ) {
            size_t r = current_header_->push( data, data + length );
            length -= r;
            data   += r;
            if( current_header_->ready( ) ) {
                container_.push_back( current_header_ );
                ok = true;
                reset_current( );
            }
        }
        if( ok ) {
            pa_->message_ready( );
        }
    }

    size_t queue_size( ) const
    {
        return container_.size( );
    }

    bool pop_proto_message( vtrc::rpc::lowlevel_unit &result )
    {
        bool res = http::http2lowlevel( *container_.front( ), result );
        container_.pop_front( );
        return res;
    }

    void close( ) { }

};

class  hello_service_impl: public howto::hello_events_service {

    typedef howto::hello_events_service super_type;

    common::connection_iface *cl_;

    void generate_events(::google::protobuf::RpcController* /*controller*/,
                 const ::howto::request_message*            /*request*/,
                 ::howto::response_message*                 /*response*/,
                 ::google::protobuf::Closure* done)
    {
        common::closure_holder ch( done ); /// instead of done->Run( );
        typedef howto::hello_events_Stub stub_type;

        using   server::channels::unicast::create_callback_channel;
        using   server::channels::unicast::create_event_channel;

        { // do event. send and dont wait response
            common::rpc_channel *ec =
                            create_event_channel( cl_->shared_from_this( ) );

            common::stub_wrapper<stub_type> event( ec );
            event.call( &stub_type::hello_event );
        }

        { // do callback. wait response from client.
            common::rpc_channel *cc =
                            create_callback_channel( cl_->shared_from_this( ) );

            common::stub_wrapper<stub_type> callback( cc );
            howto::event_res response;

            callback.call_response( &stub_type::hello_callback, &response );

            std::cout << "Client string: "
                      << response.hello_from_client( )
                      << "\n"
                      ;
        }
    }

    void say_hello(::google::protobuf::RpcController* controller,
                         const ::howto::request_message* request,
                         ::howto::response_message* response,
                         ::google::protobuf::Closure* done)
    {
        common::closure_holder ch( done ); /// instead of done->Run( );
        response->set_hello( "Hello!" );
    }

public:

    hello_service_impl( common::connection_iface *cl )
        :cl_(cl)
    { }

    static std::string const &service_name(  )
    {
        return super_type::descriptor( )->full_name( );
    }
};

class hello_application: public server::application {

    typedef common::rpc_service_wrapper     wrapper_type;
    typedef vtrc::shared_ptr<wrapper_type>  wrapper_sptr;

public:

    hello_application( common::pool_pair &pp )
        :server::application(pp)
    { }

    wrapper_sptr get_service_by_name( common::connection_iface* connection,
                                      const std::string &service_name )
    {
        if( service_name == hello_service_impl::service_name( ) ) {

             hello_service_impl *new_impl = new hello_service_impl(connection);

             return vtrc::make_shared<wrapper_type>( new_impl );

        }
        return wrapper_sptr( );
    }

};

} // namespace

int main( int argc, const char **argv )
{

    const char *address = "127.0.0.1";
    unsigned short port = 56560;

    for( int i=0; i<argc; ++i ) {
        run_params.insert( argv[i] );
    }

    if( argc > 2 ) {
        address = argv[1];
        port = boost::lexical_cast<unsigned short>( argv[2] );
    } else if( argc > 1 ) {
        port = boost::lexical_cast<unsigned short>( argv[1] );
    }

    common::pool_pair pp( 0, 1 );
    hello_application app( pp );

    try {

        rpc::session_options opts = vtrc::common::defaults::session_options( );
        //opts.set_read_buffer_size( 1 ); // test

        vtrc::shared_ptr<server::listener>
                tcp( server::listeners::tcp::create( app, opts,
                                                     address, port ) );

        tcp->assign_lowlevel_protocol_factory( &http_lowlevel_server::create );

        tcp->start( );

        pp.get_io_pool( ).attach( );

    } catch( const std::exception &ex ) {
        std::cerr << "Hello, world failed: " << ex.what( ) << "\n";
    }

    pp.join_all( );

    /// make valgrind happy.
    google::protobuf::ShutdownProtobufLibrary( );

    return 0;
}


text:
package com.yingt.uimain.adapter;

import android.animation.ObjectAnimator;
import android.content.Context;
import android.support.v7.widget.RecyclerView;
import android.view.View;
import android.widget.RelativeLayout;
import android.widget.TextView;

import com.github.aakira.expandablelayout.Utils;
import com.yingt.uimain.R;

/**
 * Created by laihuan.wan on 2017/7/11 0011.
 */

public class YtBaseExpandAdapter extends BaseExpandAdapter{

    private String title;

    public YtBaseExpandAdapter(Context context){
        super(context);
    }

    @Override
    public int getTitleLayoutResId() {
        return R.layout.yingt_uimain_base_expand_title;
    }

    @Override
    public int getContentLayoutResId() {
        return 0;
    }

    @Override
    public YtBaseExpandHolder onCreateViewHolder(View view, int position) {
        super.onCreateViewHolder(view, position);
        setTitleText("盈通 Expand"); // 默认标题栏文本
        setExpandState(false);// 默认关闭状态,因为本来就没数据
        return new YtBaseExpandHolder(view);
    }

    @Override
    public void onBindViewHolder(RecyclerView.ViewHolder viewHolder, int position) {
        final YtBaseExpandHolder holder = (YtBaseExpandHolder) viewHolder;
        holder.textView.setText(title); // 动态设置标题栏,用于上层的设置
        holder.buttonLayout.setRotation(isExpandState() ? 0f : -90f);// 初始化指示器默认的方向
        super.onBindViewHolder(viewHolder, position);
    }

    @Override
    public void onExpandObserver(RecyclerView.ViewHolder viewHolder, int position, boolean isOpenState) {
        YtBaseExpandHolder holder = (YtBaseExpandHolder) viewHolder;
        if (isOpenState) {
            createRotateAnimator(holder.buttonLayout, -90f, 0f).start();
        } else {
            createRotateAnimator(holder.buttonLayout, 0f, -90f).start();
        }
        if(onExpandListener != null)
            onExpandListener.onExpand(isOpenState, position);
    }

    private ObjectAnimator createRotateAnimator(final View target, final float from, final float to) {
        ObjectAnimator animator = ObjectAnimator.ofFloat(target, "rotation", from, to);
        animator.setDuration(300);
        animator.setInterpolator(Utils.createInterpolator(Utils.LINEAR_INTERPOLATOR));
        return animator;
    }

    @Override
    public void onClickTitle(View view) {
        super.onClickTitle(view);
    }

    public void setTitleText(String text) {
        this.title = text;
    }

    protected class YtBaseExpandHolder extends BaseExpandAdapter.BaseExpandHolder {
        public TextView textView;
        public RelativeLayout buttonLayout;

        public YtBaseExpandHolder(View v) {
            super(v);
            textView = (TextView) v.findViewById(R.id.textView);
            buttonLayout = (RelativeLayout) v.findViewById(R.id.button);

        }
    }

    private OnExpandListener onExpandListener;
    public void setOnExpandListener(OnExpandListener onExpandListener){
        this.onExpandListener = onExpandListener;
    }
    public interface OnExpandListener{
        void onExpand(boolean isExpand, int position);
    }
}


text:
The basic steps when preparing a challenge are:

* A Docker image is built from the `challenge` directory. For the simplest challenges, replacing `challenge/chal.c` is sufficient.
* Edit `challenge/Dockerfile` to change the commandline or the files you want to include.
* To try the challenge locally, you will need to
  * create a a local cluster with `kctf cluster create --type kind --start $configname`
  * build the challenge binary with `make -C challenge`
  * and then deploy the challenge with `kctf chal start`
* To access the challenge, create a port forward with `kctf chal debug port-forward` and connect to it via `nc localhost PORT` using the printed port.
* Check out `kctf chal <tab>` for more commands.

## Directory layout

The following files/directories are available:

### /challenge.yaml

`challenge.yaml` is the main configuration file. You can use it to change
settings like the name and namespace of the challenge, the exposed ports, the
proof-of-work difficulty etc.
For documentation on the available fields, you can run `kubectl explain challenge` and
`kubectl explain challenge.spec`.

### /challenge

The `challenge` directory contains a Dockerfile that describes the challenge and
any challenge files. This template comes with a Makefile to build the challenge,
which is the recommended way for pwnables if the deployed binary matters, e.g.
if you hand it out as an attachment for ROP gadgets.
If the binary layout doesn't matter, you can build it using an intermediate
container as part of the Dockerfile similar to how the chroot is created.

### /healthcheck

The `healthcheck` directory is optional. If you don't want to write a healthcheck, feel free to delete it. However, we strongly recommend that you implement a healthcheck :).

We provide a basic healthcheck skeleton that uses pwntools to implement the
healthcheck code. The only requirement is that the healthcheck replies to GET
requests to http://$host:45281/healthz with either a success or an error status
code.

In most cases, you will only have to modify `healthcheck/healthcheck.py`.

## API contract

Ensure your setup fulfills the following requirements to ensure it works with kCTF:

* Verify `kctf_setup` is used as the first command in the CMD instruction of your `challenge/Dockerfile`.
* You can do pretty much whatever you want in the `challenge` directory but:
* We strongly recommend using nsjail in all challenges. While nsjail is already installed, you need to configure it in `challenge/nsjail.cfg`. For more information on nsjail, see the [official website](https://nsjail.dev/).
* Your challenge receives connections on port 1337. The port can be changed in `challenge.yaml`.
* The healthcheck directory is optional.
  * If it exists, the image should run a webserver on port 45281 and respond to `/healthz` requests.


text:
import {CanActivate, Router, RouterState, ActivatedRouteSnapshot, RouterStateSnapshot,} from "@angular/router";
import { AuthService } from "../pages/curtain/login/auth.service";
import { Injectable } from "@angular/core";

@Injectable()
export class LoggedInGuard implements CanActivate {
  constructor(private authService: AuthService,
              private router: Router) {
  }

  canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): boolean {
    // let isLoggedIn = this.authService.isLoggedIn();
    // let targetState = state.url;
    // let result = true;
    //
    // if (targetState == '/login' && isLoggedIn){
    //   result = false;
    //   if (this.router.routerState.snapshot.url != "/courses-list"){
    //     history.back(-1)
    //   }
    // } else
    //   if (targetState != '/login' && !isLoggedIn){
    //   this.router.navigate(['/login']);
    // }
    // return result;
    return true;
  }
}


text:
package com.wixpress.petri.laboratory;

import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.wixpress.petri.experiments.domain.*;
import com.wixpress.petri.experiments.jackson.ObjectMapperFactory;
import com.wixpress.petri.laboratory.dsl.ExperimentMakers;
import filters.AdditionalFilter;
import org.junit.Test;

import java.io.IOException;
import java.util.Map;

import static com.natpryce.makeiteasy.MakeItEasy.an;
import static com.natpryce.makeiteasy.MakeItEasy.with;
import static com.wixpress.petri.laboratory.dsl.ExperimentMakers.filters;
import static java.util.Arrays.asList;
import static org.hamcrest.Matchers.is;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;

public class FiltersExtenderIT {

    @Test
    public void experimentsCanBeSerializedWithExtendedFilterTypesFromClassPath() throws IOException {
        ObjectMapper objectMapper = ObjectMapperFactory.makeObjectMapper();
        AdditionalFilter additionalFilterFromClasspath = new AdditionalFilter();
        Experiment experimentWithNewFilterType = an(ExperimentMakers.Experiment, with(filters,
                asList(new FirstTimeVisitorsOnlyFilter(), additionalFilterFromClasspath)
        )).make();
        String json = objectMapper.writeValueAsString(experimentWithNewFilterType);
        Experiment deSerialized = objectMapper.readValue(json, new TypeReference<Experiment>() {
        });
        assertThat(deSerialized, is(experimentWithNewFilterType));
    }

    @Test
    public void filterTypesCanBeExtendedWithDynamicallyLoadedClassesFromMatchingJars() throws IOException {
        //relevant jar is committed as 'sample-extended-filters.jar' under petri-plugins folder
        //(once api module is extracted this jar can be created before petri-core and copied there, same as in the e2e-tests)

        FilterTypeIdResolver.useDynamicFilterClassLoading("dynamic.filters");

        Map<String, Class<? extends Filter>> extendedTypes = ExtendedFilterTypesIds.extendedTypes();
        assertTrue("SomeCustomFilter was not dynamically loaded", extendedTypes.containsKey("SomeCustomFilter"));
        assertThat(extendedTypes.get("SomeCustomFilter").getName(), is("dynamic.filters.SomeCustomFilter"));
    }

}


text:
package de.quist.app.maps.google;

import de.quist.app.maps.utils.Wrapper;

class Circle extends Wrapper<com.google.android.gms.maps.model.Circle> implements de.quist.app.maps.model.Circle {

    static final Mapper<de.quist.app.maps.model.Circle, Circle, com.google.android.gms.maps.model.Circle> MAPPER = new DefaultMapper<de.quist.app.maps.model.Circle, Circle, com.google.android.gms.maps.model.Circle>() {

        @Override
        public Circle createWrapper(com.google.android.gms.maps.model.Circle original) {
            return original != null ? new Circle(original) : null;
        }
    };

    private Circle(com.google.android.gms.maps.model.Circle original) {
        super(original);
    }

    @Override
    public void remove() {
        original.remove();
    }

    @Override
    public String getId() {
        return original.getId();
    }

    @Override
    public void setCenter(de.quist.app.maps.model.LatLng center) {
        original.setCenter(LatLng.MAPPER.unwrap(center));
    }

    @Override
    public de.quist.app.maps.model.LatLng getCenter() {
        return LatLng.MAPPER.wrap(original.getCenter());
    }

    @Override
    public void setRadius(double radius) {
        original.setRadius(radius);
    }

    @Override
    public double getRadius() {
        return original.getRadius();
    }

    @Override
    public void setStrokeWidth(float width) {
        original.setStrokeWidth(width);
    }

    @Override
    public float getStrokeWidth() {
        return original.getStrokeWidth();
    }

    @Override
    public void setStrokeColor(int color) {
        original.setStrokeColor(color);
    }

    @Override
    public int getStrokeColor() {
        return original.getStrokeColor();
    }

    @Override
    public void setFillColor(int color) {
        original.setFillColor(color);
    }

    @Override
    public int getFillColor() {
        return original.getFillColor();
    }

    @Override
    public void setZIndex(float zIndex) {
        original.setZIndex(zIndex);
    }

    @Override
    public float getZIndex() {
        return original.getZIndex();
    }

    @Override
    public void setVisible(boolean visible) {
        original.setVisible(visible);
    }

    @Override
    public boolean isVisible() {
        return original.isVisible();
    }

    @Override
    public void setPosition(de.quist.app.maps.model.LatLng latLng) {
        original.setCenter(LatLng.MAPPER.unwrap(latLng));
    }

    @Override
    public de.quist.app.maps.model.LatLng getPosition() {
        return LatLng.MAPPER.wrap(original.getCenter());
    }
}


text:
package ca.pfv.spmf.algorithms.sequentialpatterns.fournier2008_seqdim;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import ca.pfv.spmf.algorithms.sequentialpatterns.fournier2008_seqdim.kmeans_for_fournier08.Cluster;
import ca.pfv.spmf.algorithms.sequentialpatterns.fournier2008_seqdim.multidimensionalsequentialpatterns.AlgoSeqDim;

/**
 * Implementation of a sequence database as used by the SeqDim and Fournier-Vier (2008) algorithms.
 * Each sequence need to hvae a unique ID.
 * See examples in the /test/ directory for the format of input files. that can be read by this class.
 *
 * @see AlgoFournierViger08
 * @see AlgoSeqDim
 * @see Sequence
*  @author Philippe Fournier-Viger
 */
public class SequenceDatabase{

	/** List of sequences */
	private final List<Sequence> sequences = new ArrayList<Sequence>();

	/** for the Fournier08 algorithm, the cluster that was used to do the projection
	  that results in this database. */
	private Cluster cluster = null;

	/**
	 * Load a sequence database from an input file
	 * @param path the input file path
	 * @throws IOException exception if error reading file
	 */
	public void loadFile(String path) throws IOException {
		// we will read line by line
		String thisLine;
		BufferedReader myInput = null;
		try {
			FileInputStream fin = new FileInputStream(new File(path));
			myInput = new BufferedReader(new InputStreamReader(fin));
			// For each line (sequence) until end of file
			while ((thisLine = myInput.readLine()) != null) {
				// if the line is  a comment, is  empty or is a
				// kind of metadata
				if (thisLine.isEmpty() == true ||
						thisLine.charAt(0) == '#' || thisLine.charAt(0) == '%'
								|| thisLine.charAt(0) == '@') {
					continue;
				}

				// process this line (sequence) splitted into tokens
				processSequence(thisLine.split(" "));
			}
		} catch (Exception e) {
			e.printStackTrace();
		}finally {
			// Close the input file
			if(myInput != null){
				myInput.close();
			}
	    }
	}

	/**
	 * Process a line from the input file, splitted into tokens.
	 * @param tokens  a list of tokens (String).
	 */
	void processSequence(String[] tokens) {	//
		// create a new Sequence
		Sequence sequence = new Sequence(sequences.size());
		// Create an itemset that will be used to store items
		// from the first itemset and eventually the next itemsets.
		Itemset itemset = new Itemset();
		// for each tokens
		for(String integer:  tokens){
			// if this token is a timestamp
			if(integer.codePointAt(0) == '<'){
				// we extract the timestamp and set it as the timestamp
				// of the current itemset
				String value = integer.substring(1, integer.length()-1);
				itemset.setTimestamp(Long.parseLong(value));
			}else if(integer.equals("-1")){
				// If -1, this indicate the end of the current itemset,
				// so we add the itemset to the sequence, and
				// create a new itemset.
				sequence.addItemset(itemset);
				itemset = new Itemset();
			}else if(integer.equals("-2")){
				// If -2, it indicates the end of a sequence
				// If the last itemset is not empty, it means
				// that a -1 was missing.
				if(itemset.size() >0){
					// in this case we add the current itemset to the sequence
					// because it is not empty
					sequence.addItemset(itemset);
					itemset = new Itemset();
				}
				// finally, we add the sequence to the sequence database
				sequences.add(sequence);
			}else{
				// otherwise, check if it is
				// an item with the format : id(value)  where
				// id is the item ID and value is a value associated with the item

				// we find the position of the left parenthesis
				int indexLeftParenthesis = integer.indexOf("(");
				// if there is a left parenthesis
				if(indexLeftParenthesis != -1){
					// we find the position of the left parenthesis
					int indexRightParenthesis = integer.indexOf(")");
					// we extract the value
					int value = Integer.parseInt(integer.substring(indexLeftParenthesis+1, indexRightParenthesis));
					// we extract the item ID
					integer = integer.substring(0, indexLeftParenthesis);
					// We create a new item with the item ID and the value
					ItemValued item = new ItemValued(Integer.parseInt(integer), value);
					// The item is then added to the current itemset
					itemset.addItem(item);
				}else{
					// Otherwise, it is just a regular item without value.

					//The item ID is extracted
					ItemSimple item = new ItemSimple(Integer.parseInt(integer));
					// If the item is not already in this itemset
					if(!itemset.getItems().contains(item)){
						// we add it to the itemset.
						itemset.addItem(item);
					}
				}

			}
		}
	}

	/**
	 * Add a sequence to the sequence database
	 * @param sequence the sequence
	 */
	public void addSequence(Sequence sequence){
		sequences.add(sequence);
	}

	/**
	 * Print this sequence database to System.out
	 */
	public void print(){
		System.out.println("============  Context ==========");
		// for each sequence
		for(Sequence sequence : sequences){
			// print the sequence
			System.out.print(sequence.getId() + ":  ");
			sequence.print();
			System.out.println("");
		}
	}

	/**
	 * Get a string representation of this sequence
	 */
	public String toString(){
		// create a string buffer
		StringBuilder r = new StringBuilder();
		// for each sequence
		for(Sequence sequence : sequences){
			// append the sequence id
			r.append(sequence.getId());
			r.append(":  ");
			// append the itemsets of the sequence
			r.append(sequence.toString());
			r.append('\n');
		}
		// return the string
		return r.toString();
	}

	/**
	 * Get the number of sequences.
	 * @return an integer
	 */
	public int size(){
		return sequences.size();
	}

	/**
	 * Get the list of sequences.
	 * @return a List of sequences.
	 */
	public List<Sequence> getSequences() {
		return sequences;
	}

	/**
	 * Get the set of sequence IDs.
	 * @return a Set of Integer.
	 */
	public Set<Integer> getSequenceIDs() {
		Set<Integer> set = new HashSet<Integer>();
		for(Sequence sequence : getSequences()){
			set.add(sequence.getId());
		}
		return set;
	}

	/**
	 * Get the cluster that was used to create this projected sequence database.
	 * @return the Cluster or null if none
	 */
	Cluster getCluster() {
		return cluster;
	}

	/**
	 * Set the cluster that was used to create this projected sequence database.
	 * @param cluster the Cluster
	 */
	void setCluster(Cluster cluster) {
		this.cluster = cluster;
	}
}