#!/usr/bin/env python
#
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements.  See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership.  The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License.  You may obtain a copy of the License at
# 
#   http://www.apache.org/licenses/LICENSE-2.0
# 
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied.  See the License for the
# specific language governing permissions and limitations
# under the License.
#

import optparse, socket
from qpid.messaging import *
from qpid.log import enable, DEBUG, WARN
from common import *

host = socket.gethostname()

parser = optparse.OptionParser(usage="usage: %prog [options]",
                               description="machine reservation agent")
parser.add_option("-b", "--broker", default="localhost",
                  help="connect to specified BROKER (default %default)")
parser.add_option("-d", "--database",
                  help="database file for persistent machine status")
parser.add_option("-a", "--address", default="reservations",
                  help="address for reservation requests")
parser.add_option("-i", "--identity", default=host,
                  help="resource id (default %default)")
parser.add_option("-v", dest="verbose", action="store_true",
                  help="enable verbose logging")

opts, args = parser.parse_args()

if opts.verbose:
  enable("qpid", DEBUG)
else:
  enable("qpid", WARN)

conn = Connection.establish(opts.broker, reconnect=True, reconnect_interval=1)


class Agent(Dispatcher):

  def __init__(self, identity):
    self.identity = identity
    self.status = FREE
    self.owner = None

  def running(self):
    return True

  def get_status(self):
    msg = Message(properties = {"type": "status"},
                  content = {"identity": self.identity,
                             "status": self.status,
                             "owner": self.owner})
    return msg

  def do_discover(self, msg):
    r = self.get_status()
    return [(msg.reply_to, r)]

  def do_reserve(self, msg):
    if self.status == FREE:
      self.owner = msg.content["owner"]
      self.status = BUSY
    return self.do_discover(msg)

  def do_release(self, msg):
    if self.owner == msg.content["owner"]:
      self.status = FREE
      self.owner = None
    return self.do_discover(msg)

  def ignored(self, msg):
    patterns = msg.properties.get("identity")
    type = msg.properties.get("type")
    if patterns and match(self.identity, patterns):
      return type == "status"
    else:
      return True

try:
  ssn = conn.session()
  rcv = ssn.receiver(opts.address)
  rcv.capacity = 10
  snd = ssn.sender(opts.address)
  agent = Agent(opts.identity)
  snd.send(agent.get_status())
  agent.run(ssn)
except KeyboardInterrupt:
  pass
finally:
  conn.close()
