[96] | 1 | from typing import TYPE_CHECKING
|
---|
| 2 | from pyson.JsonSubTypes import JsonSubTypes
|
---|
| 3 | from tudelft.utilities.listener.Listenable import Listenable
|
---|
| 4 |
|
---|
| 5 | from geniusweb.events.ProtocolEvent import ProtocolEvent
|
---|
| 6 | if TYPE_CHECKING:
|
---|
| 7 | from geniusweb.protocol.NegoState import NegoState
|
---|
| 8 | from geniusweb.protocol.partyconnection.ProtocolToPartyConnFactory import ProtocolToPartyConnFactory
|
---|
| 9 | from geniusweb.references.PartyWithProfile import PartyWithProfile
|
---|
| 10 | from geniusweb.references.ProtocolRef import ProtocolRef
|
---|
| 11 |
|
---|
| 12 |
|
---|
| 13 | @JsonSubTypes(["SessionProtocol"])
|
---|
| 14 | class NegoProtocol (Listenable[ProtocolEvent]):
|
---|
| 15 | '''
|
---|
| 16 | Abstract interface to all negotiation protocols, both single session and
|
---|
| 17 | tournaments. Generally a protocol handles events on the provided connections
|
---|
| 18 | according to the rules set by the protocol. The rules are explained by
|
---|
| 19 | {@link #getDescription()}. A protocol reports the progress through its
|
---|
| 20 | {@link Listenable} interface. <br>
|
---|
| 21 | <h2>General information</h2>
|
---|
| 22 |
|
---|
| 23 | A protocol is mutable because the incoming connections cause state changes.
|
---|
| 24 | But it is recommended to push changing properties into the state so that the
|
---|
| 25 | complete state can be recovered and analysed.
|
---|
| 26 | <p>
|
---|
| 27 | Because a protocol contains an internal state, it can be used only once.
|
---|
| 28 | <p>
|
---|
| 29 | The protocol can emit a {@link CurrentState} event at any time. It should do
|
---|
| 30 | so at least once, to log the final outcome of the nego.
|
---|
| 31 | <p>
|
---|
| 32 |
|
---|
| 33 | Normally the constructor will receive a {@link ConnectionFactory} through
|
---|
| 34 | which it can resolve received {@link Reference}s. <br>
|
---|
| 35 | First call to instances <b>must be</b>
|
---|
| 36 | {@link #start(ProtocolToPartyConnFactory)}.
|
---|
| 37 |
|
---|
| 38 | <h2>Ensure time deadline</h2>
|
---|
| 39 |
|
---|
| 40 | The protocol also needs to keep an eye on the deadline and take appropriate
|
---|
| 41 | actions when the deadline is reached. <br>
|
---|
| 42 | <p>
|
---|
| 43 | All protocol implementations must ensure that the deadline is kept and that
|
---|
| 44 | the session ends at the agreed time {@link Deadline#getDuration()}. This is
|
---|
| 45 | to ensure that the negotiation ends and resources are freed up at or before
|
---|
| 46 | some known time.
|
---|
| 47 | '''
|
---|
| 48 | def start(self, connectionfactory:ProtocolToPartyConnFactory):
|
---|
| 49 | '''
|
---|
| 50 | Start the protocol: make connection with parties and follow the protocol.
|
---|
| 51 | This must be called once and should be the first call after construction.
|
---|
| 52 | <p>
|
---|
| 53 |
|
---|
| 54 | The protocol implementation should not start any real work (eg making
|
---|
| 55 | connections) before this point. That also allows us to construct protocol
|
---|
| 56 | instances just to fetch the description.
|
---|
| 57 | <p>
|
---|
| 58 |
|
---|
| 59 | All errors are to be handled through {@link SessionState#getResult()}
|
---|
| 60 | except for bugs that use {@link RuntimeException} like
|
---|
| 61 | {@link IllegalArgumentException}s. <br>
|
---|
| 62 | The protocol usually uses the incoming connections to keep running. It
|
---|
| 63 | does not need to run in a separate thread or so.
|
---|
| 64 |
|
---|
| 65 |
|
---|
| 66 | @param connectionfactory the {@link ProtocolToPartyConnFactory} that
|
---|
| 67 | allows the protocol to connect with the
|
---|
| 68 | {@link Reference}s in the settings
|
---|
| 69 | '''
|
---|
| 70 |
|
---|
| 71 | def getDescription(self)-> str:
|
---|
| 72 | '''
|
---|
| 73 | @return a complete description of how this protocol behaves. Presented to
|
---|
| 74 | the end users who should know negotiation basics but not all
|
---|
| 75 | technical terms.
|
---|
| 76 | '''
|
---|
| 77 | def getState(self)->"NegoState" :
|
---|
| 78 | '''
|
---|
| 79 | @return current state: the results of all sessions run so far and how to
|
---|
| 80 | continue from that point. Changes over time as the session
|
---|
| 81 | proceeds. Errors are also stored in the state.
|
---|
| 82 | '''
|
---|
| 83 |
|
---|
| 84 |
|
---|
| 85 | def getRef(self) -> ProtocolRef :
|
---|
| 86 | '''
|
---|
| 87 | @return the {@link ProtocolRef} for this protocol
|
---|
| 88 | '''
|
---|
| 89 |
|
---|
| 90 | def addParticipant(self, party:PartyWithProfile ):
|
---|
| 91 | '''
|
---|
| 92 | Add a party after the protocol has started. Only some protocols can
|
---|
| 93 | handle this call. Usual protocols take the settings with their
|
---|
| 94 | constructor.
|
---|
| 95 | @param party the {@link PartyWithProfile} to be added.
|
---|
| 96 | '''
|
---|
| 97 |
|
---|