Visualizzazione dei risultati da 1 a 10 su 10
  1. #1
    Utente di HTML.it
    Registrato dal
    Dec 2002
    Messaggi
    1,326

    [delphi] refresh tabelle firebird

    Ciao a tutti,

    delphi7 + database firebird

    in un programma delphi7 c'e' la possibilita di selezionare tramite il menu il frame da visualizzare:

    frameClienti= videata archivio clienti
    frameFornitori= videata archivio fornitori
    frameMovimentiMagazzino= videata MovimentiMagazzino
    etc.etc.

    all'apertura di ogni frame devo aprire anche le tabella per il lookup dei vari campi, quindi a secondo del frame in questione ci sono un numero diverso di tabelle da aprire

    chiaramente quante più tabelle devo aprire tanto più lungo e' il tempo necessario per l'operazione.

    e' necessario aprire le tabella ogni volta anche perche e' solo effettuando il close e l'open che la stessa tabella viene aggiornata con gli eventuali record inseriti da altri user da altre postazioni.

    se effettuo l'open di queste tabelle solo all'apertuara del programma rischierei di non trovare record di tabelle che invece sono stati già inseriti.

    io vorrei poter ridurre il tempo di passaggio da un frame all'altro, effettuando in qualche modo il refresh delle tabelle.


    avete suggerimenti?

    grazie

  2. #2
    Moderatore di Programmazione L'avatar di alka
    Registrato dal
    Oct 2001
    residenza
    Reggio Emilia
    Messaggi
    24,472
    Le soluzioni sono tante, ciascuna con vari pro e contro.

    Indicativamente, potresti usare per la tabella che viene aggiornata un solo componente TDataSet condiviso, magari inserito in un TDataModule; in questo modo, posto che gli aggiornamenti vengano inviati a quel componente, essi risulteranno sempre aggiornati, senza che sia necessario aprire e chiudere la tabella.

    Se la tabella deve essere condivisa tra più TFrame, questo potrebbe portare a effetti collaterali: se la visualizzazione di un campo fa scorrere i record della tabella per fare un lookup, questo potrebbe creare a visualizzazioni errate di altri campi che utilizzano la medesima tabella.

    In questo caso, meglio usare più TDataSet che puntino alla stessa tabella, come mi pare tu abbia fatto in questo frangente, con il problema però delle performance legate alla necessaria riapertura delle stesse tabelle ogni volta che si richiede un TFrame che ha bisogno di quei dati per le proprie specifiche esigenze.

    Io suggerirei di procedere in questo modo: caricare i dati all'interno di un componente TClientDataSet, che ha la possibilità di scaricarli automaticamente da qualsiasi TDataSet che rappresenta una tabella o una query su database; una volta che i dati sono stati scaricati, questi vengono immagazzinati in memoria, ed è possibile andarli a clonare velocemente in altrettanti TClientDataSet presenti nei vari TFrame, che ogni volta prelevano i dati da quello originale, il quale viene aggiornato solo quando si effettuano aggiornamenti alla tabella o query che costituisce la sorgente dei dati.

    Approfondisci l'uso di questi componenti nella documentazione Delphi per capirne le potenzialità.

    Ciao!
    MARCO BREVEGLIERI
    Software and Web Developer, Teacher and Consultant

    Home | Blog | Delphi Podcast | Twitch | Altro...

  3. #3
    Utente di HTML.it
    Registrato dal
    Dec 2002
    Messaggi
    1,326
    ciao

    Originariamente inviato da alka
    Le soluzioni sono tante, ciascuna con vari pro e contro.

    Indicativamente, potresti usare per la tabella che viene aggiornata un solo componente TDataSet condiviso, magari inserito in un TDataModule; in questo modo, posto che gli aggiornamenti vengano inviati a quel componente, essi risulteranno sempre aggiornati, senza che sia necessario aprire e chiudere la tabella.

    Se la tabella deve essere condivisa tra più TFrame, questo potrebbe portare a effetti collaterali: se la visualizzazione di un campo fa scorrere i record della tabella per fare un lookup, questo potrebbe creare a visualizzazioni errate di altri campi che utilizzano la medesima tabella.
    (come mi insegnasti Tu) gia' uso questo tipo di approccio,
    ho un datamadule e la mia tabella (il mio datasource) e' inserito in esso. tutti i frame puntano allo stesso datamodule e stesso datasource... trovando sempre i dati aggiornati.

    il problema e' sempre lo stesso:
    se USER1 aggiunge/modifica/cancella un record... tale modifica verra' vista USER2 solo nel momento in cui USER2 effettua close e open della tabella.


    Originariamente inviato da alka ...una volta che i dati sono stati scaricati, questi vengono immagazzinati in memoria, ed è possibile andarli a clonare velocemente in altrettanti TClientDataSet presenti nei vari TFrame, che ogni volta prelevano i dati da quello originale, il quale viene aggiornato solo quando si effettuano aggiornamenti alla tabella o query che costituisce la sorgente dei dati.
    questo e' cio che non riesco a focalizzare! quando una tabella viene aggiornata da USER1 per vedere le modifiche da USER2 devo effettuare la close e l'open.

    avevo pensato cosi:
    creo una tabella nel database:
    codice:
    CREATE TABLE TabellaUltimoAggiornamento(
        ID                 INTEGER NOT NULL PRIMARY KEY,
        NomeTabella    VARCHAR(100),
        UltimoAgg      varchar(16));   /* yyyymmddhhmmss */
    aggiornando il record relativo alla tabella modificata ogni volta che che viene effettuato un insert/update/delete nella medesima tabella.

    le tabelle le apro solo alla esecuzione del formmain del programma, poi ogni volta che apro un frame diverso, prima di effettuare close e open verifico che la tabella che devo ''refreshiare'' abbia una data di 'ultima modifica' superiore alla data di quando e' stata aperta ad inizio programma e solo in questo caso effettuo il close e l'open.

    pensiero errato?

    grazie

  4. #4
    Utente di HTML.it
    Registrato dal
    Jan 2011
    Messaggi
    1,469
    non è una gran soluzione a mio avviso.

    Se vuoi il refresh immediato dei record devi avere un meccanismo "immediato" che segnali. In questo caso uso dei messaggini broadcast UDP nei quali allego il nome del computer.

    qualcosa del genere (al post di un record)
    "spediscimessaggio(aggiornarecord;nomecomputer ")

    tutti i client ricevono il messaggio, il "nomecomputer" ovviamente lo ignora, gli altri fanno il refresh.

    metodologia più sofisticata prevede l'invio delle chiavi dei record modificati, sicchè i client aggiornano le grid se e solo se le chiavi modificate sono visibili (per ragioni di performances, dipende dalla tipologia)

    spero di essere stato utile

    PS ovviamente devi pre-mettere una procedura di controllo del firewall di windows ed, eventualmente, settare la relativa eccezione per la porta UDP che usi

    PS/2 ancor più ovvio ti serve un range di porte UDP nel caso in cui utilizzi più sessioni/terminal server, ma non è difficile "spazzolarle" fino ad un numero ragionevole (20 o 30 senza grossi problemi)

  5. #5
    Utente di HTML.it
    Registrato dal
    Dec 2002
    Messaggi
    1,326
    ciao

    come faccio ad inviare e ricevere questi messaggi? devo utilizzare qualche componente?

    grazie

  6. #6
    Utente di HTML.it
    Registrato dal
    Jan 2011
    Messaggi
    1,469
    hai parecchi modi; quello più semplice, a mio avviso, è usare TWSocket di ICS

  7. #7
    Moderatore di Programmazione L'avatar di alka
    Registrato dal
    Oct 2001
    residenza
    Reggio Emilia
    Messaggi
    24,472
    Originariamente inviato da franzauker
    non è una gran soluzione a mio avviso.
    Se vuoi il refresh immediato dei record devi avere un meccanismo "immediato" che segnali. In questo caso uso dei messaggini broadcast UDP nei quali allego il nome del computer.
    Il refresh immediato è una cosa differente rispetto a ciò di cui si stava parlando, e al massimo si può aggiungere all'architettura che è stata descritta sino ad ora, ma non è una soluzione sostitutiva, né tanto meno obbligatoria, infatti non mi è mai stata richiesta in alcuna applicazione.

    Inoltre, una simile implementazione va attentamente ponderata, perché in un sistema in cui sono presenti molti utenti la circolazione di simili messaggi può generare un massiccio traffico di rete o andare ad aggiornare informazioni sui client quando questi non ne hanno bisogno, anzi in certi casi può ingenerare problemi quando riguardano dati su cui è in corso un'operazione, oppure che sono già filtrati in qualche modo e così via.

    Un meccanismo di questo tipo lo valuterei se e solo se esiste una esplicita richiesta di aggiornamento di determinate informazioni in tempo reale (può andare bene per una chat, ad esempio, mentre non mi sembra indispensabile per l'anagrafica dei clienti), visto che può produrre un serio decadimento delle performance, numerosi "effetti collaterali" nell'applicazione e, in ogni caso, è un meccanismo da implementare a parte (rispetto alla gestione delle riconciliazioni fornita dal ClientDataSet che è quasi totalmente automatica).

    Ciao!
    MARCO BREVEGLIERI
    Software and Web Developer, Teacher and Consultant

    Home | Blog | Delphi Podcast | Twitch | Altro...

  8. #8
    Utente di HTML.it
    Registrato dal
    Jan 2011
    Messaggi
    1,469
    Originariamente inviato da alka
    Il refresh immediato è una cosa differente rispetto a ciò di cui si stava parlando, e al massimo si può aggiungere all'architettura che è stata descritta sino ad ora, ma non è una soluzione sostitutiva, né tanto meno obbligatoria, infatti non mi è mai stata richiesta in alcuna applicazione.
    Dipende dalle necessità, mi sembrava di averlo specificato
    Inoltre, una simile implementazione va attentamente ponderata, perché in un sistema in cui sono presenti molti utenti la circolazione di simili messaggi può generare un massiccio traffico di rete
    Quale "massiccio traffico di rete"?
    Anche con un centinaio di utenti i messaggi UDP sono così piccoli (e richiedono così poco per essere gestiti dal sistema) che non c'è alcun rallentamento, o almeno non l'ho mai riscontrato
    o andare ad aggiornare informazioni sui client quando questi non ne hanno bisogno, anzi in certi casi può ingenerare problemi quando riguardano dati su cui è in corso un'operazione, oppure che sono già filtrati in qualche modo e così via.
    Come segnalato il modo "furbo" è quello di specificare quali record sono stati aggiornati, e regolarsi di conseguenza
    Un meccanismo di questo tipo lo valuterei se e solo se esiste una esplicita richiesta di aggiornamento di determinate informazioni in tempo reale (può andare bene per una chat, ad esempio, mentre non mi sembra indispensabile per l'anagrafica dei clienti),
    Dipende, soprattutto se quest'ultima contiene dati al suo interno (esempio: sconti).
    nel caso di agenti e backoffice che operano sui medesimi clienti "refreshare" le condizioni commerciali dei clienti (immediatamente) è proprio uno dei casi tipici, soprattutto nel caso in cui si stiano facendo degli ordini a fornitore molto grandi (che richiedono decine di minuti).

    Oppure (altro caso frequente) l'inserimento separato di un cliente (backoffice) e immediata "visibilità" ai front-office (agente) etc.

    visto che può produrre un serio decadimento delle performance,
    Su questo punto, come accennato, non sono d'accordo
    numerosi "effetti collaterali" nell'applicazione
    Neppure su questo, ovviamente occorre porre attenzione a cosa aggiornare, e cosa no
    e, in ogni caso, è un meccanismo da implementare a parte (rispetto alla gestione delle riconciliazioni fornita dal ClientDataSet che è quasi totalmente automatica).
    In realtà sono una 50ina di righe in tutto.
    ---
    Riguardo poi alla domanda ne vedo 2 nel thread,

    1) come e quando aprire i dati
    2) come gestire la concorrenza.

    Mi pare di aver suggerito due soluzioni per entrambe, non necessariamente le migliori.

    Metto anche la terza, ossia lo "screensaver". Più brutalmente si può fare un timer che calcola l'idle time (è banale), e poi "fa qualcosa", tipo pre-caricare i dati, refresharli etc.

    In certi casi basta semplicemente un test del tipo "fai una count sulla tabella clienti, verifica se il numero dei record è uguale al recordcount del mio dataset, nel caso aggiorna"

    Non è perfetto (qui c'è aggiunta, non modifica), e questa sì che può dare problemi di performances se la count(*) viene fatto su un database che NON ha il supporto per il conteggio delle righe (es. mysql-innodb, mysql-myisam se ci sono WHERE) etc

    ---
    PS i miei sono solo suggerimenti, ognuno faccia come crede

    EDIT: mi sono accorto di non aver fatto un'assunzione che però dipende dal contesto.
    Spedire messaggi UDP ha senso in un ambiente con più client su più macchine fisicamente diverse, ovviamente.

    Ha molto meno senso auto-spedirseli (una singola macchina).

    Se il problema è quindi "più finestre dello stesso programma su una certa macchina" oppure "più finestre dello stesso programma su macchine distinte".

    Tendo sempre a dar per scontato che i client siano tanti, ma non sempre è così

  9. #9
    Moderatore di Programmazione L'avatar di alka
    Registrato dal
    Oct 2001
    residenza
    Reggio Emilia
    Messaggi
    24,472
    Originariamente inviato da franzauker
    Dipende dalle necessità, mi sembrava di averlo specificato
    Tu hai detto che "non ti sembrava una gran soluzione", senza fare distinzioni, altrimenti non ci sarebbe stato alcun problema.


    Originariamente inviato da franzauker
    Quale "massiccio traffico di rete"?
    Anche con un centinaio di utenti i messaggi UDP sono così piccoli (e richiedono così poco per essere gestiti dal sistema) che non c'è alcun rallentamento, o almeno non l'ho mai riscontrato
    Come segnalato il modo "furbo" è quello di specificare quali record sono stati aggiornati, e regolarsi di conseguenza
    Il traffico è generato dai dati aggiornati che transitano, non dai messaggi UDP usati come notifica.

    Originariamente inviato da franzauker
    Dipende, soprattutto se quest'ultima contiene dati al suo interno (esempio: sconti).
    nel caso di agenti e backoffice che operano sui medesimi clienti "refreshare" le condizioni commerciali dei clienti (immediatamente) è proprio uno dei casi tipici, soprattutto nel caso in cui si stiano facendo degli ordini a fornitore molto grandi (che richiedono decine di minuti).
    Oppure (altro caso frequente) l'inserimento separato di un cliente (backoffice) e immediata "visibilità" ai front-office (agente) etc.
    Senza aggiungere un meccanismo di notifica, questo lo fanno normalmente i componenti Delphi al momento dell'invio dei dati (è la "riconciliazione").

    I casi frequenti che tu indichi, in realtà, sono casi specifici della tua applicazione, che ha requisiti particolari e che, giustamente (ci mancherebbe) hai risolto nel modo che hai descritto.

    Originariamente inviato da franzauker
    Su questo punto, come accennato, non sono d'accordo
    Neppure su questo, ovviamente occorre porre attenzione a cosa aggiornare, e cosa no
    In realtà sono una 50ina di righe in tutto.
    Le performance diminuiscono senz'altro, visto che - oltre alla normale gestione dei dati che rimane - l'applicazione deve ricevere messaggi di aggiornamento e scaricarsi in automatico pacchetti di dati che, in un meccanismo di "riconciliazione" normale (quello incorporato nel componente ClientDataSet, ad esempio) non sarebbe necessario, e questo lo si nota molto di più se si esce da una rete locale e si approda a Internet.

    Il punto, come dicevo, è dato dal fatto che la tua applicazione gestisce una casistica che necessariamente, come prerequisito, richiede di dover fare questa operazione per risolvere specifiche esigenze del cliente, quindi l'operazione è necessaria e la questione del tempo aggiuntivo introdotto per gestire i messaggi sulla rete è ben bilanciata dalla risoluzione di specifici problemi, quindi è accettabile.


    Originariamente inviato da franzauker
    Riguardo poi alla domanda ne vedo 2 nel thread,
    1) come e quando aprire i dati
    2) come gestire la concorrenza.
    Mi pare di aver suggerito due soluzioni per entrambe, non necessariamente le migliori.
    La mia obiezione infatti è questa: l'introduzione del meccanismo che hai descritto e le istruzioni annesse NON sono necessarie per gestire la concorrenza, poiché questa è già gestita dai componenti standard di Delphi.

    La tua soluzione ha un altro scopo: garantire che in qualsiasi momento sul client ci siano sempre i dati più aggiornati possibile, che non è gestire la concorrenza.

    Infatti, tenuto conto che un PC potrebbe disconnettersi e non ricevere il messaggio, oppure che il messaggio potrebbe arrivare corrotto, il client non saprebbe come aggiornare i propri dati; detto questo, la tua soluzione NON è sufficiente a garantire la gestione corretta della concorrenza, e infatti risolve un altro problema, cioè quello di aumentare la probabilità che il client possieda già - per comodità dell'utente - i dati più aggiornati possibili.


    Originariamente inviato da franzauker
    Metto anche la terza, ossia lo "screensaver". Più brutalmente si può fare un timer che calcola l'idle time (è banale), e poi "fa qualcosa", tipo pre-caricare i dati, refresharli etc.
    Sono tutte "innovazioni" al meccanismo che hai ideato per cercare il più possibile di aggiornare i dati sui client, ma sono un "di più".

    Intendiamoci, per lo scopo da ottenere, la tua soluzione è senz'altro pulita e conservatrice, e se qualcuno chiedesse come cercare di mantenere aggiornato i dati di un client, la proporrei anche io, ma sempre avvertendo sui possibili problemi legati a questa metodologia e accertandomi che sia realmente necessaria.


    Originariamente inviato da franzauker
    In certi casi basta semplicemente un test del tipo "fai una count sulla tabella clienti, verifica se il numero dei record è uguale al recordcount del mio dataset, nel caso aggiorna"
    Se l'aggiornamento si basa solo su questo, basterebbe aggiungere un nuovo cliente e toglierne uno vecchio per far sì che il client non riceva l'aggiornamento, visto che il totale rimane sempre lo stesso.


    Originariamente inviato da franzauker
    PS i miei sono solo suggerimenti, ognuno faccia come crede
    Questo è implicito: se io voglio assumere una persona che stia al telefono e prema un pulsante ogni volta che c'è un nuovo dato da scaricare, si tratta di una mia libera scelta.

    Ma siccome siamo in un forum di discussione, è altrettanto normale discutere le proposte tecniche evidenziando quelli che potrebbero essere problemi o migliorie, a discrezione di ciascuno, anche sbagliando ovviamente (il forum è fatto apposta).


    Originariamente inviato da franzauker
    EDIT: mi sono accorto di non aver fatto un'assunzione che però dipende dal contesto.
    Spedire messaggi UDP ha senso in un ambiente con più client su più macchine fisicamente diverse, ovviamente.

    Ha molto meno senso auto-spedirseli (una singola macchina).

    Se il problema è quindi "più finestre dello stesso programma su una certa macchina" oppure "più finestre dello stesso programma su macchine distinte".
    Si parlava di "altri user" e "altre postazioni", quindi l'assunzione è giusta.

    Ciao!
    MARCO BREVEGLIERI
    Software and Web Developer, Teacher and Consultant

    Home | Blog | Delphi Podcast | Twitch | Altro...

  10. #10
    Utente di HTML.it
    Registrato dal
    Jan 2011
    Messaggi
    1,469
    La domanda posta, ossia questa
    il problema e' sempre lo stesso:
    se USER1 aggiunge/modifica/cancella un record... tale modifica verra' vista USER2 solo nel momento in cui USER2 effettua close e open della tabella.

    io l'ho interpretata "come fare in modo che l'USER2 veda le modifiche SUBITO, anzichè quando fa un close/open?


    Tu hai detto che "non ti sembrava una gran soluzione", senza fare distinzioni, altrimenti non ci sarebbe stato alcun problema.
    Confermo che non è una gran soluzione quello di usare una tabella e scriverci sopra le ultime "viste"

    avevo pensato cosi:
    creo una tabella nel database:
    codice:
    CREATE TABLE TabellaUltimoAggiornamento(
    ID INTEGER NOT NULL PRIMARY KEY,
    NomeTabella VARCHAR(100),
    UltimoAgg varchar(16)); /* yyyymmddhhmmss */


    aggiornando il record relativo alla tabella modificata ogni volta che che viene effettuato un insert/update/delete nella medesima tabella.

    Continua a non sembrarmi una gran soluzione
    Il traffico è generato dai dati aggiornati che transitano, non dai messaggi UDP usati come notifica.
    Se vuoi i dati aggiornati (che sono il requisito di progetto) -> li devi fetchare -> devi avere il traffico.
    Non è che ci siano alternative
    Senza aggiungere un meccanismo di notifica, questo lo fanno normalmente i componenti Delphi al momento dell'invio dei dati (è la "riconciliazione").
    ??? Sono un pochino perplesso, magari parli di un meccanismo che non conosco

    I casi frequenti che tu indichi, in realtà, sono casi specifici della tua applicazione, che ha requisiti particolari e che, giustamente (ci mancherebbe) hai risolto nel modo che hai descritto.
    Bhè diciamo che la richiesta di avere il refresh dei dati il prima possibile è comune tra tutti i clienti.
    Non ne ho ancora trovato uno che mi abbia chiesto il contrario, bisogna però precisare che i "miei clienti" non sono "tutti i clienti del mondo"

    Le performance diminuiscono senz'altro, visto che - oltre alla normale gestione dei dati che rimane - l'applicazione deve ricevere messaggi di aggiornamento e scaricarsi in automatico pacchetti di dati che, in un meccanismo di "riconciliazione" normale (quello incorporato nel componente ClientDataSet, ad esempio) non sarebbe necessario, e questo lo si nota molto di più se si esce da una rete locale e si approda a Internet.
    Continuo a non essere particolarmente d'accordo, per la semplice considerazione che se i client devono avere i dati, da qualche parte li devono fetchare (client intesi come macchine distinte).

    E, in qualsiasi modo scegli, li devi comunque far arrivare
    Il punto, come dicevo, è dato dal fatto che la tua applicazione gestisce una casistica che necessariamente, come prerequisito, richiede di dover fare questa operazione per risolvere specifiche esigenze del cliente, quindi l'operazione è necessaria e la questione del tempo aggiuntivo introdotto per gestire i messaggi sulla rete è ben bilanciata dalla risoluzione di specifici problemi, quindi è accettabile.
    In realtà, come accennato, il "refresh immediato" può essere esteso a 1, alcune o tutte le tabelle.

    Sta alla scelta (ed esperienza) del progettista trovare il "giusto" bilanciamento.
    La mia obiezione infatti è questa: l'introduzione del meccanismo che hai descritto e le istruzioni annesse NON sono necessarie per gestire la concorrenza, poiché questa è già gestita dai componenti standard di Delphi.
    Concorrenza intesa con la domanda posta, ossia "refresh"
    Infatti, tenuto conto che un PC potrebbe disconnettersi e non ricevere il messaggio,
    Se è disconnesso dalla rete -> lo sarà anche dal server SQL (non trattiamo le connessioni stateful, che non mi paiono corrispondenti al profilo della domanda)
    oppure che il messaggio potrebbe arrivare corrotto,
    Su una LAN è sostanzialmente impossibile, (tralascio i vari componentini con CRC nei messaggi etc)
    il client non saprebbe come aggiornare i propri dati;
    Certo, e non fa nulla
    detto questo, la tua soluzione NON è sufficiente a garantire la gestione corretta della concorrenza, e infatti risolve un altro problema, cioè quello di aumentare la probabilità che il client possieda già - per comodità dell'utente - i dati più aggiornati possibili.
    In realtà si possono mettere facilmente in piedi meccanismi simili al 3way handshaking, ossia messaggi "di ritorno".
    Ma, nella mia esperienza, su LAN mai e poi mai ho avuto questi problemi


    Intendiamoci, per lo scopo da ottenere, la tua soluzione è senz'altro pulita e conservatrice, e se qualcuno chiedesse come cercare di mantenere aggiornato i dati di un client...
    Evidentemente avevo capito male la domanda posta (anche se non mi pare)

    ...Se l'aggiornamento si basa solo su questo, basterebbe aggiungere un nuovo cliente e toglierne uno vecchio per far sì che il client non riceva l'aggiornamento, visto che il totale rimane sempre lo stesso.
    Normalmente i clienti non si cancellano mai (anzi, diciamo mai) per non de-normalizzare gli archivi.
    Si flaggano "obsoleti" (al più).
    In questo caso il problema è davvero la count(*) [mi riferisco a mysql].
    In certi casi i clienti sono 400.000, e contarli è devastante

    Comunque ho solo provato a dare qualche suggerimento, non mi intendo molto di queste cose.

    Ciao!

Permessi di invio

  • Non puoi inserire discussioni
  • Non puoi inserire repliche
  • Non puoi inserire allegati
  • Non puoi modificare i tuoi messaggi
  •  
Powered by vBulletin® Version 4.2.1
Copyright © 2025 vBulletin Solutions, Inc. All rights reserved.