Qual è un modo efficace per convertire un sistema mappato in memoria condivisa in un altro modello di accesso ai dati?

7

Ho una base di codice progettata attorno alla memoria condivisa. Ogni processo che deve accedere alla memoria lo mappa nel proprio spazio di indirizzamento. Le strutture dati nella memoria condivisa sono direttamente accessibili, cioè non c'è API. Ad esempio:

Supponi quanto segue:

typedef struct {
  int x;
  int y;
  struct {
    int a;
    int b;
  } z;
} myStruct;

myStruct s;

Quindi un processo potrebbe accedere a questa struttura come:

myStruct *s = mapGlobalMem();

E usalo come:

int tmpX = s->x;

La maggior parte delle informazioni nella struttura globale sono informazioni di configurazione che vengono impostate una volta e lette più volte. Vorrei memorizzare queste informazioni in un database e sviluppare un'API per accedere al database. Il problema è che questi riferimenti sono cosparsi in tutto il codice. Ho bisogno di un modo per analizzare il codice e identificare i riferimenti alle strutture globali che dovranno essere refactored.

Ho esaminato l'utilizzo di ANTLR per creare un parser che identificherà i riferimenti a un piccolo insieme di strutture e inserirli in un tabella dei simboli personalizzati. Potrei quindi utilizzare questa tabella dei simboli per identificare quali file di origine devono essere sottoposti a refactoring. Sembra un approccio promettente.

Quali altri approcci ci sono? Certo, sto cercando un approccio programmatico. Ci sono troppi file sorgente per esaminarli visivamente.

Questo è tutto normale ANSI C. Nient'altro.

    
posta Rob Jones 14.08.2011 - 19:41
fonte

4 risposte

1

Suppongo che faccia parte di un grande progetto perché hai citato "troppi file sorgente". Non sono chiaro sull'obiettivo finale. Puoi inserire la configurazione in un database e modificare mapGlobalMem () per popolare & restituisce una posizione di memoria che contiene la configurazione. In questo modo non stai violando il tuo contratto con il codice corrente ma hai spostato la configurazione "fuori" dal processo. Suppongo che tu non voglia effettuare una chiamata al database ogni volta che qualcuno tenta di accedere alle informazioni di configurazione.

Ora, se sei preoccupato per la freschezza e quindi devi rifattorizzarlo in un'API, ti suggerirei di cercare tutte le occorrenze di mapGlobalMem () e myStruct. Questo dovrebbe darti una stima del parco giochi.

In definitiva, se stai cercando di automatizzare questa modifica, suppongo che impiegheresti più tempo ad automatizzarla rispetto a una semplice sed / find-replace.

    
risposta data 21.11.2011 - 00:08
fonte
0

Poiché il tuo codice è in C - rinomina il typedef, crea il codice, guarda il compilatore lamentarsi. Ora sai dove si fa riferimento alla struttura. Dal momento che convertirai il codice per utilizzare un modo completamente diverso di accedere a questi dati, avrai comunque bisogno di analizzare ogni caso. Quindi metti un caffè fresco e fai l'hacking ...: -)

    
risposta data 17.08.2011 - 23:21
fonte
0

Un approccio un po 'meno all-or-nothing potrebbe essere quello di popolare la struttura globale e restituire solo i puntatori "const" ad esso. Consenti agli avvertimenti del compilatore di essere la tua guida, ancora una volta, ma solo "devi" aggiornare gli scrittori . Inizializza la struct una volta (aggiungi un flag is_configured, forse come statico con scope del file?) Alla prima richiesta, e se viene chiamata la funzione "writer", aggiornare la struct e il database di backup. @Lasse ha la risposta "giusta", ma potrebbe essere quella "utile" per il duct-taping a breve termine.

Lato negativo: dovresti gestire una sorta di segnale asincrono se un altro processo modifica un'impostazione. Su Unix / Linux, SIGWINCH è un buon candidato e SIGHUP è piuttosto tradizionale. (SIGWINCH ottiene risultati spuri se stai eseguendo da un xterm che viene ridimensionato, ma per un demone di sfondo non viene mai chiamato e il valore predefinito è IGNored. SIGHUP per impostazione predefinita ti uccide.

    
risposta data 28.12.2011 - 04:38
fonte
0

In base alla tua descrizione, ecco come definirei l'obiettivo.

  1. Il meccanismo di utilizzo per l'applicazione finale dovrebbe rimanere lo stesso; cioè.

    myStruct *s = mapGlobalMem(); int tmpX = s->x; non dovrebbe cambiare. Ciò implica che l'applicazione che utilizza questo GlobalMap non dovrebbe essere consapevole del fatto che tale mappa proviene effettivamente dal database.

  2. Entrambi i meccanismi dovrebbero continuare a funzionare - cioè l'app esistente dovrebbe funzionare come è dove sta attualmente ricevendo la mappa o in aggiunta ora può ottenerla anche dal DB.

  3. Il sistema dovrebbe essere thread-safe e multi-instance capace. Pensalo come Malloc (). Gestisce le strutture di dati interne di varie cose. Tuttavia, se più thread si avvicinano simultaneamente non rovina la struttura e thread / oggetti diversi possono richiedere memoria e vengono assegnati blocchi diversi.

  4. La base di codice globale è molto più grande, quindi l'unità di modifiche dovrebbe essere isolata solo su specifici segmenti centrali. cioè cambierei la parte di creazione della mappa (centrale) piuttosto che la parte di accesso alla mappa (distribuita su tutto il codice). In questo caso

  5. Dato che, comunque, sto estendendo questo sistema in un aspetto - diciamo che la connettività con DB - i può anche estenderlo in modo tale che domani altri meccanismi possano essere usati per fornire tali informazioni.

Suppongo che DATA che è rappresentato in *s sia ora recuperato dal DB piuttosto che dalla sorgente corrente. (Se ho torto qui - potrebbe essere necessario riscrivere la maggior parte della risposta qui sotto).

Ecco cosa vorrei fare.

  1. C'è un'estensione della funzionalità primaria con una nuova API: qualcosa di simile setGlobalMem (info);

Il info è il punto in cui decido quale fonte utilizzare, se la metodologia corrente o db e se in DB, quale query la ridistribuisce essenzialmente. In alternativa si può anche immaginare che la configurazione possa venire attraverso un file .conf o attraverso qualche altra forma di input.

  1. Riduci l'importanza dell'API principale per supportare entrambe le opzioni. Fondamentalmente avrei un puntatore protetto qualcosa come *currentValidMap . Ogni volta che c'è un aggiornamento da / a qualsiasi origine dati, la s finale viene aggiornata come una di queste; probabilmente qualcosa di simile potrebbe semplicemente esistere.

  2. Potrei avere una funzione aggiuntiva come updateMap(section,source) usata in modo restrittivo per sovrascrivere alcune opzioni di configurazione localmente, ad esempio. Qui vorrei usare parte delle informazioni attraverso un'altra fonte. Ancora più importante potrei anche avere lockMap per chiudere eventuali ulteriori modifiche alla mappa. Tutte queste API sono utilizzate centralmente per stabilire la mappa come richiesto.

Sto assumendo le cose - quindi potrebbe essere inaccurato in alcuni casi a causa di questo.

Fondamentalmente mai modificherò qualsiasi altra parte dell'applicazione che è solo leggendo i dati di configurazione - non hanno business per capire dove i dati di configurazione sono proveniente da .

    
risposta data 02.01.2012 - 09:03
fonte

Leggi altre domande sui tag