<commit_before>package resource

import (
	"code.google.com/p/go-uuid/uuid"
	"errors"
	log "github.com/Sirupsen/logrus"
	"github.com/jmmcatee/cracklord/common"
	"sync"
)

// TODO: Add function for adding tools and assign a UUID

const (
	ERROR_AUTH    = "Call to resource did not have the proper authentication token."
	ERROR_NO_TOOL = "Tool specified does not exit."
)

type Queue struct {
	stack map[string]common.Tasker
	tools []common.Tooler
	sync.RWMutex
	hardware map[string]bool
}

func NewResourceQueue() Queue {
	return Queue{
		stack:    map[string]common.Tasker{},
		tools:    []common.Tooler{},
		hardware: map[string]bool{},
	}
}

func (q *Queue) AddTool(tooler common.Tooler) {
	// Add the hardware used by the tool
	q.hardware[tooler.Requirements()] = true

	tooler.SetUUID(uuid.New())
	q.tools = append(q.tools, tooler)
	log.WithFields(log.Fields{
		"toolid":  tooler.UUID(),
		"name":    tooler.Name(),
		"version": tooler.Version(),
	}).Debug("Tool added")
}

// Task RPC functions
func (q *Queue) Ping(ping int, pong *int) error {
	q.Lock()
	defer q.Unlock()

	pong = &ping

	return nil
}

func (q *Queue) ResourceHardware(rpc common.RPCCall, hw *map[string]bool) error {
	q.RLock()
	defer q.RUnlock()

	*hw = q.hardware

	return nil
}

func (q *Queue) AddTask(rpc common.RPCCall, rj *common.Job) error {
	log.WithFields(log.Fields{
		"name": rpc.Job.Name,
		"uuid": rpc.Job.UUID,
	}).Info("Job added")

	log.WithFields(log.Fields{
		"uuid":       rpc.Job.UUID,
		"parameters": rpc.Job.Parameters,
	})

	// Add a defered catch for panic from within the tools
	defer func() {
		if err := recover(); err != nil {
			log.Errorf("Recovered from Panic in Resource.AddTask: %v", err)
		}
	}()

	// variable to hold the tasker
	var tasker common.Tasker
	var err error
	// loop through common.Toolers for matching tool
	q.Lock()
	defer q.Unlock()
	for i, _ := range q.tools {
		if q.tools[i].UUID() == rpc.Job.ToolUUID {
			tasker, err = q.tools[i].NewTask(rpc.Job)
			if err != nil {
				return err
			}
		}
	}

	// Check if no tool was found and return error
	if tasker == nil {
		log.Warn("An error occured, we could not find the tool requested")
		return errors.New(ERROR_NO_TOOL)
	}
	log.WithFields(log.Fields{
		"task": rpc.Job.UUID,
	}).Debug("Tasker created")

	// Looks good so lets add to the stack
	if q.stack == nil {
		q.stack = make(map[string]common.Tasker)
	}

	q.stack[rpc.Job.UUID] = tasker

	// Everything should be paused by the control queue so start this job
	err = q.stack[rpc.Job.UUID].Run()
	if err != nil {
		log.Debug("Error starting task on resource")
		return errors.New("Error starting task on the resource: " + err.Error())
	}

	// Grab the status and return that job to the control queue
	*rj = q.stack[rpc.Job.UUID].Status()

	return nil
}

func (q *Queue) TaskStatus(rpc common.RPCCall, j *common.Job) error {
	log.WithField("task", j.UUID).Debug("Attempting to gather task status")

	// Add a defered catch for panic from within the tools
	defer func() {
		if err := recover(); err != nil {
			log.Errorf("Recovered from Panic in Resource.TaskStatus: %v", err)
		}
	}()

	// Grab the task specified by the UUID and return its status
	q.Lock()
	defer q.Unlock()
	_, ok := q.stack[rpc.Job.UUID]

	// Check for a bad UUID
	if ok != false {
		log.WithField("task", j.UUID).Error("Task with UUID provided does not exist.")
		return errors.New("Task with UUID provided does not exist.")
	}

	*j = q.stack[rpc.Job.UUID].Status()<commit_msg>Fixed long running blank UUID error bug<commit_after>package resource

import (
	"code.google.com/p/go-uuid/uuid"
	"errors"
	log "github.com/Sirupsen/logrus"
	"github.com/jmmcatee/cracklord/common"
	"sync"
)

// TODO: Add function for adding tools and assign a UUID

const (
	ERROR_AUTH    = "Call to resource did not have the proper authentication token."
	ERROR_NO_TOOL = "Tool specified does not exit."
)

type Queue struct {
	stack map[string]common.Tasker
	tools []common.Tooler
	sync.RWMutex
	hardware map[string]bool
}

func NewResourceQueue() Queue {
	return Queue{
		stack:    map[string]common.Tasker{},
		tools:    []common.Tooler{},
		hardware: map[string]bool{},
	}
}

func (q *Queue) AddTool(tooler common.Tooler) {
	// Add the hardware used by the tool
	q.hardware[tooler.Requirements()] = true

	tooler.SetUUID(uuid.New())
	q.tools = append(q.tools, tooler)
	log.WithFields(log.Fields{
		"toolid":  tooler.UUID(),
		"name":    tooler.Name(),
		"version": tooler.Version(),
	}).Debug("Tool added")
}

// Task RPC functions
func (q *Queue) Ping(ping int, pong *int) error {
	q.Lock()
	defer q.Unlock()

	pong = &ping

	return nil
}

func (q *Queue) ResourceHardware(rpc common.RPCCall, hw *map[string]bool) error {
	q.RLock()
	defer q.RUnlock()

	*hw = q.hardware

	return nil
}

func (q *Queue) AddTask(rpc common.RPCCall, rj *common.Job) error {
	log.WithFields(log.Fields{
		"name": rpc.Job.Name,
		"uuid": rpc.Job.UUID,
	}).Info("Job added")

	log.WithFields(log.Fields{
		"uuid":       rpc.Job.UUID,
		"parameters": rpc.Job.Parameters,
	})

	// Add a defered catch for panic from within the tools
	defer func() {
		if err := recover(); err != nil {
			log.Errorf("Recovered from Panic in Resource.AddTask: %v", err)
		}
	}()

	// variable to hold the tasker
	var tasker common.Tasker
	var err error
	// loop through common.Toolers for matching tool
	q.Lock()
	defer q.Unlock()
	for i, _ := range q.tools {
		if q.tools[i].UUID() == rpc.Job.ToolUUID {
			tasker, err = q.tools[i].NewTask(rpc.Job)
			if err != nil {
				return err
			}
		}
	}

	// Check if no tool was found and return error
	if tasker == nil {
		log.Warn("An error occured, we could not find the tool requested")
		return errors.New(ERROR_NO_TOOL)
	}
	log.WithFields(log.Fields{
		"task": rpc.Job.UUID,
	}).Debug("Tasker created")

	// Looks good so lets add to the stack
	if q.stack == nil {
		q.stack = make(map[string]common.Tasker)
	}

	q.stack[rpc.Job.UUID] = tasker

	// Everything should be paused by the control queue so start this job
	err = q.stack[rpc.Job.UUID].Run()
	if err != nil {
		log.Debug("Error starting task on resource")
		return errors.New("Error starting task on the resource: " + err.Error())
	}

	// Grab the status and return that job to the control queue
	*rj = q.stack[rpc.Job.UUID].Status()

	return nil
}

func (q *Queue) TaskStatus(rpc common.RPCCall, j *common.Job) error {
	log.WithField("task", rpc.Job.UUID).Debug("Attempting to gather task status")

	// Add a defered catch for panic from within the tools
	defer func() {
		if err := recover(); err != nil {
			log.Errorf("Recovered from Panic in Resource.TaskStatus: %v", err)
		}
	}()

	// Grab the task specified by the UUID and return its status
	q.Lock()
	defer q.Unlock()
	_, ok := q.stack[rpc.Job.UUID]

	// Check for a bad UUID
	if !ok {
		log.WithField("task", rpc.Job.UUID).Error("Task with UUID provided does not exist.")
		return errors.New("Task with UUID provided does not exist.")
	}

	*j = q.stack[rpc.Job.UUID].Status()
{'fraction_non_alphanumeric': 0.14124212936462507, 'fraction_numerical': 0.0, 'mean_word_length': 3.511943189154293, 'pattern_counts': {'":': 16, '<': 3, '<?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': '4596442', 'n_tokens_mistral': 2605, 'n_tokens_neox': 2520, 'n_words': 736}