OVERALL STATES, defining interaction with innd: F refers to the main feed file as written by innd D refers to the flushing file _flushing START | ,-->--. check F, D | | | | | | | | <----------------<---------------------------------'| | | F exists | | | D ENOENT | | | duct opens F | | V | | Normal | | F: innd writing, duct reading | | D: ENOENT | | | | | | duct decides time to flush | | | duct makes hardlink | | | | | V <------------------------'| | Hardlinked F==D | | F == D: innd writing, duct reading both exist | ^ | | | | duct unlinks F | | | <-----------<-------------<--'| | | open D F ENOENT | | | if exists | | | | | V <---------------------. | | Moved | | | F: ENOENT | | | D: innd writing, duct reading; or ENOENT | | | | | | | | duct requests flush of feed | | | | (others can too, harmlessly) | | | V | | | Flushing | | | F: ENOENT | | | D: innd flushing, duct; or ENOENT | | | | | | | | inndcomm flush fails | | | |`-------------------------->------------------' | | | | | | inndcomm reports no such site | | |`---------------------------------------------------- | -. | | | | | | innd finishes writing D, creates F | | | | inndcomm reports flush successful | | | | | | | V | | | Separated <----------------' | | F: innd writing F!=D / | D: duct reading; or ENOENT both exist / | | / | | duct gets to the end of D / | | duct opens F too / | V / | Finishing / | F: innd writing, duct reading | | D: duct finishing V | | Dropping | | duct finishes processing D F: ENOENT | V duct unlinks D D: duct reading | | | `--<--' | duct finishes | processing D | duct unlinks D | duct exits V Dropped F: ENOENT D: ENOENT duct not running "duct reading" means innduct is reading the file but also overwriting processed tokens. We implement this as follows: .=======. ||START|| `=======' | | open F | | F ENOENT |`---------------------------------------------------. F OPEN OK | | |`---------------- - - - | D ENOENT | D EXISTS see OVERALL STATES diagram | | for full startup logic | ,--------->| | | V | | ============ try to | | NORMAL open D | | [Normal] | | main F tail | | ============ V | | | | | F IS SO BIG WE SHOULD FLUSH, OR TIMEOUT | ^ | hardlink F to D | | [Hardlinked] | | | unlink F | | | our handle onto F is now onto D | | [Moved] | | | | | |<-------------------<---------------------<---------+ | | | | | spawn inndcomm flush | | V | | ================== | | FLUSHING[-ABSENT] | | [Flushing] | | main D tail/none | | ================== | | | | | | INNDCOMM FLUSH FAILS ^ | |`----------------------->----------. | | | | | | | NO SUCH SITE V | ^ |`--------------->----. ==================== | | | \ FLUSHFAILED[-ABSENT] | | | \ [Moved] | | | FLUSH OK \ main D tail/none | | | open F \ ==================== | | | \ | | | | \ | TIME TO RETRY | | |`------->----. ,---<---'\ `----------------' | | D NONE | | D NONE `----. | V | | V | ============= V V ============ | SEPARATED-1 | | DROPPING-1 | flsh->rd!=0 | | flsh->rd!=0 | [Separated] | | [Dropping] | main F idle | | main none | flsh D tail | | flsh D tail | ============= | | ============ | | | | install | ^ | EOF ON D | | defer | EOF ON D | V | | V | =============== | | =============== | SEPARATED-2 | | DROPPING-2 | flsh->rd==0 | V flsh->rd==0 | [Finishing] | | [Dropping] | main F tail | `. main none | flsh D closed | `. flsh D closed | =============== V `. =============== | | `. | | | ALL D PROCESSED `. | ALL D PROCESSED | V install defer as backlog `. | install defer ^ | close D `. | close D | | unlink D `. | unlink D | | | | | | V V `----------' ============== DROPPED [Dropped] main none flsh none some backlog ============== | | ALL BACKLOG DONE | | unlink lock | exit V ========== (ESRCH) [Droppped] ========== rune for printing diagrams: a2ps -R -B -ops README.states