Scrivere all'inizio di un file qualcosa che conosci solo alla fine


9

Sfondo: sto scrivendo il codice C del microcontrollore per scrivere un file EBML. EBML è come un XML binario con elementi nidificati, ma invece di tag di inizio e fine, c'è un ID di inizio, lunghezza e quindi i dati. Sto scrivendo questo in Flash esterno in un'applicazione a bassa potenza, quindi vorrei limitare al minimo gli accessi al flash. Anche la memoria è limitata, perché nulla è mai facile.

Quando riesco a conservare l'intero elemento EBML in memoria, generarlo è semplice perché posso tornare indietro e riempire la lunghezza di ciascun elemento dopo aver saputo quale sia quella lunghezza. Il problema è cosa fare quando non riesco a trattenere l'intero elemento in memoria. Le opzioni che vedo sono:

  • Scrivi quello che so, poi torna indietro e aggiungi le lunghezze (più semplice, ma aggiunge più accesso flash di quello che voglio)
  • Calcola la lunghezza di ogni elemento prima di iniziare a scriverlo (relativamente semplice, ma molto tempo del processore)
  • Cambia modalità una volta che la mia memoria si riempie, in modo che io continui attraverso i dati, ma solo per calcolare le lunghezze per gli elementi già riservati in memoria. Quindi scrivi quello che ho in memoria, torna indietro e continua a elaborare i dati da dove avevo interrotto. (La mia opzione preferita finora)
  • Assegna agli elementi una lunghezza massima o peggiore quando devono essere scritti e la loro lunghezza finale non è ancora nota. (Più facile di quanto sopra, ma potrebbe ritorcersi contro e sprecare spazio)

Domanda: sembra che questo dovrebbe essere un problema relativamente comune a cui la gente ha pensato. So che può succedere anche quando si formano alcuni pacchetti di dati. C'è una tecnica migliore / più comune / più accettata che mi manca qui? O solo alcuni termini per il problema che posso cercare?


1
/ sccs funziona in questo modo: scrive il checksum di tutti i byte all'inizio del file dopo aver finito di scrivere. Funziona alla grande su Unix che possono eseguire atomicamente le operazioni di file necessarie (ad esempio Solaris) e causa strani problemi sporadici su Unix che non possono farlo, ad esempio Linux
moscerino

Risposte:


2

Se non sai quanto tempo durerà il tuo payload, questo è raramente motivo di preoccupazione anche se non ricordi la posizione e riempi la lunghezza in seguito:

Basta annotare "dimensione sconosciuta".

Tale funzione dipende dal payload costituito da elementi EBML e il seguente elemento non è tuttavia un elemento figlio valido.

Se lo desideri, puoi successivamente canonicalizzare l'EBML risultante offline come preferisci, ad esempio "nessuna dimensione sconosciuta, dimensione minima" o "dimensione minima, evita dimensioni sconosciute".


Per i dettagli, consultare la bozza di RFC EBML su matroska.org.


Questo è fantastico! È qualcosa di cui non ero a conoscenza ed evita il problema principale, ma vorrei comunque ricevere indicazioni su un buon modo per risolvere il problema principale. L'uso di un elemento di dimensione sconosciuto sembra limitare la compatibilità futura, poiché il vecchio software usciva prematuramente con nuovi elementi.
pscheidler

Hai bisogno del giusto DTD o non puoi davvero decodificare EBML. Bene, se tutti gli elementi sconosciuti sono dimensionati, puoi saltarli, ma è abbastanza? Post-processa qualsiasi EBML che desideri archiviare offline, se lo è.
Deduplicatore

Stiamo usando il nostro schema, che si espanderà. È stato progettato con la consapevolezza che i software più vecchi potrebbero eventualmente saltare alcuni dati. Ma questa è una grande caratteristica di EBML di cui non ero a conoscenza, quindi accetto la risposta.
pscheidler,

0

Se un singolo elemento con un numero fisso di sottoelementi è troppo grande, forse dovresti provare a dividerlo nello schema. Non conosco questo formato, ma molto probabilmente puoi definirne una lunghezza massima.

Per le sequenze potresti provare a definire il numero massimo di sottoelementi e "stream" rimanenti nel file successivo

Per elementi potenzialmente superiori alla dimensione massima della memoria preparare uno stack contenente coppie: posizione della lunghezza dell'elemento riservata e contatore della lunghezza. Su pop salva il contatore corrente nel marker corrente e aggiungi il suo valore al contatore successivo.

In generale, cerca di ridurre al minimo il numero di elementi troppo grandi


Bene, probabilmente potrebbe farlo per i suoi elementi EBML, ma ciò non lo aiuta ancora con l'elemento genitore.
Deduplicatore

La tua idea funzionerebbe, ma preferirei creare un sistema in grado di gestire elementi di grandi dimensioni, invece di limitare lo schema in modo da evitare elementi di grandi dimensioni.
pscheidler

Questa soluzione funzionerà anche per elementi di grandi dimensioni, basta essere attenti alle dimensioni dello stack. E se si tratta di schema ... pensalo come una lingua utilizzata dalle tue applicazioni, se uno non è in grado di gestirne uno complesso, allora l'altro dovrebbe adattarsi o è richiesto un traduttore. Molti sviluppatori (almeno quelli C / C ++ che conosco) tendono ad evitare cambiamenti di schema / progettazione come se fosse un incendio, che in seguito si tradurrebbe in un sistema scadente. Se un altro componente non è in grado di regolare, forse è scarsamente decomposto / progettato. Se ci sono altri motivi per non cambiare, allora probabilmente dovresti considerare l'uso di un altro hardware
Whoot

0

KISS e YAGNI.
Scegli l'opzione # 1 e se diventa un vero problema, solo allora ripeterlo.

Almeno per casi d'uso simili con formati binari simili, quando solo un paio di valori dovevano essere compilati in questo modo, questa è la soluzione più semplice / facile / migliore. Se devi farlo su ogni singolo pezzo di dati, allora potrebbe essere un difetto nell'architettura.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.