Pages: [1]   Go Down
Print
Author Topic: Sistema 3 Buyers/Seller in Sepi  (Read 1142 times)
0 Members e 1 Utente non registrato stanno visualizzando questa discussione.
rondey
Matricola
*
Offline Offline

Posts: 74


« on: 21-06-2016, 21:06:11 »

Ok, lo so che l'esercizio da fare era il 2 Buyers/seller, ma me ne sono accorto troppo tardi e perciò mi sono detto: "A questo punto, tanto vale finire questo esercizio. In fondo sono esercizi molto simili".

Ho riscontrato uno strano errore nella fase finale. Questo è il codice che ho scritto io:
Code:
type AtoSProt= !string.?integer.end

type BtoSProt= ?integer.BtoSFinProt
type BtoSFinProt=+{ok: !string.?string.end,
                   quit: end}

type BtoAProt= ?integer.BtoAFinProt
type BtoAFinProt= +{ok: end,
                    quit: end}

type BtoCProt= !integer.!BtoSFinProt.!BtoAFinProt.&{ok: end,
                       quit: end}

def sellerManager (book1:string,price1:integer,book2:string,price2:integer,
  date: string,
  chAtoSManager: *!AtoSProt, chBtoSManager: *!BtoSProt) =
def sellerSessionManager (chStoA: dualof AtoSProt,
        chStoB: dualof BtoSProt) =
  //chiedi il libro
          chStoA?book.
          if book==book1
  then //Invia il relativo numero di conto corrente
   chStoA!price1.chStoB!price1.
   {
                   case chStoB of
                      //Se ricevo l'ok ricevo l'indirizzo e invio la data
                      ok   -> chStoB?address.chStoB!date.
                        //Richiama il sellerManager in modo da poter soddisfare un
                              //ulteriore richiesta
                              sellerManager!(book1,price1,book2,price2,date,
                                             chAtoSManager, chBtoSManager)
                      //Altrimenti chiudo
                      quit -> //Richiama il sellerManager in modo da poter soddisfare un
                              //ulteriore richiesta
                              sellerManager!(book1,price1,book2,price2,date,
                                             chAtoSManager, chBtoSManager)
                   }
   
              else chStoA!price2.chStoB!price2.
   {
                   case chStoB of
                      //Se ricevo l'ok ricevo l'indirizzo e invio la data
                      ok   -> chStoB?address.chStoB!date.
                        //Richiama il sellerManager in modo da poter soddisfare un
                              //ulteriore richiesta
                              sellerManager!(book1,price1,book2,price2,date,
                                             chAtoSManager, chBtoSManager)
                      //Altrimenti chiudo
                      quit -> sellerManager!(book1,price1,book2,price2,date,
                                             chAtoSManager, chBtoSManager)
                   }
new chAtoSCl chAtoSSr : AtoSProt // crea un canale sellerManagerProt
chAtoSManager!chAtoSCl. // pubblica l'estremità del client
new chBtoSCl chBtoSSr : BtoSProt // crea un canale sellerManagerProt
chBtoSManager!chBtoSCl. // pubblica l'estremità del client
sellerSessionManager!(chAtoSSr, chBtoSSr) // tieni le estremità del server


//Creo un nuovo canale per il sellerManager
new AtoSManagerServer AtoSManagerClient: *!AtoSProt
new BtoSManagerServer BtoSManagerClient: *!BtoSProt
//Inizializzo il sellerManager
sellerManager!("H.P. e la vita filosofale",10,"Sudorra",20, "15/12/2016",
  AtoSManagerServer, BtoSManagerServer) |

def clientA (book: string, money: integer, chAtoB: dualof BtoAProt) =
//Richiedo l'estremità client del sellerManager
    AtoSManagerClient?s.
//Invio il libro
s!book.
s?m.printStringLn!("Il prezzo e': "++m).
//Invio a B i soldi che ho a disposizione
chAtoB!money.
case chAtoB of
      //Se ricevo l'ok informo l'avvenuto acquisto
      ok   -> printStringLn!("Il libro e' stato acquistato")
      //Altrimenti informo l'annullamento
      quit -> printStringLn!("L'acquisto del libro e' stato annullato")

def clientB (money: integer, address: string, chBtoA: BtoAProt) =
//Richiedo l'estremità client del sellerManager
    BtoSManagerClient?s.
//Ricevo il prezzo del libro
s?m.
//Ricevo l'informativa sui soldi di A
chBtoA?mA.
if m<=(money+mA)
  //Ho soldi a sufficienza
      then s select ok. chBtoA select ok.
   //Invio l'indirizzo e richiedo la data di spedizione
   s!address.s?date.
   printStringLn!("Spedira' il libro il "++date)
   //Altrimenti i soldi non bastano. Chiedo l'aiuto di C(ok, lo sto creando qui,
   //ma è solo per rafforzare una mia teoria...),
   //inviandogli quanto deve pagare e i canali
  else  {new chBtoC chCtoB : BtoCProt
clientC!(1, "Via Celere N.17",chCtoB)|
chBtoC!(m-money-mA).
chBtoC!s.
chBtoC!chBtoA.
   case chBtoC of
              //Se ricevo l'ok informo l'avvenuto acquisto
              ok   -> printStringLn!("Il libro e' stato acquistato")
              //Altrimenti informo l'annullamento
              quit -> printStringLn!("L'acquisto del libro e' stato annullato")
      }

def clientC (money: integer, address: string, chCtoB: dualof BtoCProt) =
//Ricevo l'informativa sui soldi che devo mettere
chCtoB?mB.
//Ricevo il canale per comunicare con Seller e A
chCtoB?chCtoS.chCtoB?chCtoA.
if mB>money
      //Se i soldi non bastano, chiudo
      then chCtoS select quit. chCtoA select quit.chCtoB select quit.
   printStringLn!("Non bastano i soldi")
      //Altrimenti proseguo
      else chCtoS select ok. chCtoA select ok.chCtoB select ok.
   //Invio l'indirizzo e richiedo la data di spedizione
   chCtoS!address.chCtoS?date.
   printStringLn!("Spedira' il libro il "++date)

new chBtoA chAtoB : BtoAProt

//Esempi di client
clientA!("H.P. e la vita filosofale", 2, chAtoB)|clientB!(7, "Via ignota N.5",chBtoA)

Questo codice restituisce l'errore:
Code:
-The sets of linear channel ends must be equal in branches: s, chBtoA
Il compilatore si lamenta perchè non gli piace la gestione dei suddetti canali all'interno del clientB, più precisamente di questi branch:
Code:
if m<=(money+mA)
  //Ho soldi a sufficienza
      then s select ok. chBtoA select ok.
   //Invio l'indirizzo e richiedo la data di spedizione
   s!address.s?date.
   printStringLn!("Spedira' il libro il "++date)
   //Altrimenti i soldi non bastano. Chiedo l'aiuto di C(ok, lo sto creando qui,
   //ma è solo per rafforzare una mia teoria...),
   //inviandogli quanto deve pagare e i canali
  else  {new chBtoC chCtoB : BtoCProt
clientC!(1, "Via Celere N.17",chCtoB)|
chBtoC!(m-money-mA).
chBtoC!s.
chBtoC!chBtoA.
   case chBtoC of
              //Se ricevo l'ok informo l'avvenuto acquisto
              ok   -> printStringLn!("Il libro e' stato acquistato")
              //Altrimenti informo l'annullamento
              quit -> printStringLn!("L'acquisto del libro e' stato annullato")
      }
Inizialmente credevo che io stessi sbagliando nella fase del passaggio delle estremità dei canali "chBtoA" e "s". In realtà l'errore non è quello, infatti se nel branch then inserisco lo stesso codice del banch else(quello che contiene i passaggi delle sopracitate estremità dei canali) il compilatore "si sente soddisfatto" e l'esecuzione del programma avviene senza intoppi.
Per intenderci:
Code:
if m<=(money+mA)
  //Ho soldi a sufficienza
      then {new chBtoC chCtoB : BtoCProt
clientC!(1, "Via Celere N.17",chCtoB)|
chBtoC!(m-money-mA).
chBtoC!s.
chBtoC!chBtoA.
   case chBtoC of
              //Se ricevo l'ok informo l'avvenuto acquisto
              ok   -> printStringLn!("Il libro e' stato acquistato")
              //Altrimenti informo l'annullamento
              quit -> printStringLn!("L'acquisto del libro e' stato annullato")
      }
   //Altrimenti i soldi non bastano. Chiedo l'aiuto di C(ok, lo sto creando qui,
   //ma è solo per rafforzare una mia teoria...),
   //inviandogli quanto deve pagare e i canali
  else  {new chBtoC chCtoB : BtoCProt
clientC!(1, "Via Celere N.17",chCtoB)|
chBtoC!(m-money-mA).
chBtoC!s.
chBtoC!chBtoA.
   case chBtoC of
              //Se ricevo l'ok informo l'avvenuto acquisto
              ok   -> printStringLn!("Il libro e' stato acquistato")
              //Altrimenti informo l'annullamento
              quit -> printStringLn!("L'acquisto del libro e' stato annullato")
      }
Perciò la domanda è: che cosa mi sta sfuggendo? Perchè Sepi mi nega la possibilità di diversificare il modo di concludere i protocolli? Che gliene frega se in un ramo dell'if i protocolli vengono soddisfatti dal clientB e nell'else decido che è il clientC a doversi occupare di soddisfare i bisogni dei protocolli???
Logged
Ocelot92
Apprendista Forumista
**
Offline Offline

Posts: 301



« Reply #1 on: 23-10-2016, 12:50:36 »

Ho capito il problema. Proprio come dice l'errore, i canali lineari che usi in un branch devono essere uguali a quello che usi nell'altro branch dell'if. Questo evita che ci siano processi che rimangono in attesa perenne di una delega che arriva solo in un branch dell'if.
Il problema si può riprodurre prendendo l'esempio giocattolo fatto sulle deleghe a lezione:
Abbiamo un client che invia un integer e tramite un high order channel invia il suo canale ad un altro client che completa inviando l'ultimo integer al server.
Code:
type prot = !integer.!integer.end

type hoT= !(!integer.end).end

new chHc chHs : hoT

new chc chs : prot

chc!1.chHc!chc |
chs?x.printIntegerLn!x.chs?y.printInteger!y |
chHs?c.c!2
Fin qui tutto ok. Se però proviamo a mettere una condizione che prevede la delega solo in un branch otteniamo l'errore:
Code:
type prot = !integer.!integer.end

type hoT= !(!integer.end).end

new chHc chHs : hoT

new chc chs : prot

chc!1.
if true then
chc!2
else
chHc!chc
|
chs?x.printIntegerLn!x.chs?y.printInteger!y
|
chHs?c.c!2

Una soluzione che ho trovato che sporca un pò il protocollo base "prot" è la seguente:
Code:
type prot = !integer.+{continue: !integer.end}

type hoT= !(!integer.end).end

new chHc chHs : +{activate: hoT, deactivate: end}

new chc chs : prot

chc!1.
if true then
chc select continue.
chc!2.
chHc select deactivate
else
chHc select activate.
chc select continue.
chHc!chc
|
chs?x.printIntegerLn!x.
case chs of
continue -> chs?y.printIntegerLn!y
|
case chHs of
activate -> chHs?c.c!2
deactivate -> printStringLn!"I'm not needed. Bye"
Dove cambiando la condizione dell'if si attiva o disattiva la delega e se non è necessaria si "disattiva" il processo in attesa della delega. Inoltre viene aggiunta un'etichetta "continue" per far si che cmq i canali utilizzati siano gli stessi nei rami dell'if.


UPDATE:
Ecco la mia versione del 3buyers protocol (sporcata con alcune etichette fittizzie per il problema di sopra):
Code:
//  The overall scenario, involving a Seller (S), Alice (A), Bob (B) and
//  Carol (C), proceeds as follows.
// 
//  (1) Alice sends a book title to Seller, then Seller sends back a quote to Alice and Bob.
//  Then Alice tells Bob how much she can contribute.
// 
//  (2) If the price is within Bob’s budget, Bob notifies both Seller and Alice he accepts, then
//  sends his address, and Seller sends back the delivery date.
// 
//  (3) If the price exceeds the budget, Bob asks Carol to collaborate together by establishing a
//  new session. Then Bob sends how much Carol must pay, then delegates the remaining
//  interactions with Alice and Seller to Carol.
// 
//  (4) If the rest of the price is within Carol’s budget, Carol accepts the quote and notifies
//  Alice, Bob and Seller, and continues the rest of the protocol with Seller and Alice
//  transparently, as if she were Bob. Otherwise she notifies Alice, Bob and Seller to quit
//  the protocol.

type Alice2Seller = !title:string. ?price:integer.end

type Alice2Bob = !bobContribute:integer. &{continueB2A: &{ok: end, quit: end}}

type Bob2Seller = ?price:integer. +{continueB2S: +{accept: !address:string. ?date:string.end, refuse: end} }

type Carol2Seller = +{accept: !address:string. ?date:string.end, refuse: end} //portion of Bob's protocol (towards Seller) delegated to Carol

type Carol2Alice = +{ok: end, quit: end} //portion of Bob's protocol (towards Alice) delegated to Carol

type Bob2Carol = +{activate: !carolContribute:integer. !(Carol2Seller). !(Carol2Alice) .&{ok: end, quit: end}, deactivate: end}


new chA2B  chB2A : Alice2Bob

new chA2S chS2A : Alice2Seller

new chB2S chS2B : Bob2Seller

new chB2C chC2B : Bob2Carol



//Alice
chA2S!"LIBRONE".
chA2S?fullPrice.
chA2B!fullPrice/2.
case chA2B of
continueB2A ->
{case chA2B of
ok -> printStringLn!"Alice: 'Thank you Bob'"
quit -> printStringLn!"Alice: 'Nevermind Bob, we'll wait the sale...'" }
|
//Bob - his max contribute is 20 in this example.
chB2A?aliceContribute.
chB2S?fullPrice.
if fullPrice - aliceContribute <= 20 then //Bob's checking his wallet... 20 is the max amount of money available to Bob in this example.
chB2C select deactivate.
chB2A select continueB2A.
    chB2A select ok.
    chB2S select continueB2S.
    chB2S select accept.
    chB2S!"221B Baker Street".
    chB2S?date.
    printStringLn!"Bob: 'Hey Alice, the book will arrive on "++date++"'"
else
    chB2S select continueB2S.
chB2A select continueB2A.
chB2C select activate.
    chB2C!fullPrice - aliceContribute - 20. //20 is the max amount of money available to Bob in this example.
    chB2C!chB2S. //Bob is sending to Carol his session channels towards Seller and Alice
    chB2C!chB2A.
    case chB2C of
        ok -> printStringLn!"Bob: 'Thank you Carol.'"
        quit -> printStringLn!"Bob: 'Nevermind Bob, we'll wait the sale...'"
|
//Carol
case chC2B of
activate ->
{chC2B?carolContribute.
chC2B?chC2S.
chC2B?chC2A.
if carolContribute <= 20 then
chC2B select ok.
chC2A select ok.
chC2S select accept.
chC2S!"221B Baker Street".
chC2S?date.
printStringLn!"Carol: 'Hey Bob, the book will arrive on "++date++"'"
else
chC2B select quit.
chC2A select quit.
chC2S select refuse.
printStringLn!"Carol: 'I'm sorry Bob...'" }
deactivate ->
printStringLn!"Carol: 'I'm not needed. Bye.'"
|
//Seller
chS2A?title.
chS2A!10. //sending price to Alice and Bob. Change this two rows to make the price higher.
chS2B!10.
case chS2B of
continueB2S ->
{case chS2B of
accept ->
chS2B?address.
chS2B!"25/12/2016"
refuse -> printStringLn!"Seller: 'Until next time.'"}
   
« Last Edit: 23-10-2016, 16:14:53 by Ocelot92 » Logged

I'm happy to tell you all that...
((λf.λx.f(f(x))) (λy.y^2)) (5)  = 5^4

"Si ma dillo che bisogna cliccare APPLY per crearle le partizioni…" - cit. Utente dopo aver seguito un How-To... .-.
Pages: [1]   Go Up
Print
Jump to: