<commit_before>// Copyright 2014, The Serviced Authors. All rights reserved.
// Use of this source code is governed by a
// license that can be found in the LICENSE file.

package registry

import (
	"github.com/zenoss/glog"
	"github.com/zenoss/serviced/coordinator/client"
)

type registryType struct {
	getPath func(nodes ...string) string
}

type WatchError func(path string, err error)

//Add key to the registry.  Returns the path of the key in the registry
func (r *registryType) AddKey(conn client.Connection, key string) (string, error) {
	path := r.getPath(key)
	if err := conn.CreateDir(path); err != nil {
		return "", err
	}
	return path, nil
}

func (r *registryType) WatchKey(conn client.Connection, key string, processChildren func(conn client.Connection, childPaths ...string), errorHandler WatchError) error {
	keyPath := r.getPath(key)
	return watch(conn, keyPath, processChildren, errorHandler)
}

func (r *registryType) WatchRegistry(conn client.Connection, processChildren func(conn client.Connection, childPaths ...string), errorHandler WatchError) error {
	path := r.getPath()
	return watch(conn, path, processChildren, errorHandler)
}

//Add VhostEndpoint to the key in registry.  Returns the path of the node in the registry
func (r *registryType) addItem(conn client.Connection, key string, nodeID string, node client.Node) (string, error) {
	path := r.getPath(key, nodeID)

	if err := r.ensureDir(conn, r.getPath(key)); err != nil {
		return "", err
	}

	if err := r.ensureDir(conn, r.getPath(nodeID)); err != nil {
		return "", err
	}

	//TODO: make ephemeral
	glog.Infof("Adding to %s: %#v", path, node)
	if err := conn.Create(path, node); err != nil {
		return "", err
	}
	return path, nil
}

func (r *registryType) ensureDir(conn client.Connection, path string) error {
	if exists, err := conn.Exists(path); err != nil {
		return err
	} else if !exists {
		if err := conn.CreateDir(path); err != nil {
			return err
		}
	}
	return nil
}

func watch(conn client.Connection, path string, processChildren func(conn client.Connection, childPaths ...string), errorHandler WatchError) error {
	for {
		nodeIDs, event, err := conn.ChildrenW(path)
		if err != nil {
			glog.Errorf("Could not watch  %s: %s", path, err)
			defer errorHandler(path, err)
			return err
		}
		processChildren(conn, nodeIDs...)
		//This blocks until a change happens under the key
		<-event
	}
	return nil
}

func (r *registryType) watchItem(conn client.Connection, path string, nodeType client.Node, processNode func(conn client.Connection,
	node client.Node), errorHandler WatchError) error {
	for {
		event, err := conn.GetW(path, nodeType)
		if err != nil {
			glog.Errorf("Could not watch %s: %s", path, err)
			defer errorHandler(path, err)
			return err<commit_msg>provide full zk paths to watch.processChildren() instead of nodeIDs<commit_after>// Copyright 2014, The Serviced Authors. All rights reserved.
// Use of this source code is governed by a
// license that can be found in the LICENSE file.

package registry

import (
	"github.com/zenoss/glog"
	"github.com/zenoss/serviced/coordinator/client"

	"fmt"
)

type registryType struct {
	getPath func(nodes ...string) string
}

type WatchError func(path string, err error)

//Add key to the registry.  Returns the path of the key in the registry
func (r *registryType) AddKey(conn client.Connection, key string) (string, error) {
	path := r.getPath(key)
	if err := conn.CreateDir(path); err != nil {
		return "", err
	}
	return path, nil
}

func (r *registryType) WatchKey(conn client.Connection, key string, processChildren func(conn client.Connection, childPaths ...string), errorHandler WatchError) error {
	keyPath := r.getPath(key)
	return watch(conn, keyPath, processChildren, errorHandler)
}

func (r *registryType) WatchRegistry(conn client.Connection, processChildren func(conn client.Connection, childPaths ...string), errorHandler WatchError) error {
	path := r.getPath()
	return watch(conn, path, processChildren, errorHandler)
}

//Add VhostEndpoint to the key in registry.  Returns the path of the node in the registry
func (r *registryType) addItem(conn client.Connection, key string, nodeID string, node client.Node) (string, error) {
	path := r.getPath(key, nodeID)

	if err := r.ensureDir(conn, r.getPath(key)); err != nil {
		return "", err
	}

	if err := r.ensureDir(conn, r.getPath(nodeID)); err != nil {
		return "", err
	}

	//TODO: make ephemeral
	glog.Infof("Adding to %s: %#v", path, node)
	if err := conn.Create(path, node); err != nil {
		return "", err
	}
	return path, nil
}

func (r *registryType) ensureDir(conn client.Connection, path string) error {
	if exists, err := conn.Exists(path); err != nil {
		return err
	} else if !exists {
		if err := conn.CreateDir(path); err != nil {
			return err
		}
	}
	return nil
}

func watch(conn client.Connection, path string, processChildren func(conn client.Connection, childPaths ...string), errorHandler WatchError) error {
	for {
		nodeIDs, event, err := conn.ChildrenW(path)
		if err != nil {
			glog.Errorf("Could not watch %s: %s", path, err)
			defer errorHandler(path, err)
			return err
		}
		paths := make([]string, len(nodeIDs))
		for ii := range nodeIDs {
			paths[ii] = fmt.Sprintf("%s/%s", path, nodeIDs[ii])
		}
		processChildren(conn, paths...)
		//This blocks until a change happens under the key
		<-event
	}
	return nil
}

func (r *registryType) watchItem(conn client.Connection, path string, nodeType client.Node, processNode func(conn client.Connection,
	node client.Node), errorHandler WatchError) error {
	for {
		event, err := conn.GetW(path, nodeType)
		if err != nil {
			glog.Errorf("Could not watch %s: %s", path, err)
			defer errorHandler(path, err)
			return err
{'fraction_non_alphanumeric': 0.12369155617585485, 'fraction_numerical': 0.0013956734124214933, 'mean_word_length': 4.16021602160216, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6854358', 'n_tokens_mistral': 1880, 'n_tokens_neox': 1794, 'n_words': 623}