design.lyx 66 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727
  1. #LyX 2.0 created this file. For more info see http://www.lyx.org/
  2. \lyxformat 413
  3. \begin_document
  4. \begin_header
  5. \textclass article
  6. \use_default_options true
  7. \maintain_unincluded_children false
  8. \language english
  9. \language_package default
  10. \inputencoding auto
  11. \fontencoding global
  12. \font_roman default
  13. \font_sans default
  14. \font_typewriter default
  15. \font_default_family default
  16. \use_non_tex_fonts false
  17. \font_sc false
  18. \font_osf false
  19. \font_sf_scale 100
  20. \font_tt_scale 100
  21. \graphics default
  22. \default_output_format default
  23. \output_sync 0
  24. \bibtex_command default
  25. \index_command default
  26. \paperfontsize default
  27. \use_hyperref false
  28. \papersize default
  29. \use_geometry false
  30. \use_amsmath 1
  31. \use_esint 1
  32. \use_mhchem 1
  33. \use_mathdots 1
  34. \cite_engine basic
  35. \use_bibtopic false
  36. \use_indices false
  37. \paperorientation portrait
  38. \suppress_date false
  39. \use_refstyle 0
  40. \index Index
  41. \shortcut idx
  42. \color #008000
  43. \end_index
  44. \secnumdepth 3
  45. \tocdepth 3
  46. \paragraph_separation indent
  47. \paragraph_indentation default
  48. \quotes_language english
  49. \papercolumns 1
  50. \papersides 1
  51. \paperpagestyle default
  52. \tracking_changes true
  53. \output_changes true
  54. \html_math_output 0
  55. \html_css_as_file 0
  56. \html_be_strict false
  57. \end_header
  58. \begin_body
  59. \begin_layout Title
  60. NTDB: Redesigning The Trivial DataBase
  61. \end_layout
  62. \begin_layout Author
  63. Rusty Russell, IBM Corporation
  64. \end_layout
  65. \begin_layout Date
  66. 19 June 2012
  67. \end_layout
  68. \begin_layout Abstract
  69. The Trivial DataBase on-disk format is 32 bits; with usage cases heading
  70. towards the 4G limit, that must change.
  71. This required breakage provides an opportunity to revisit TDB's other design
  72. decisions and reassess them.
  73. \end_layout
  74. \begin_layout Section
  75. Introduction
  76. \end_layout
  77. \begin_layout Standard
  78. The Trivial DataBase was originally written by Andrew Tridgell as a simple
  79. key/data pair storage system with the same API as dbm, but allowing multiple
  80. readers and writers while being small enough (< 1000 lines of C) to include
  81. in SAMBA.
  82. The simple design created in 1999 has proven surprisingly robust and performant
  83. , used in Samba versions 3 and 4 as well as numerous other projects.
  84. Its useful life was greatly increased by the (backwards-compatible!) addition
  85. of transaction support in 2005.
  86. \end_layout
  87. \begin_layout Standard
  88. The wider variety and greater demands of TDB-using code has lead to some
  89. organic growth of the API, as well as some compromises on the implementation.
  90. None of these, by themselves, are seen as show-stoppers, but the cumulative
  91. effect is to a loss of elegance over the initial, simple TDB implementation.
  92. Here is a table of the approximate number of lines of implementation code
  93. and number of API functions at the end of each year:
  94. \end_layout
  95. \begin_layout Standard
  96. \begin_inset Tabular
  97. <lyxtabular version="3" rows="12" columns="3">
  98. <features tabularvalignment="middle">
  99. <column alignment="center" valignment="top" width="0">
  100. <column alignment="center" valignment="top" width="0">
  101. <column alignment="center" valignment="top" width="0">
  102. <row>
  103. <cell alignment="center" valignment="top" topline="true" bottomline="true" leftline="true" usebox="none">
  104. \begin_inset Text
  105. \begin_layout Plain Layout
  106. Year End
  107. \end_layout
  108. \end_inset
  109. </cell>
  110. <cell alignment="center" valignment="top" topline="true" bottomline="true" leftline="true" usebox="none">
  111. \begin_inset Text
  112. \begin_layout Plain Layout
  113. API Functions
  114. \end_layout
  115. \end_inset
  116. </cell>
  117. <cell alignment="center" valignment="top" topline="true" bottomline="true" leftline="true" rightline="true" usebox="none">
  118. \begin_inset Text
  119. \begin_layout Plain Layout
  120. Lines of C Code Implementation
  121. \end_layout
  122. \end_inset
  123. </cell>
  124. </row>
  125. <row>
  126. <cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
  127. \begin_inset Text
  128. \begin_layout Plain Layout
  129. 1999
  130. \end_layout
  131. \end_inset
  132. </cell>
  133. <cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
  134. \begin_inset Text
  135. \begin_layout Plain Layout
  136. 13
  137. \end_layout
  138. \end_inset
  139. </cell>
  140. <cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
  141. \begin_inset Text
  142. \begin_layout Plain Layout
  143. 1195
  144. \end_layout
  145. \end_inset
  146. </cell>
  147. </row>
  148. <row>
  149. <cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
  150. \begin_inset Text
  151. \begin_layout Plain Layout
  152. 2000
  153. \end_layout
  154. \end_inset
  155. </cell>
  156. <cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
  157. \begin_inset Text
  158. \begin_layout Plain Layout
  159. 24
  160. \end_layout
  161. \end_inset
  162. </cell>
  163. <cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
  164. \begin_inset Text
  165. \begin_layout Plain Layout
  166. 1725
  167. \end_layout
  168. \end_inset
  169. </cell>
  170. </row>
  171. <row>
  172. <cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
  173. \begin_inset Text
  174. \begin_layout Plain Layout
  175. 2001
  176. \end_layout
  177. \end_inset
  178. </cell>
  179. <cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
  180. \begin_inset Text
  181. \begin_layout Plain Layout
  182. 32
  183. \end_layout
  184. \end_inset
  185. </cell>
  186. <cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
  187. \begin_inset Text
  188. \begin_layout Plain Layout
  189. 2228
  190. \end_layout
  191. \end_inset
  192. </cell>
  193. </row>
  194. <row>
  195. <cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
  196. \begin_inset Text
  197. \begin_layout Plain Layout
  198. 2002
  199. \end_layout
  200. \end_inset
  201. </cell>
  202. <cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
  203. \begin_inset Text
  204. \begin_layout Plain Layout
  205. 35
  206. \end_layout
  207. \end_inset
  208. </cell>
  209. <cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
  210. \begin_inset Text
  211. \begin_layout Plain Layout
  212. 2481
  213. \end_layout
  214. \end_inset
  215. </cell>
  216. </row>
  217. <row>
  218. <cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
  219. \begin_inset Text
  220. \begin_layout Plain Layout
  221. 2003
  222. \end_layout
  223. \end_inset
  224. </cell>
  225. <cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
  226. \begin_inset Text
  227. \begin_layout Plain Layout
  228. 35
  229. \end_layout
  230. \end_inset
  231. </cell>
  232. <cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
  233. \begin_inset Text
  234. \begin_layout Plain Layout
  235. 2552
  236. \end_layout
  237. \end_inset
  238. </cell>
  239. </row>
  240. <row>
  241. <cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
  242. \begin_inset Text
  243. \begin_layout Plain Layout
  244. 2004
  245. \end_layout
  246. \end_inset
  247. </cell>
  248. <cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
  249. \begin_inset Text
  250. \begin_layout Plain Layout
  251. 40
  252. \end_layout
  253. \end_inset
  254. </cell>
  255. <cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
  256. \begin_inset Text
  257. \begin_layout Plain Layout
  258. 2584
  259. \end_layout
  260. \end_inset
  261. </cell>
  262. </row>
  263. <row>
  264. <cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
  265. \begin_inset Text
  266. \begin_layout Plain Layout
  267. 2005
  268. \end_layout
  269. \end_inset
  270. </cell>
  271. <cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
  272. \begin_inset Text
  273. \begin_layout Plain Layout
  274. 38
  275. \end_layout
  276. \end_inset
  277. </cell>
  278. <cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
  279. \begin_inset Text
  280. \begin_layout Plain Layout
  281. 2647
  282. \end_layout
  283. \end_inset
  284. </cell>
  285. </row>
  286. <row>
  287. <cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
  288. \begin_inset Text
  289. \begin_layout Plain Layout
  290. 2006
  291. \end_layout
  292. \end_inset
  293. </cell>
  294. <cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
  295. \begin_inset Text
  296. \begin_layout Plain Layout
  297. 52
  298. \end_layout
  299. \end_inset
  300. </cell>
  301. <cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
  302. \begin_inset Text
  303. \begin_layout Plain Layout
  304. 3754
  305. \end_layout
  306. \end_inset
  307. </cell>
  308. </row>
  309. <row>
  310. <cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
  311. \begin_inset Text
  312. \begin_layout Plain Layout
  313. 2007
  314. \end_layout
  315. \end_inset
  316. </cell>
  317. <cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
  318. \begin_inset Text
  319. \begin_layout Plain Layout
  320. 66
  321. \end_layout
  322. \end_inset
  323. </cell>
  324. <cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
  325. \begin_inset Text
  326. \begin_layout Plain Layout
  327. 4398
  328. \end_layout
  329. \end_inset
  330. </cell>
  331. </row>
  332. <row>
  333. <cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
  334. \begin_inset Text
  335. \begin_layout Plain Layout
  336. 2008
  337. \end_layout
  338. \end_inset
  339. </cell>
  340. <cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
  341. \begin_inset Text
  342. \begin_layout Plain Layout
  343. 71
  344. \end_layout
  345. \end_inset
  346. </cell>
  347. <cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
  348. \begin_inset Text
  349. \begin_layout Plain Layout
  350. 4768
  351. \end_layout
  352. \end_inset
  353. </cell>
  354. </row>
  355. <row>
  356. <cell alignment="center" valignment="top" topline="true" bottomline="true" leftline="true" usebox="none">
  357. \begin_inset Text
  358. \begin_layout Plain Layout
  359. 2009
  360. \end_layout
  361. \end_inset
  362. </cell>
  363. <cell alignment="center" valignment="top" topline="true" bottomline="true" leftline="true" usebox="none">
  364. \begin_inset Text
  365. \begin_layout Plain Layout
  366. 73
  367. \end_layout
  368. \end_inset
  369. </cell>
  370. <cell alignment="center" valignment="top" topline="true" bottomline="true" leftline="true" rightline="true" usebox="none">
  371. \begin_inset Text
  372. \begin_layout Plain Layout
  373. 5715
  374. \end_layout
  375. \end_inset
  376. </cell>
  377. </row>
  378. </lyxtabular>
  379. \end_inset
  380. \end_layout
  381. \begin_layout Standard
  382. This review is an attempt to catalog and address all the known issues with
  383. TDB and create solutions which address the problems without significantly
  384. increasing complexity; all involved are far too aware of the dangers of
  385. second system syndrome in rewriting a successful project like this.
  386. \end_layout
  387. \begin_layout Standard
  388. Note: the final decision was to make ntdb a separate library, with a separarate
  389. 'ntdb' namespace so both can potentially be linked together.
  390. This document still refers to
  391. \begin_inset Quotes eld
  392. \end_inset
  393. tdb
  394. \begin_inset Quotes erd
  395. \end_inset
  396. everywhere, for simplicity.
  397. \end_layout
  398. \begin_layout Section
  399. API Issues
  400. \end_layout
  401. \begin_layout Subsection
  402. tdb_open_ex Is Not Expandable
  403. \end_layout
  404. \begin_layout Standard
  405. The tdb_open() call was expanded to tdb_open_ex(), which added an optional
  406. hashing function and an optional logging function argument.
  407. Additional arguments to open would require the introduction of a tdb_open_ex2
  408. call etc.
  409. \end_layout
  410. \begin_layout Subsubsection
  411. Proposed Solution
  412. \begin_inset CommandInset label
  413. LatexCommand label
  414. name "attributes"
  415. \end_inset
  416. \end_layout
  417. \begin_layout Standard
  418. tdb_open() will take a linked-list of attributes:
  419. \end_layout
  420. \begin_layout LyX-Code
  421. enum tdb_attribute {
  422. \end_layout
  423. \begin_layout LyX-Code
  424. TDB_ATTRIBUTE_LOG = 0,
  425. \end_layout
  426. \begin_layout LyX-Code
  427. TDB_ATTRIBUTE_HASH = 1
  428. \end_layout
  429. \begin_layout LyX-Code
  430. };
  431. \end_layout
  432. \begin_layout LyX-Code
  433. struct tdb_attribute_base {
  434. \end_layout
  435. \begin_layout LyX-Code
  436. enum tdb_attribute attr;
  437. \end_layout
  438. \begin_layout LyX-Code
  439. union tdb_attribute *next;
  440. \end_layout
  441. \begin_layout LyX-Code
  442. };
  443. \end_layout
  444. \begin_layout LyX-Code
  445. struct tdb_attribute_log {
  446. \end_layout
  447. \begin_layout LyX-Code
  448. struct tdb_attribute_base base; /* .attr = TDB_ATTRIBUTE_LOG */
  449. \end_layout
  450. \begin_layout LyX-Code
  451. tdb_log_func log_fn;
  452. \end_layout
  453. \begin_layout LyX-Code
  454. void *log_private;
  455. \end_layout
  456. \begin_layout LyX-Code
  457. };
  458. \end_layout
  459. \begin_layout LyX-Code
  460. struct tdb_attribute_hash {
  461. \end_layout
  462. \begin_layout LyX-Code
  463. struct tdb_attribute_base base; /* .attr = TDB_ATTRIBUTE_HASH */
  464. \end_layout
  465. \begin_layout LyX-Code
  466. tdb_hash_func hash_fn;
  467. \end_layout
  468. \begin_layout LyX-Code
  469. void *hash_private;
  470. \end_layout
  471. \begin_layout LyX-Code
  472. };
  473. \end_layout
  474. \begin_layout LyX-Code
  475. union tdb_attribute {
  476. \end_layout
  477. \begin_layout LyX-Code
  478. struct tdb_attribute_base base;
  479. \end_layout
  480. \begin_layout LyX-Code
  481. struct tdb_attribute_log log;
  482. \end_layout
  483. \begin_layout LyX-Code
  484. struct tdb_attribute_hash hash;
  485. \end_layout
  486. \begin_layout LyX-Code
  487. };
  488. \end_layout
  489. \begin_layout Standard
  490. This allows future attributes to be added, even if this expands the size
  491. of the union.
  492. \end_layout
  493. \begin_layout Subsubsection
  494. Status
  495. \end_layout
  496. \begin_layout Standard
  497. Complete.
  498. \end_layout
  499. \begin_layout Subsection
  500. tdb_traverse Makes Impossible Guarantees
  501. \end_layout
  502. \begin_layout Standard
  503. tdb_traverse (and tdb_firstkey/tdb_nextkey) predate transactions, and it
  504. was thought that it was important to guarantee that all records which exist
  505. at the start and end of the traversal would be included, and no record
  506. would be included twice.
  507. \end_layout
  508. \begin_layout Standard
  509. This adds complexity (see
  510. \begin_inset CommandInset ref
  511. LatexCommand ref
  512. reference "Reliable-Traversal-Adds"
  513. \end_inset
  514. ) and does not work anyway for records which are altered (in particular,
  515. those which are expanded may be effectively deleted and re-added behind
  516. the traversal).
  517. \end_layout
  518. \begin_layout Subsubsection
  519. \begin_inset CommandInset label
  520. LatexCommand label
  521. name "traverse-Proposed-Solution"
  522. \end_inset
  523. Proposed Solution
  524. \end_layout
  525. \begin_layout Standard
  526. Abandon the guarantee.
  527. You will see every record if no changes occur during your traversal, otherwise
  528. you will see some subset.
  529. You can prevent changes by using a transaction or the locking API.
  530. \end_layout
  531. \begin_layout Subsubsection
  532. Status
  533. \end_layout
  534. \begin_layout Standard
  535. Complete.
  536. Delete-during-traverse will still delete every record, too (assuming no
  537. other changes).
  538. \end_layout
  539. \begin_layout Subsection
  540. Nesting of Transactions Is Fraught
  541. \end_layout
  542. \begin_layout Standard
  543. TDB has alternated between allowing nested transactions and not allowing
  544. them.
  545. Various paths in the Samba codebase assume that transactions will nest,
  546. and in a sense they can: the operation is only committed to disk when the
  547. outer transaction is committed.
  548. There are two problems, however:
  549. \end_layout
  550. \begin_layout Enumerate
  551. Canceling the inner transaction will cause the outer transaction commit
  552. to fail, and will not undo any operations since the inner transaction began.
  553. This problem is soluble with some additional internal code.
  554. \end_layout
  555. \begin_layout Enumerate
  556. An inner transaction commit can be cancelled by the outer transaction.
  557. This is desirable in the way which Samba's database initialization code
  558. uses transactions, but could be a surprise to any users expecting a successful
  559. transaction commit to expose changes to others.
  560. \end_layout
  561. \begin_layout Standard
  562. The current solution is to specify the behavior at tdb_open(), with the
  563. default currently that nested transactions are allowed.
  564. This flag can also be changed at runtime.
  565. \end_layout
  566. \begin_layout Subsubsection
  567. Proposed Solution
  568. \end_layout
  569. \begin_layout Standard
  570. Given the usage patterns, it seems that the
  571. \begin_inset Quotes eld
  572. \end_inset
  573. least-surprise
  574. \begin_inset Quotes erd
  575. \end_inset
  576. behavior of disallowing nested transactions should become the default.
  577. Additionally, it seems the outer transaction is the only code which knows
  578. whether inner transactions should be allowed, so a flag to indicate this
  579. could be added to tdb_transaction_start.
  580. However, this behavior can be simulated with a wrapper which uses tdb_add_flags
  581. () and tdb_remove_flags(), so the API should not be expanded for this relatively
  582. -obscure case.
  583. \end_layout
  584. \begin_layout Subsubsection
  585. Status
  586. \end_layout
  587. \begin_layout Standard
  588. Complete; the nesting flag has been removed.
  589. \end_layout
  590. \begin_layout Subsection
  591. Incorrect Hash Function is Not Detected
  592. \end_layout
  593. \begin_layout Standard
  594. tdb_open_ex() allows the calling code to specify a different hash function
  595. to use, but does not check that all other processes accessing this tdb
  596. are using the same hash function.
  597. The result is that records are missing from tdb_fetch().
  598. \end_layout
  599. \begin_layout Subsubsection
  600. Proposed Solution
  601. \end_layout
  602. \begin_layout Standard
  603. The header should contain an example hash result (eg.
  604. the hash of 0xdeadbeef), and tdb_open_ex() should check that the given
  605. hash function produces the same answer, or fail the tdb_open call.
  606. \end_layout
  607. \begin_layout Subsubsection
  608. Status
  609. \end_layout
  610. \begin_layout Standard
  611. Complete.
  612. \end_layout
  613. \begin_layout Subsection
  614. tdb_set_max_dead/TDB_VOLATILE Expose Implementation
  615. \end_layout
  616. \begin_layout Standard
  617. In response to scalability issues with the free list (
  618. \begin_inset CommandInset ref
  619. LatexCommand ref
  620. reference "TDB-Freelist-Is"
  621. \end_inset
  622. ) two API workarounds have been incorporated in TDB: tdb_set_max_dead()
  623. and the TDB_VOLATILE flag to tdb_open.
  624. The latter actually calls the former with an argument of
  625. \begin_inset Quotes eld
  626. \end_inset
  627. 5
  628. \begin_inset Quotes erd
  629. \end_inset
  630. .
  631. \end_layout
  632. \begin_layout Standard
  633. This code allows deleted records to accumulate without putting them in the
  634. free list.
  635. On delete we iterate through each chain and free them in a batch if there
  636. are more than max_dead entries.
  637. These are never otherwise recycled except as a side-effect of a tdb_repack.
  638. \end_layout
  639. \begin_layout Subsubsection
  640. Proposed Solution
  641. \end_layout
  642. \begin_layout Standard
  643. With the scalability problems of the freelist solved, this API can be removed.
  644. The TDB_VOLATILE flag may still be useful as a hint that store and delete
  645. of records will be at least as common as fetch in order to allow some internal
  646. tuning, but initially will become a no-op.
  647. \end_layout
  648. \begin_layout Subsubsection
  649. Status
  650. \end_layout
  651. \begin_layout Standard
  652. Complete.
  653. Unknown flags cause tdb_open() to fail as well, so they can be detected
  654. at runtime.
  655. \end_layout
  656. \begin_layout Subsection
  657. \begin_inset CommandInset label
  658. LatexCommand label
  659. name "TDB-Files-Cannot"
  660. \end_inset
  661. TDB Files Cannot Be Opened Multiple Times In The Same Process
  662. \end_layout
  663. \begin_layout Standard
  664. No process can open the same TDB twice; we check and disallow it.
  665. This is an unfortunate side-effect of fcntl locks, which operate on a per-file
  666. rather than per-file-descriptor basis, and do not nest.
  667. Thus, closing any file descriptor on a file clears all the locks obtained
  668. by this process, even if they were placed using a different file descriptor!
  669. \end_layout
  670. \begin_layout Standard
  671. Note that even if this were solved, deadlock could occur if operations were
  672. nested: this is a more manageable programming error in most cases.
  673. \end_layout
  674. \begin_layout Subsubsection
  675. Proposed Solution
  676. \end_layout
  677. \begin_layout Standard
  678. We could lobby POSIX to fix the perverse rules, or at least lobby Linux
  679. to violate them so that the most common implementation does not have this
  680. restriction.
  681. This would be a generally good idea for other fcntl lock users.
  682. \end_layout
  683. \begin_layout Standard
  684. Samba uses a wrapper which hands out the same tdb_context to multiple callers
  685. if this happens, and does simple reference counting.
  686. We should do this inside the tdb library, which already emulates lock nesting
  687. internally; it would need to recognize when deadlock occurs within a single
  688. process.
  689. This would create a new failure mode for tdb operations (while we currently
  690. handle locking failures, they are impossible in normal use and a process
  691. encountering them can do little but give up).
  692. \end_layout
  693. \begin_layout Standard
  694. I do not see benefit in an additional tdb_open flag to indicate whether
  695. re-opening is allowed, as though there may be some benefit to adding a
  696. call to detect when a tdb_context is shared, to allow other to create such
  697. an API.
  698. \end_layout
  699. \begin_layout Subsubsection
  700. Status
  701. \end_layout
  702. \begin_layout Standard
  703. Complete.
  704. \end_layout
  705. \begin_layout Subsection
  706. TDB API Is Not POSIX Thread-safe
  707. \end_layout
  708. \begin_layout Standard
  709. The TDB API uses an error code which can be queried after an operation to
  710. determine what went wrong.
  711. This programming model does not work with threads, unless specific additional
  712. guarantees are given by the implementation.
  713. In addition, even otherwise-independent threads cannot open the same TDB
  714. (as in
  715. \begin_inset CommandInset ref
  716. LatexCommand ref
  717. reference "TDB-Files-Cannot"
  718. \end_inset
  719. ).
  720. \end_layout
  721. \begin_layout Subsubsection
  722. Proposed Solution
  723. \end_layout
  724. \begin_layout Standard
  725. Reachitecting the API to include a tdb_errcode pointer would be a great
  726. deal of churn, but fortunately most functions return 0 on success and -1
  727. on error: we can change these to return 0 on success and a negative error
  728. code on error, and the API remains similar to previous.
  729. The tdb_fetch, tdb_firstkey and tdb_nextkey functions need to take a TDB_DATA
  730. pointer and return an error code.
  731. It is also simpler to have tdb_nextkey replace its key argument in place,
  732. freeing up any old .dptr.
  733. \end_layout
  734. \begin_layout Standard
  735. Internal locking is required to make sure that fcntl locks do not overlap
  736. between threads, and also that the global list of tdbs is maintained.
  737. \end_layout
  738. \begin_layout Standard
  739. The aim is that building tdb with -DTDB_PTHREAD will result in a pthread-safe
  740. version of the library, and otherwise no overhead will exist.
  741. Alternatively, a hooking mechanism similar to that proposed for
  742. \begin_inset CommandInset ref
  743. LatexCommand ref
  744. reference "Proposed-Solution-locking-hook"
  745. \end_inset
  746. could be used to enable pthread locking at runtime.
  747. \end_layout
  748. \begin_layout Subsubsection
  749. Status
  750. \end_layout
  751. \begin_layout Standard
  752. Incomplete; API has been changed but thread safety has not been implemented.
  753. \end_layout
  754. \begin_layout Subsection
  755. *_nonblock Functions And *_mark Functions Expose Implementation
  756. \end_layout
  757. \begin_layout Standard
  758. CTDB
  759. \begin_inset Foot
  760. status collapsed
  761. \begin_layout Plain Layout
  762. Clustered TDB, see http://ctdb.samba.org
  763. \end_layout
  764. \end_inset
  765. wishes to operate on TDB in a non-blocking manner.
  766. This is currently done as follows:
  767. \end_layout
  768. \begin_layout Enumerate
  769. Call the _nonblock variant of an API function (eg.
  770. tdb_lockall_nonblock).
  771. If this fails:
  772. \end_layout
  773. \begin_layout Enumerate
  774. Fork a child process, and wait for it to call the normal variant (eg.
  775. tdb_lockall).
  776. \end_layout
  777. \begin_layout Enumerate
  778. If the child succeeds, call the _mark variant to indicate we already have
  779. the locks (eg.
  780. tdb_lockall_mark).
  781. \end_layout
  782. \begin_layout Enumerate
  783. Upon completion, tell the child to release the locks (eg.
  784. tdb_unlockall).
  785. \end_layout
  786. \begin_layout Enumerate
  787. Indicate to tdb that it should consider the locks removed (eg.
  788. tdb_unlockall_mark).
  789. \end_layout
  790. \begin_layout Standard
  791. There are several issues with this approach.
  792. Firstly, adding two new variants of each function clutters the API for
  793. an obscure use, and so not all functions have three variants.
  794. Secondly, it assumes that all paths of the functions ask for the same locks,
  795. otherwise the parent process will have to get a lock which the child doesn't
  796. have under some circumstances.
  797. I don't believe this is currently the case, but it constrains the implementatio
  798. n.
  799. \end_layout
  800. \begin_layout Subsubsection
  801. \begin_inset CommandInset label
  802. LatexCommand label
  803. name "Proposed-Solution-locking-hook"
  804. \end_inset
  805. Proposed Solution
  806. \end_layout
  807. \begin_layout Standard
  808. Implement a hook for locking methods, so that the caller can control the
  809. calls to create and remove fcntl locks.
  810. In this scenario, ctdbd would operate as follows:
  811. \end_layout
  812. \begin_layout Enumerate
  813. Call the normal API function, eg tdb_lockall().
  814. \end_layout
  815. \begin_layout Enumerate
  816. When the lock callback comes in, check if the child has the lock.
  817. Initially, this is always false.
  818. If so, return 0.
  819. Otherwise, try to obtain it in non-blocking mode.
  820. If that fails, return EWOULDBLOCK.
  821. \end_layout
  822. \begin_layout Enumerate
  823. Release locks in the unlock callback as normal.
  824. \end_layout
  825. \begin_layout Enumerate
  826. If tdb_lockall() fails, see if we recorded a lock failure; if so, call the
  827. child to repeat the operation.
  828. \end_layout
  829. \begin_layout Enumerate
  830. The child records what locks it obtains, and returns that information to
  831. the parent.
  832. \end_layout
  833. \begin_layout Enumerate
  834. When the child has succeeded, goto 1.
  835. \end_layout
  836. \begin_layout Standard
  837. This is flexible enough to handle any potential locking scenario, even when
  838. lock requirements change.
  839. It can be optimized so that the parent does not release locks, just tells
  840. the child which locks it doesn't need to obtain.
  841. \end_layout
  842. \begin_layout Standard
  843. It also keeps the complexity out of the API, and in ctdbd where it is needed.
  844. \end_layout
  845. \begin_layout Subsubsection
  846. Status
  847. \end_layout
  848. \begin_layout Standard
  849. Complete.
  850. \end_layout
  851. \begin_layout Subsection
  852. tdb_chainlock Functions Expose Implementation
  853. \end_layout
  854. \begin_layout Standard
  855. tdb_chainlock locks some number of records, including the record indicated
  856. by the given key.
  857. This gave atomicity guarantees; no-one can start a transaction, alter,
  858. read or delete that key while the lock is held.
  859. \end_layout
  860. \begin_layout Standard
  861. It also makes the same guarantee for any other key in the chain, which is
  862. an internal implementation detail and potentially a cause for deadlock.
  863. \end_layout
  864. \begin_layout Subsubsection
  865. Proposed Solution
  866. \end_layout
  867. \begin_layout Standard
  868. None.
  869. It would be nice to have an explicit single entry lock which effected no
  870. other keys.
  871. Unfortunately, this won't work for an entry which doesn't exist.
  872. Thus while chainlock may be implemented more efficiently for the existing
  873. case, it will still have overlap issues with the non-existing case.
  874. So it is best to keep the current (lack of) guarantee about which records
  875. will be effected to avoid constraining our implementation.
  876. \end_layout
  877. \begin_layout Subsection
  878. Signal Handling is Not Race-Free
  879. \end_layout
  880. \begin_layout Standard
  881. The tdb_setalarm_sigptr() call allows the caller's signal handler to indicate
  882. that the tdb locking code should return with a failure, rather than trying
  883. again when a signal is received (and errno == EAGAIN).
  884. This is usually used to implement timeouts.
  885. \end_layout
  886. \begin_layout Standard
  887. Unfortunately, this does not work in the case where the signal is received
  888. before the tdb code enters the fcntl() call to place the lock: the code
  889. will sleep within the fcntl() code, unaware that the signal wants it to
  890. exit.
  891. In the case of long timeouts, this does not happen in practice.
  892. \end_layout
  893. \begin_layout Subsubsection
  894. Proposed Solution
  895. \end_layout
  896. \begin_layout Standard
  897. The locking hooks proposed in
  898. \begin_inset CommandInset ref
  899. LatexCommand ref
  900. reference "Proposed-Solution-locking-hook"
  901. \end_inset
  902. would allow the user to decide on whether to fail the lock acquisition
  903. on a signal.
  904. This allows the caller to choose their own compromise: they could narrow
  905. the race by checking immediately before the fcntl call.
  906. \begin_inset Foot
  907. status collapsed
  908. \begin_layout Plain Layout
  909. It may be possible to make this race-free in some implementations by having
  910. the signal handler alter the struct flock to make it invalid.
  911. This will cause the fcntl() lock call to fail with EINVAL if the signal
  912. occurs before the kernel is entered, otherwise EAGAIN.
  913. \end_layout
  914. \end_inset
  915. \end_layout
  916. \begin_layout Subsubsection
  917. Status
  918. \end_layout
  919. \begin_layout Standard
  920. Complete.
  921. \end_layout
  922. \begin_layout Subsection
  923. The API Uses Gratuitous Typedefs, Capitals
  924. \end_layout
  925. \begin_layout Standard
  926. typedefs are useful for providing source compatibility when types can differ
  927. across implementations, or arguably in the case of function pointer definitions
  928. which are hard for humans to parse.
  929. Otherwise it is simply obfuscation and pollutes the namespace.
  930. \end_layout
  931. \begin_layout Standard
  932. Capitalization is usually reserved for compile-time constants and macros.
  933. \end_layout
  934. \begin_layout Description
  935. TDB_CONTEXT There is no reason to use this over 'struct tdb_context'; the
  936. definition isn't visible to the API user anyway.
  937. \end_layout
  938. \begin_layout Description
  939. TDB_DATA There is no reason to use this over struct TDB_DATA; the struct
  940. needs to be understood by the API user.
  941. \end_layout
  942. \begin_layout Description
  943. struct
  944. \begin_inset space ~
  945. \end_inset
  946. TDB_DATA This would normally be called 'struct tdb_data'.
  947. \end_layout
  948. \begin_layout Description
  949. enum
  950. \begin_inset space ~
  951. \end_inset
  952. TDB_ERROR Similarly, this would normally be enum tdb_error.
  953. \end_layout
  954. \begin_layout Subsubsection
  955. Proposed Solution
  956. \end_layout
  957. \begin_layout Standard
  958. None.
  959. Introducing lower case variants would please pedants like myself, but if
  960. it were done the existing ones should be kept.
  961. There is little point forcing a purely cosmetic change upon tdb users.
  962. \end_layout
  963. \begin_layout Subsection
  964. \begin_inset CommandInset label
  965. LatexCommand label
  966. name "tdb_log_func-Doesnt-Take"
  967. \end_inset
  968. tdb_log_func Doesn't Take The Private Pointer
  969. \end_layout
  970. \begin_layout Standard
  971. For API compatibility reasons, the logging function needs to call tdb_get_loggin
  972. g_private() to retrieve the pointer registered by the tdb_open_ex for logging.
  973. \end_layout
  974. \begin_layout Subsubsection
  975. Proposed Solution
  976. \end_layout
  977. \begin_layout Standard
  978. It should simply take an extra argument, since we are prepared to break
  979. the API/ABI.
  980. \end_layout
  981. \begin_layout Subsubsection
  982. Status
  983. \end_layout
  984. \begin_layout Standard
  985. Complete.
  986. \end_layout
  987. \begin_layout Subsection
  988. Various Callback Functions Are Not Typesafe
  989. \end_layout
  990. \begin_layout Standard
  991. The callback functions in tdb_set_logging_function (after
  992. \begin_inset CommandInset ref
  993. LatexCommand ref
  994. reference "tdb_log_func-Doesnt-Take"
  995. \end_inset
  996. is resolved), tdb_parse_record, tdb_traverse, tdb_traverse_read and tdb_check
  997. all take void * and must internally convert it to the argument type they
  998. were expecting.
  999. \end_layout
  1000. \begin_layout Standard
  1001. If this type changes, the compiler will not produce warnings on the callers,
  1002. since it only sees void *.
  1003. \end_layout
  1004. \begin_layout Subsubsection
  1005. Proposed Solution
  1006. \end_layout
  1007. \begin_layout Standard
  1008. With careful use of macros, we can create callback functions which give
  1009. a warning when used on gcc and the types of the callback and its private
  1010. argument differ.
  1011. Unsupported compilers will not give a warning, which is no worse than now.
  1012. In addition, the callbacks become clearer, as they need not use void *
  1013. for their parameter.
  1014. \end_layout
  1015. \begin_layout Standard
  1016. See CCAN's typesafe_cb module at http://ccan.ozlabs.org/info/typesafe_cb.html
  1017. \end_layout
  1018. \begin_layout Subsubsection
  1019. Status
  1020. \end_layout
  1021. \begin_layout Standard
  1022. Complete.
  1023. \end_layout
  1024. \begin_layout Subsection
  1025. TDB_CLEAR_IF_FIRST Must Be Specified On All Opens, tdb_reopen_all Problematic
  1026. \end_layout
  1027. \begin_layout Standard
  1028. The TDB_CLEAR_IF_FIRST flag to tdb_open indicates that the TDB file should
  1029. be cleared if the caller discovers it is the only process with the TDB
  1030. open.
  1031. However, if any caller does not specify TDB_CLEAR_IF_FIRST it will not
  1032. be detected, so will have the TDB erased underneath them (usually resulting
  1033. in a crash).
  1034. \end_layout
  1035. \begin_layout Standard
  1036. There is a similar issue on fork(); if the parent exits (or otherwise closes
  1037. the tdb) before the child calls tdb_reopen_all() to establish the lock
  1038. used to indicate the TDB is opened by someone, a TDB_CLEAR_IF_FIRST opener
  1039. at that moment will believe it alone has opened the TDB and will erase
  1040. it.
  1041. \end_layout
  1042. \begin_layout Subsubsection
  1043. Proposed Solution
  1044. \end_layout
  1045. \begin_layout Standard
  1046. Remove TDB_CLEAR_IF_FIRST.
  1047. Other workarounds are possible, but see
  1048. \begin_inset CommandInset ref
  1049. LatexCommand ref
  1050. reference "TDB_CLEAR_IF_FIRST-Imposes-Performance"
  1051. \end_inset
  1052. .
  1053. \end_layout
  1054. \begin_layout Subsubsection
  1055. Status
  1056. \end_layout
  1057. \begin_layout Standard
  1058. Complete.
  1059. An open hook is provided to replicate this functionality if required.
  1060. \end_layout
  1061. \begin_layout Subsection
  1062. Extending The Header Is Difficult
  1063. \end_layout
  1064. \begin_layout Standard
  1065. We have reserved (zeroed) words in the TDB header, which can be used for
  1066. future features.
  1067. If the future features are compulsory, the version number must be updated
  1068. to prevent old code from accessing the database.
  1069. But if the future feature is optional, we have no way of telling if older
  1070. code is accessing the database or not.
  1071. \end_layout
  1072. \begin_layout Subsubsection
  1073. Proposed Solution
  1074. \end_layout
  1075. \begin_layout Standard
  1076. The header should contain a
  1077. \begin_inset Quotes eld
  1078. \end_inset
  1079. format variant
  1080. \begin_inset Quotes erd
  1081. \end_inset
  1082. value (64-bit).
  1083. This is divided into two 32-bit parts:
  1084. \end_layout
  1085. \begin_layout Enumerate
  1086. The lower part reflects the format variant understood by code accessing
  1087. the database.
  1088. \end_layout
  1089. \begin_layout Enumerate
  1090. The upper part reflects the format variant you must understand to write
  1091. to the database (otherwise you can only open for reading).
  1092. \end_layout
  1093. \begin_layout Standard
  1094. The latter field can only be written at creation time, the former should
  1095. be written under the OPEN_LOCK when opening the database for writing, if
  1096. the variant of the code is lower than the current lowest variant.
  1097. \end_layout
  1098. \begin_layout Standard
  1099. This should allow backwards-compatible features to be added, and detection
  1100. if older code (which doesn't understand the feature) writes to the database.
  1101. \end_layout
  1102. \begin_layout Subsubsection
  1103. Status
  1104. \end_layout
  1105. \begin_layout Standard
  1106. Complete.
  1107. \end_layout
  1108. \begin_layout Subsection
  1109. Record Headers Are Not Expandible
  1110. \end_layout
  1111. \begin_layout Standard
  1112. If we later want to add (say) checksums on keys and data, it would require
  1113. another format change, which we'd like to avoid.
  1114. \end_layout
  1115. \begin_layout Subsubsection
  1116. Proposed Solution
  1117. \end_layout
  1118. \begin_layout Standard
  1119. We often have extra padding at the tail of a record.
  1120. If we ensure that the first byte (if any) of this padding is zero, we will
  1121. have a way for future changes to detect code which doesn't understand a
  1122. new format: the new code would write (say) a 1 at the tail, and thus if
  1123. there is no tail or the first byte is 0, we would know the extension is
  1124. not present on that record.
  1125. \end_layout
  1126. \begin_layout Subsubsection
  1127. Status
  1128. \end_layout
  1129. \begin_layout Standard
  1130. Complete.
  1131. \end_layout
  1132. \begin_layout Subsection
  1133. TDB Does Not Use Talloc
  1134. \end_layout
  1135. \begin_layout Standard
  1136. Many users of TDB (particularly Samba) use the talloc allocator, and thus
  1137. have to wrap TDB in a talloc context to use it conveniently.
  1138. \end_layout
  1139. \begin_layout Subsubsection
  1140. Proposed Solution
  1141. \end_layout
  1142. \begin_layout Standard
  1143. The allocation within TDB is not complicated enough to justify the use of
  1144. talloc, and I am reluctant to force another (excellent) library on TDB
  1145. users.
  1146. Nonetheless a compromise is possible.
  1147. An attribute (see
  1148. \begin_inset CommandInset ref
  1149. LatexCommand ref
  1150. reference "attributes"
  1151. \end_inset
  1152. ) can be added later to tdb_open() to provide an alternate allocation mechanism,
  1153. specifically for talloc but usable by any other allocator (which would
  1154. ignore the
  1155. \begin_inset Quotes eld
  1156. \end_inset
  1157. context
  1158. \begin_inset Quotes erd
  1159. \end_inset
  1160. argument).
  1161. \end_layout
  1162. \begin_layout Standard
  1163. This would form a talloc heirarchy as expected, but the caller would still
  1164. have to attach a destructor to the tdb context returned from tdb_open to
  1165. close it.
  1166. All TDB_DATA fields would be children of the tdb_context, and the caller
  1167. would still have to manage them (using talloc_free() or talloc_steal()).
  1168. \end_layout
  1169. \begin_layout Subsubsection
  1170. Status
  1171. \end_layout
  1172. \begin_layout Standard
  1173. Complete, using the NTDB_ATTRIBUTE_ALLOCATOR attribute.
  1174. \end_layout
  1175. \begin_layout Section
  1176. Performance And Scalability Issues
  1177. \end_layout
  1178. \begin_layout Subsection
  1179. \begin_inset CommandInset label
  1180. LatexCommand label
  1181. name "TDB_CLEAR_IF_FIRST-Imposes-Performance"
  1182. \end_inset
  1183. TDB_CLEAR_IF_FIRST Imposes Performance Penalty
  1184. \end_layout
  1185. \begin_layout Standard
  1186. When TDB_CLEAR_IF_FIRST is specified, a 1-byte read lock is placed at offset
  1187. 4 (aka.
  1188. the ACTIVE_LOCK).
  1189. While these locks never conflict in normal tdb usage, they do add substantial
  1190. overhead for most fcntl lock implementations when the kernel scans to detect
  1191. if a lock conflict exists.
  1192. This is often a single linked list, making the time to acquire and release
  1193. a fcntl lock O(N) where N is the number of processes with the TDB open,
  1194. not the number actually doing work.
  1195. \end_layout
  1196. \begin_layout Standard
  1197. In a Samba server it is common to have huge numbers of clients sitting idle,
  1198. and thus they have weaned themselves off the TDB_CLEAR_IF_FIRST flag.
  1199. \begin_inset Foot
  1200. status collapsed
  1201. \begin_layout Plain Layout
  1202. There is a flag to tdb_reopen_all() which is used for this optimization:
  1203. if the parent process will outlive the child, the child does not need the
  1204. ACTIVE_LOCK.
  1205. This is a workaround for this very performance issue.
  1206. \end_layout
  1207. \end_inset
  1208. \end_layout
  1209. \begin_layout Subsubsection
  1210. Proposed Solution
  1211. \end_layout
  1212. \begin_layout Standard
  1213. Remove the flag.
  1214. It was a neat idea, but even trivial servers tend to know when they are
  1215. initializing for the first time and can simply unlink the old tdb at that
  1216. point.
  1217. \end_layout
  1218. \begin_layout Subsubsection
  1219. Status
  1220. \end_layout
  1221. \begin_layout Standard
  1222. Complete.
  1223. \end_layout
  1224. \begin_layout Subsection
  1225. TDB Files Have a 4G Limit
  1226. \end_layout
  1227. \begin_layout Standard
  1228. This seems to be becoming an issue (so much for
  1229. \begin_inset Quotes eld
  1230. \end_inset
  1231. trivial
  1232. \begin_inset Quotes erd
  1233. \end_inset
  1234. !), particularly for ldb.
  1235. \end_layout
  1236. \begin_layout Subsubsection
  1237. Proposed Solution
  1238. \end_layout
  1239. \begin_layout Standard
  1240. A new, incompatible TDB format which uses 64 bit offsets internally rather
  1241. than 32 bit as now.
  1242. For simplicity of endian conversion (which TDB does on the fly if required),
  1243. all values will be 64 bit on disk.
  1244. In practice, some upper bits may be used for other purposes, but at least
  1245. 56 bits will be available for file offsets.
  1246. \end_layout
  1247. \begin_layout Standard
  1248. tdb_open() will automatically detect the old version, and even create them
  1249. if TDB_VERSION6 is specified to tdb_open.
  1250. \end_layout
  1251. \begin_layout Standard
  1252. 32 bit processes will still be able to access TDBs larger than 4G (assuming
  1253. that their off_t allows them to seek to 64 bits), they will gracefully
  1254. fall back as they fail to mmap.
  1255. This can happen already with large TDBs.
  1256. \end_layout
  1257. \begin_layout Standard
  1258. Old versions of tdb will fail to open the new TDB files (since 28 August
  1259. 2009, commit 398d0c29290: prior to that any unrecognized file format would
  1260. be erased and initialized as a fresh tdb!)
  1261. \end_layout
  1262. \begin_layout Subsubsection
  1263. Status
  1264. \end_layout
  1265. \begin_layout Standard
  1266. Complete.
  1267. \end_layout
  1268. \begin_layout Subsection
  1269. TDB Records Have a 4G Limit
  1270. \end_layout
  1271. \begin_layout Standard
  1272. This has not been a reported problem, and the API uses size_t which can
  1273. be 64 bit on 64 bit platforms.
  1274. However, other limits may have made such an issue moot.
  1275. \end_layout
  1276. \begin_layout Subsubsection
  1277. Proposed Solution
  1278. \end_layout
  1279. \begin_layout Standard
  1280. Record sizes will be 64 bit, with an error returned on 32 bit platforms
  1281. which try to access such records (the current implementation would return
  1282. TDB_ERR_OOM in a similar case).
  1283. It seems unlikely that 32 bit keys will be a limitation, so the implementation
  1284. may not support this (see
  1285. \begin_inset CommandInset ref
  1286. LatexCommand ref
  1287. reference "sub:Records-Incur-A"
  1288. \end_inset
  1289. ).
  1290. \end_layout
  1291. \begin_layout Subsubsection
  1292. Status
  1293. \end_layout
  1294. \begin_layout Standard
  1295. Complete.
  1296. \end_layout
  1297. \begin_layout Subsection
  1298. Hash Size Is Determined At TDB Creation Time
  1299. \end_layout
  1300. \begin_layout Standard
  1301. TDB contains a number of hash chains in the header; the number is specified
  1302. at creation time, and defaults to 131.
  1303. This is such a bottleneck on large databases (as each hash chain gets quite
  1304. long), that LDB uses 10,000 for this hash.
  1305. In general it is impossible to know what the 'right' answer is at database
  1306. creation time.
  1307. \end_layout
  1308. \begin_layout Subsubsection
  1309. \begin_inset CommandInset label
  1310. LatexCommand label
  1311. name "sub:Hash-Size-Solution"
  1312. \end_inset
  1313. Proposed Solution
  1314. \end_layout
  1315. \begin_layout Standard
  1316. After comprehensive performance testing on various scalable hash variants
  1317. \begin_inset Foot
  1318. status collapsed
  1319. \begin_layout Plain Layout
  1320. http://rusty.ozlabs.org/?p=89 and http://rusty.ozlabs.org/?p=94 This was annoying
  1321. because I was previously convinced that an expanding tree of hashes would
  1322. be very close to optimal.
  1323. \end_layout
  1324. \end_inset
  1325. , it became clear that it is hard to beat a straight linear hash table which
  1326. doubles in size when it reaches saturation.
  1327. Unfortunately, altering the hash table introduces serious locking complications
  1328. : the entire hash table needs to be locked to enlarge the hash table, and
  1329. others might be holding locks.
  1330. Particularly insidious are insertions done under tdb_chainlock.
  1331. \end_layout
  1332. \begin_layout Standard
  1333. Thus an expanding layered hash will be used: an array of hash groups, with
  1334. each hash group exploding into pointers to lower hash groups once it fills,
  1335. turning into a hash tree.
  1336. This has implications for locking: we must lock the entire group in case
  1337. we need to expand it, yet we don't know how deep the tree is at that point.
  1338. \end_layout
  1339. \begin_layout Standard
  1340. Note that bits from the hash table entries should be stolen to hold more
  1341. hash bits to reduce the penalty of collisions.
  1342. We can use the otherwise-unused lower 3 bits.
  1343. If we limit the size of the database to 64 exabytes, we can use the top
  1344. 8 bits of the hash entry as well.
  1345. These 11 bits would reduce false positives down to 1 in 2000 which is more
  1346. than we need: we can use one of the bits to indicate that the extra hash
  1347. bits are valid.
  1348. This means we can choose not to re-hash all entries when we expand a hash
  1349. group; simply use the next bits we need and mark them invalid.
  1350. \end_layout
  1351. \begin_layout Subsubsection
  1352. Status
  1353. \end_layout
  1354. \begin_layout Standard
  1355. Ignore.
  1356. Scaling the hash automatically proved inefficient at small hash sizes;
  1357. we default to a 8192-element hash (changable via NTDB_ATTRIBUTE_HASHSIZE),
  1358. and when buckets clash we expand to an array of hash entries.
  1359. This scales slightly better than the tdb chain (due to the 8 top bits containin
  1360. g extra hash).
  1361. \end_layout
  1362. \begin_layout Subsection
  1363. \begin_inset CommandInset label
  1364. LatexCommand label
  1365. name "TDB-Freelist-Is"
  1366. \end_inset
  1367. TDB Freelist Is Highly Contended
  1368. \end_layout
  1369. \begin_layout Standard
  1370. TDB uses a single linked list for the free list.
  1371. Allocation occurs as follows, using heuristics which have evolved over
  1372. time:
  1373. \end_layout
  1374. \begin_layout Enumerate
  1375. Get the free list lock for this whole operation.
  1376. \end_layout
  1377. \begin_layout Enumerate
  1378. Multiply length by 1.25, so we always over-allocate by 25%.
  1379. \end_layout
  1380. \begin_layout Enumerate
  1381. Set the slack multiplier to 1.
  1382. \end_layout
  1383. \begin_layout Enumerate
  1384. Examine the current freelist entry: if it is > length but < the current
  1385. best case, remember it as the best case.
  1386. \end_layout
  1387. \begin_layout Enumerate
  1388. Multiply the slack multiplier by 1.05.
  1389. \end_layout
  1390. \begin_layout Enumerate
  1391. If our best fit so far is less than length * slack multiplier, return it.
  1392. The slack will be turned into a new free record if it's large enough.
  1393. \end_layout
  1394. \begin_layout Enumerate
  1395. Otherwise, go onto the next freelist entry.
  1396. \end_layout
  1397. \begin_layout Standard
  1398. Deleting a record occurs as follows:
  1399. \end_layout
  1400. \begin_layout Enumerate
  1401. Lock the hash chain for this whole operation.
  1402. \end_layout
  1403. \begin_layout Enumerate
  1404. Walk the chain to find the record, keeping the prev pointer offset.
  1405. \end_layout
  1406. \begin_layout Enumerate
  1407. If max_dead is non-zero:
  1408. \end_layout
  1409. \begin_deeper
  1410. \begin_layout Enumerate
  1411. Walk the hash chain again and count the dead records.
  1412. \end_layout
  1413. \begin_layout Enumerate
  1414. If it's more than max_dead, bulk free all the dead ones (similar to steps
  1415. 4 and below, but the lock is only obtained once).
  1416. \end_layout
  1417. \begin_layout Enumerate
  1418. Simply mark this record as dead and return.
  1419. \end_layout
  1420. \end_deeper
  1421. \begin_layout Enumerate
  1422. Get the free list lock for the remainder of this operation.
  1423. \end_layout
  1424. \begin_layout Enumerate
  1425. \begin_inset CommandInset label
  1426. LatexCommand label
  1427. name "right-merging"
  1428. \end_inset
  1429. Examine the following block to see if it is free; if so, enlarge the current
  1430. block and remove that block from the free list.
  1431. This was disabled, as removal from the free list was O(entries-in-free-list).
  1432. \end_layout
  1433. \begin_layout Enumerate
  1434. Examine the preceeding block to see if it is free: for this reason, each
  1435. block has a 32-bit tailer which indicates its length.
  1436. If it is free, expand it to cover our new block and return.
  1437. \end_layout
  1438. \begin_layout Enumerate
  1439. Otherwise, prepend ourselves to the free list.
  1440. \end_layout
  1441. \begin_layout Standard
  1442. Disabling right-merging (step
  1443. \begin_inset CommandInset ref
  1444. LatexCommand ref
  1445. reference "right-merging"
  1446. \end_inset
  1447. ) causes fragmentation; the other heuristics proved insufficient to address
  1448. this, so the final answer to this was that when we expand the TDB file
  1449. inside a transaction commit, we repack the entire tdb.
  1450. \end_layout
  1451. \begin_layout Standard
  1452. The single list lock limits our allocation rate; due to the other issues
  1453. this is not currently seen as a bottleneck.
  1454. \end_layout
  1455. \begin_layout Subsubsection
  1456. Proposed Solution
  1457. \end_layout
  1458. \begin_layout Standard
  1459. The first step is to remove all the current heuristics, as they obviously
  1460. interact, then examine them once the lock contention is addressed.
  1461. \end_layout
  1462. \begin_layout Standard
  1463. The free list must be split to reduce contention.
  1464. Assuming perfect free merging, we can at most have 1 free list entry for
  1465. each entry.
  1466. This implies that the number of free lists is related to the size of the
  1467. hash table, but as it is rare to walk a large number of free list entries
  1468. we can use far fewer, say 1/32 of the number of hash buckets.
  1469. \end_layout
  1470. \begin_layout Standard
  1471. It seems tempting to try to reuse the hash implementation which we use for
  1472. records here, but we have two ways of searching for free entries: for allocatio
  1473. n we search by size (and possibly zone) which produces too many clashes
  1474. for our hash table to handle well, and for coalescing we search by address.
  1475. Thus an array of doubly-linked free lists seems preferable.
  1476. \end_layout
  1477. \begin_layout Standard
  1478. There are various benefits in using per-size free lists (see
  1479. \begin_inset CommandInset ref
  1480. LatexCommand ref
  1481. reference "sub:TDB-Becomes-Fragmented"
  1482. \end_inset
  1483. ) but it's not clear this would reduce contention in the common case where
  1484. all processes are allocating/freeing the same size.
  1485. Thus we almost certainly need to divide in other ways: the most obvious
  1486. is to divide the file into zones, and using a free list (or table of free
  1487. lists) for each.
  1488. This approximates address ordering.
  1489. \end_layout
  1490. \begin_layout Standard
  1491. Unfortunately it is difficult to know what heuristics should be used to
  1492. determine zone sizes, and our transaction code relies on being able to
  1493. create a
  1494. \begin_inset Quotes eld
  1495. \end_inset
  1496. recovery area
  1497. \begin_inset Quotes erd
  1498. \end_inset
  1499. by simply appending to the file (difficult if it would need to create a
  1500. new zone header).
  1501. Thus we use a linked-list of free tables; currently we only ever create
  1502. one, but if there is more than one we choose one at random to use.
  1503. In future we may use heuristics to add new free tables on contention.
  1504. We only expand the file when all free tables are exhausted.
  1505. \end_layout
  1506. \begin_layout Standard
  1507. The basic algorithm is as follows.
  1508. Freeing is simple:
  1509. \end_layout
  1510. \begin_layout Enumerate
  1511. Identify the correct free list.
  1512. \end_layout
  1513. \begin_layout Enumerate
  1514. Lock the corresponding list.
  1515. \end_layout
  1516. \begin_layout Enumerate
  1517. Re-check the list (we didn't have a lock, sizes could have changed): relock
  1518. if necessary.
  1519. \end_layout
  1520. \begin_layout Enumerate
  1521. Place the freed entry in the list.
  1522. \end_layout
  1523. \begin_layout Standard
  1524. Allocation is a little more complicated, as we perform delayed coalescing
  1525. at this point:
  1526. \end_layout
  1527. \begin_layout Enumerate
  1528. Pick a free table; usually the previous one.
  1529. \end_layout
  1530. \begin_layout Enumerate
  1531. Lock the corresponding list.
  1532. \end_layout
  1533. \begin_layout Enumerate
  1534. If the top entry is -large enough, remove it from the list and return it.
  1535. \end_layout
  1536. \begin_layout Enumerate
  1537. Otherwise, coalesce entries in the list.If there was no entry large enough,
  1538. unlock the list and try the next largest list
  1539. \end_layout
  1540. \begin_layout Enumerate
  1541. If no list has an entry which meets our needs, try the next free table.
  1542. \end_layout
  1543. \begin_layout Enumerate
  1544. If no zone satisfies, expand the file.
  1545. \end_layout
  1546. \begin_layout Standard
  1547. This optimizes rapid insert/delete of free list entries by not coalescing
  1548. them all the time..
  1549. First-fit address ordering ordering seems to be fairly good for keeping
  1550. fragmentation low (see
  1551. \begin_inset CommandInset ref
  1552. LatexCommand ref
  1553. reference "sub:TDB-Becomes-Fragmented"
  1554. \end_inset
  1555. ).
  1556. Note that address ordering does not need a tailer to coalesce, though if
  1557. we needed one we could have one cheaply: see
  1558. \begin_inset CommandInset ref
  1559. LatexCommand ref
  1560. reference "sub:Records-Incur-A"
  1561. \end_inset
  1562. .
  1563. \end_layout
  1564. \begin_layout Standard
  1565. Each free entry has the free table number in the header: less than 255.
  1566. It also contains a doubly-linked list for easy deletion.
  1567. \end_layout
  1568. \begin_layout Subsection
  1569. \begin_inset CommandInset label
  1570. LatexCommand label
  1571. name "sub:TDB-Becomes-Fragmented"
  1572. \end_inset
  1573. TDB Becomes Fragmented
  1574. \end_layout
  1575. \begin_layout Standard
  1576. Much of this is a result of allocation strategy
  1577. \begin_inset Foot
  1578. status collapsed
  1579. \begin_layout Plain Layout
  1580. The Memory Fragmentation Problem: Solved? Johnstone & Wilson 1995 ftp://ftp.cs.ute
  1581. xas.edu/pub/garbage/malloc/ismm98.ps
  1582. \end_layout
  1583. \end_inset
  1584. and deliberate hobbling of coalescing; internal fragmentation (aka overallocati
  1585. on) is deliberately set at 25%, and external fragmentation is only cured
  1586. by the decision to repack the entire db when a transaction commit needs
  1587. to enlarge the file.
  1588. \end_layout
  1589. \begin_layout Subsubsection
  1590. Proposed Solution
  1591. \end_layout
  1592. \begin_layout Standard
  1593. The 25% overhead on allocation works in practice for ldb because indexes
  1594. tend to expand by one record at a time.
  1595. This internal fragmentation can be resolved by having an
  1596. \begin_inset Quotes eld
  1597. \end_inset
  1598. expanded
  1599. \begin_inset Quotes erd
  1600. \end_inset
  1601. bit in the header to note entries that have previously expanded, and allocating
  1602. more space for them.
  1603. \end_layout
  1604. \begin_layout Standard
  1605. There are is a spectrum of possible solutions for external fragmentation:
  1606. one is to use a fragmentation-avoiding allocation strategy such as best-fit
  1607. address-order allocator.
  1608. The other end of the spectrum would be to use a bump allocator (very fast
  1609. and simple) and simply repack the file when we reach the end.
  1610. \end_layout
  1611. \begin_layout Standard
  1612. There are three problems with efficient fragmentation-avoiding allocators:
  1613. they are non-trivial, they tend to use a single free list for each size,
  1614. and there's no evidence that tdb allocation patterns will match those recorded
  1615. for general allocators (though it seems likely).
  1616. \end_layout
  1617. \begin_layout Standard
  1618. Thus we don't spend too much effort on external fragmentation; we will be
  1619. no worse than the current code if we need to repack on occasion.
  1620. More effort is spent on reducing freelist contention, and reducing overhead.
  1621. \end_layout
  1622. \begin_layout Subsection
  1623. \begin_inset CommandInset label
  1624. LatexCommand label
  1625. name "sub:Records-Incur-A"
  1626. \end_inset
  1627. Records Incur A 28-Byte Overhead
  1628. \end_layout
  1629. \begin_layout Standard
  1630. Each TDB record has a header as follows:
  1631. \end_layout
  1632. \begin_layout LyX-Code
  1633. struct tdb_record {
  1634. \end_layout
  1635. \begin_layout LyX-Code
  1636. tdb_off_t next; /* offset of the next record in the list */
  1637. \end_layout
  1638. \begin_layout LyX-Code
  1639. tdb_len_t rec_len; /* total byte length of record */
  1640. \end_layout
  1641. \begin_layout LyX-Code
  1642. tdb_len_t key_len; /* byte length of key */
  1643. \end_layout
  1644. \begin_layout LyX-Code
  1645. tdb_len_t data_len; /* byte length of data */
  1646. \end_layout
  1647. \begin_layout LyX-Code
  1648. uint32_t full_hash; /* the full 32 bit hash of the key */
  1649. \end_layout
  1650. \begin_layout LyX-Code
  1651. uint32_t magic; /* try to catch errors */
  1652. \end_layout
  1653. \begin_layout LyX-Code
  1654. /* the following union is implied:
  1655. \end_layout
  1656. \begin_layout LyX-Code
  1657. union {
  1658. \end_layout
  1659. \begin_layout LyX-Code
  1660. char record[rec_len];
  1661. \end_layout
  1662. \begin_layout LyX-Code
  1663. struct {
  1664. \end_layout
  1665. \begin_layout LyX-Code
  1666. char key[key_len];
  1667. \end_layout
  1668. \begin_layout LyX-Code
  1669. char data[data_len];
  1670. \end_layout
  1671. \begin_layout LyX-Code
  1672. }
  1673. \end_layout
  1674. \begin_layout LyX-Code
  1675. uint32_t totalsize; (tailer)
  1676. \end_layout
  1677. \begin_layout LyX-Code
  1678. }
  1679. \end_layout
  1680. \begin_layout LyX-Code
  1681. */
  1682. \end_layout
  1683. \begin_layout LyX-Code
  1684. };
  1685. \end_layout
  1686. \begin_layout Standard
  1687. Naively, this would double to a 56-byte overhead on a 64 bit implementation.
  1688. \end_layout
  1689. \begin_layout Subsubsection
  1690. Proposed Solution
  1691. \end_layout
  1692. \begin_layout Standard
  1693. We can use various techniques to reduce this for an allocated block:
  1694. \end_layout
  1695. \begin_layout Enumerate
  1696. The 'next' pointer is not required, as we are using a flat hash table.
  1697. \end_layout
  1698. \begin_layout Enumerate
  1699. 'rec_len' can instead be expressed as an addition to key_len and data_len
  1700. (it accounts for wasted or overallocated length in the record).
  1701. Since the record length is always a multiple of 8, we can conveniently
  1702. fit it in 32 bits (representing up to 35 bits).
  1703. \end_layout
  1704. \begin_layout Enumerate
  1705. 'key_len' and 'data_len' can be reduced.
  1706. I'm unwilling to restrict 'data_len' to 32 bits, but instead we can combine
  1707. the two into one 64-bit field and using a 5 bit value which indicates at
  1708. what bit to divide the two.
  1709. Keys are unlikely to scale as fast as data, so I'm assuming a maximum key
  1710. size of 32 bits.
  1711. \end_layout
  1712. \begin_layout Enumerate
  1713. 'full_hash' is used to avoid a memcmp on the
  1714. \begin_inset Quotes eld
  1715. \end_inset
  1716. miss
  1717. \begin_inset Quotes erd
  1718. \end_inset
  1719. case, but this is diminishing returns after a handful of bits (at 10 bits,
  1720. it reduces 99.9% of false memcmp).
  1721. As an aside, as the lower bits are already incorporated in the hash table
  1722. resolution, the upper bits should be used here.
  1723. Note that it's not clear that these bits will be a win, given the extra
  1724. bits in the hash table itself (see
  1725. \begin_inset CommandInset ref
  1726. LatexCommand ref
  1727. reference "sub:Hash-Size-Solution"
  1728. \end_inset
  1729. ).
  1730. \end_layout
  1731. \begin_layout Enumerate
  1732. 'magic' does not need to be enlarged: it currently reflects one of 5 values
  1733. (used, free, dead, recovery, and unused_recovery).
  1734. It is useful for quick sanity checking however, and should not be eliminated.
  1735. \end_layout
  1736. \begin_layout Enumerate
  1737. 'tailer' is only used to coalesce free blocks (so a block to the right can
  1738. find the header to check if this block is free).
  1739. This can be replaced by a single 'free' bit in the header of the following
  1740. block (and the tailer only exists in free blocks).
  1741. \begin_inset Foot
  1742. status collapsed
  1743. \begin_layout Plain Layout
  1744. This technique from Thomas Standish.
  1745. Data Structure Techniques.
  1746. Addison-Wesley, Reading, Massachusetts, 1980.
  1747. \end_layout
  1748. \end_inset
  1749. The current proposed coalescing algorithm doesn't need this, however.
  1750. \end_layout
  1751. \begin_layout Standard
  1752. This produces a 16 byte used header like this:
  1753. \end_layout
  1754. \begin_layout LyX-Code
  1755. struct tdb_used_record {
  1756. \end_layout
  1757. \begin_layout LyX-Code
  1758. uint32_t used_magic : 16,
  1759. \end_layout
  1760. \begin_layout LyX-Code
  1761. \end_layout
  1762. \begin_layout LyX-Code
  1763. key_data_divide: 5,
  1764. \end_layout
  1765. \begin_layout LyX-Code
  1766. top_hash: 11;
  1767. \end_layout
  1768. \begin_layout LyX-Code
  1769. uint32_t extra_octets;
  1770. \end_layout
  1771. \begin_layout LyX-Code
  1772. uint64_t key_and_data_len;
  1773. \end_layout
  1774. \begin_layout LyX-Code
  1775. };
  1776. \end_layout
  1777. \begin_layout Standard
  1778. And a free record like this:
  1779. \end_layout
  1780. \begin_layout LyX-Code
  1781. struct tdb_free_record {
  1782. \end_layout
  1783. \begin_layout LyX-Code
  1784. uint64_t free_magic: 8,
  1785. \end_layout
  1786. \begin_layout LyX-Code
  1787. prev : 56;
  1788. \end_layout
  1789. \begin_layout LyX-Code
  1790. \end_layout
  1791. \begin_layout LyX-Code
  1792. uint64_t free_table: 8,
  1793. \end_layout
  1794. \begin_layout LyX-Code
  1795. total_length : 56
  1796. \end_layout
  1797. \begin_layout LyX-Code
  1798. uint64_t next;;
  1799. \end_layout
  1800. \begin_layout LyX-Code
  1801. };
  1802. \end_layout
  1803. \begin_layout Standard
  1804. Note that by limiting valid offsets to 56 bits, we can pack everything we
  1805. need into 3 64-byte words, meaning our minimum record size is 8 bytes.
  1806. \end_layout
  1807. \begin_layout Subsubsection
  1808. Status
  1809. \end_layout
  1810. \begin_layout Standard
  1811. Complete.
  1812. \end_layout
  1813. \begin_layout Subsection
  1814. Transaction Commit Requires 4 fdatasync
  1815. \end_layout
  1816. \begin_layout Standard
  1817. The current transaction algorithm is:
  1818. \end_layout
  1819. \begin_layout Enumerate
  1820. write_recovery_data();
  1821. \end_layout
  1822. \begin_layout Enumerate
  1823. sync();
  1824. \end_layout
  1825. \begin_layout Enumerate
  1826. write_recovery_header();
  1827. \end_layout
  1828. \begin_layout Enumerate
  1829. sync();
  1830. \end_layout
  1831. \begin_layout Enumerate
  1832. overwrite_with_new_data();
  1833. \end_layout
  1834. \begin_layout Enumerate
  1835. sync();
  1836. \end_layout
  1837. \begin_layout Enumerate
  1838. remove_recovery_header();
  1839. \end_layout
  1840. \begin_layout Enumerate
  1841. sync();
  1842. \end_layout
  1843. \begin_layout Standard
  1844. On current ext3, each sync flushes all data to disk, so the next 3 syncs
  1845. are relatively expensive.
  1846. But this could become a performance bottleneck on other filesystems such
  1847. as ext4.
  1848. \end_layout
  1849. \begin_layout Subsubsection
  1850. Proposed Solution
  1851. \end_layout
  1852. \begin_layout Standard
  1853. Neil Brown points out that this is overzealous, and only one sync is needed:
  1854. \end_layout
  1855. \begin_layout Enumerate
  1856. Bundle the recovery data, a transaction counter and a strong checksum of
  1857. the new data.
  1858. \end_layout
  1859. \begin_layout Enumerate
  1860. Strong checksum that whole bundle.
  1861. \end_layout
  1862. \begin_layout Enumerate
  1863. Store the bundle in the database.
  1864. \end_layout
  1865. \begin_layout Enumerate
  1866. Overwrite the oldest of the two recovery pointers in the header (identified
  1867. using the transaction counter) with the offset of this bundle.
  1868. \end_layout
  1869. \begin_layout Enumerate
  1870. sync.
  1871. \end_layout
  1872. \begin_layout Enumerate
  1873. Write the new data to the file.
  1874. \end_layout
  1875. \begin_layout Standard
  1876. Checking for recovery means identifying the latest bundle with a valid checksum
  1877. and using the new data checksum to ensure that it has been applied.
  1878. This is more expensive than the current check, but need only be done at
  1879. open.
  1880. For running databases, a separate header field can be used to indicate
  1881. a transaction in progress; we need only check for recovery if this is set.
  1882. \end_layout
  1883. \begin_layout Subsubsection
  1884. Status
  1885. \end_layout
  1886. \begin_layout Standard
  1887. Deferred.
  1888. \end_layout
  1889. \begin_layout Subsection
  1890. \begin_inset CommandInset label
  1891. LatexCommand label
  1892. name "sub:TDB-Does-Not"
  1893. \end_inset
  1894. TDB Does Not Have Snapshot Support
  1895. \end_layout
  1896. \begin_layout Subsubsection
  1897. Proposed Solution
  1898. \end_layout
  1899. \begin_layout Standard
  1900. None.
  1901. At some point you say
  1902. \begin_inset Quotes eld
  1903. \end_inset
  1904. use a real database
  1905. \begin_inset Quotes erd
  1906. \end_inset
  1907. (but see
  1908. \begin_inset CommandInset ref
  1909. LatexCommand ref
  1910. reference "replay-attribute"
  1911. \end_inset
  1912. ).
  1913. \end_layout
  1914. \begin_layout Standard
  1915. But as a thought experiment, if we implemented transactions to only overwrite
  1916. free entries (this is tricky: there must not be a header in each entry
  1917. which indicates whether it is free, but use of presence in metadata elsewhere),
  1918. and a pointer to the hash table, we could create an entirely new commit
  1919. without destroying existing data.
  1920. Then it would be easy to implement snapshots in a similar way.
  1921. \end_layout
  1922. \begin_layout Standard
  1923. This would not allow arbitrary changes to the database, such as tdb_repack
  1924. does, and would require more space (since we have to preserve the current
  1925. and future entries at once).
  1926. If we used hash trees rather than one big hash table, we might only have
  1927. to rewrite some sections of the hash, too.
  1928. \end_layout
  1929. \begin_layout Standard
  1930. We could then implement snapshots using a similar method, using multiple
  1931. different hash tables/free tables.
  1932. \end_layout
  1933. \begin_layout Subsubsection
  1934. Status
  1935. \end_layout
  1936. \begin_layout Standard
  1937. Deferred.
  1938. \end_layout
  1939. \begin_layout Subsection
  1940. Transactions Cannot Operate in Parallel
  1941. \end_layout
  1942. \begin_layout Standard
  1943. This would be useless for ldb, as it hits the index records with just about
  1944. every update.
  1945. It would add significant complexity in resolving clashes, and cause the
  1946. all transaction callers to write their code to loop in the case where the
  1947. transactions spuriously failed.
  1948. \end_layout
  1949. \begin_layout Subsubsection
  1950. Proposed Solution
  1951. \end_layout
  1952. \begin_layout Standard
  1953. None (but see
  1954. \begin_inset CommandInset ref
  1955. LatexCommand ref
  1956. reference "replay-attribute"
  1957. \end_inset
  1958. ).
  1959. We could solve a small part of the problem by providing read-only transactions.
  1960. These would allow one write transaction to begin, but it could not commit
  1961. until all r/o transactions are done.
  1962. This would require a new RO_TRANSACTION_LOCK, which would be upgraded on
  1963. commit.
  1964. \end_layout
  1965. \begin_layout Subsubsection
  1966. Status
  1967. \end_layout
  1968. \begin_layout Standard
  1969. Deferred.
  1970. \end_layout
  1971. \begin_layout Subsection
  1972. Default Hash Function Is Suboptimal
  1973. \end_layout
  1974. \begin_layout Standard
  1975. The Knuth-inspired multiplicative hash used by tdb is fairly slow (especially
  1976. if we expand it to 64 bits), and works best when the hash bucket size is
  1977. a prime number (which also means a slow modulus).
  1978. In addition, it is highly predictable which could potentially lead to a
  1979. Denial of Service attack in some TDB uses.
  1980. \end_layout
  1981. \begin_layout Subsubsection
  1982. Proposed Solution
  1983. \end_layout
  1984. \begin_layout Standard
  1985. The Jenkins lookup3 hash
  1986. \begin_inset Foot
  1987. status open
  1988. \begin_layout Plain Layout
  1989. http://burtleburtle.net/bob/c/lookup3.c
  1990. \end_layout
  1991. \end_inset
  1992. is a fast and superbly-mixing hash.
  1993. It's used by the Linux kernel and almost everything else.
  1994. This has the particular properties that it takes an initial seed, and produces
  1995. two 32 bit hash numbers, which we can combine into a 64-bit hash.
  1996. \end_layout
  1997. \begin_layout Standard
  1998. The seed should be created at tdb-creation time from some random source,
  1999. and placed in the header.
  2000. This is far from foolproof, but adds a little bit of protection against
  2001. hash bombing.
  2002. \end_layout
  2003. \begin_layout Subsubsection
  2004. Status
  2005. \end_layout
  2006. \begin_layout Standard
  2007. Complete.
  2008. \end_layout
  2009. \begin_layout Subsection
  2010. \begin_inset CommandInset label
  2011. LatexCommand label
  2012. name "Reliable-Traversal-Adds"
  2013. \end_inset
  2014. Reliable Traversal Adds Complexity
  2015. \end_layout
  2016. \begin_layout Standard
  2017. We lock a record during traversal iteration, and try to grab that lock in
  2018. the delete code.
  2019. If that grab on delete fails, we simply mark it deleted and continue onwards;
  2020. traversal checks for this condition and does the delete when it moves off
  2021. the record.
  2022. \end_layout
  2023. \begin_layout Standard
  2024. If traversal terminates, the dead record may be left indefinitely.
  2025. \end_layout
  2026. \begin_layout Subsubsection
  2027. Proposed Solution
  2028. \end_layout
  2029. \begin_layout Standard
  2030. Remove reliability guarantees; see
  2031. \begin_inset CommandInset ref
  2032. LatexCommand ref
  2033. reference "traverse-Proposed-Solution"
  2034. \end_inset
  2035. .
  2036. \end_layout
  2037. \begin_layout Subsubsection
  2038. Status
  2039. \end_layout
  2040. \begin_layout Standard
  2041. Complete.
  2042. \end_layout
  2043. \begin_layout Subsection
  2044. Fcntl Locking Adds Overhead
  2045. \end_layout
  2046. \begin_layout Standard
  2047. Placing a fcntl lock means a system call, as does removing one.
  2048. This is actually one reason why transactions can be faster (everything
  2049. is locked once at transaction start).
  2050. In the uncontended case, this overhead can theoretically be eliminated.
  2051. \end_layout
  2052. \begin_layout Subsubsection
  2053. Proposed Solution
  2054. \end_layout
  2055. \begin_layout Standard
  2056. None.
  2057. \end_layout
  2058. \begin_layout Standard
  2059. We tried this before with spinlock support, in the early days of TDB, and
  2060. it didn't make much difference except in manufactured benchmarks.
  2061. \end_layout
  2062. \begin_layout Standard
  2063. We could use spinlocks (with futex kernel support under Linux), but it means
  2064. that we lose automatic cleanup when a process dies with a lock.
  2065. There is a method of auto-cleanup under Linux, but it's not supported by
  2066. other operating systems.
  2067. We could reintroduce a clear-if-first-style lock and sweep for dead futexes
  2068. on open, but that wouldn't help the normal case of one concurrent opener
  2069. dying.
  2070. Increasingly elaborate repair schemes could be considered, but they require
  2071. an ABI change (everyone must use them) anyway, so there's no need to do
  2072. this at the same time as everything else.
  2073. \end_layout
  2074. \begin_layout Subsection
  2075. Some Transactions Don't Require Durability
  2076. \end_layout
  2077. \begin_layout Standard
  2078. Volker points out that gencache uses a CLEAR_IF_FIRST tdb for normal (fast)
  2079. usage, and occasionally empties the results into a transactional TDB.
  2080. This kind of usage prioritizes performance over durability: as long as
  2081. we are consistent, data can be lost.
  2082. \end_layout
  2083. \begin_layout Standard
  2084. This would be more neatly implemented inside tdb: a
  2085. \begin_inset Quotes eld
  2086. \end_inset
  2087. soft
  2088. \begin_inset Quotes erd
  2089. \end_inset
  2090. transaction commit (ie.
  2091. syncless) which meant that data may be reverted on a crash.
  2092. \end_layout
  2093. \begin_layout Subsubsection
  2094. Proposed Solution
  2095. \end_layout
  2096. \begin_layout Standard
  2097. None.
  2098. \end_layout
  2099. \begin_layout Standard
  2100. Unfortunately any transaction scheme which overwrites old data requires
  2101. a sync before that overwrite to avoid the possibility of corruption.
  2102. \end_layout
  2103. \begin_layout Standard
  2104. It seems possible to use a scheme similar to that described in
  2105. \begin_inset CommandInset ref
  2106. LatexCommand ref
  2107. reference "sub:TDB-Does-Not"
  2108. \end_inset
  2109. ,where transactions are committed without overwriting existing data, and
  2110. an array of top-level pointers were available in the header.
  2111. If the transaction is
  2112. \begin_inset Quotes eld
  2113. \end_inset
  2114. soft
  2115. \begin_inset Quotes erd
  2116. \end_inset
  2117. then we would not need a sync at all: existing processes would pick up
  2118. the new hash table and free list and work with that.
  2119. \end_layout
  2120. \begin_layout Standard
  2121. At some later point, a sync would allow recovery of the old data into the
  2122. free lists (perhaps when the array of top-level pointers filled).
  2123. On crash, tdb_open() would examine the array of top levels, and apply the
  2124. transactions until it encountered an invalid checksum.
  2125. \end_layout
  2126. \begin_layout Subsection
  2127. Tracing Is Fragile, Replay Is External
  2128. \end_layout
  2129. \begin_layout Standard
  2130. The current TDB has compile-time-enabled tracing code, but it often breaks
  2131. as it is not enabled by default.
  2132. In a similar way, the ctdb code has an external wrapper which does replay
  2133. tracing so it can coordinate cluster-wide transactions.
  2134. \end_layout
  2135. \begin_layout Subsubsection
  2136. Proposed Solution
  2137. \begin_inset CommandInset label
  2138. LatexCommand label
  2139. name "replay-attribute"
  2140. \end_inset
  2141. \end_layout
  2142. \begin_layout Standard
  2143. Tridge points out that an attribute can be later added to tdb_open (see
  2144. \begin_inset CommandInset ref
  2145. LatexCommand ref
  2146. reference "attributes"
  2147. \end_inset
  2148. ) to provide replay/trace hooks, which could become the basis for this and
  2149. future parallel transactions and snapshot support.
  2150. \end_layout
  2151. \begin_layout Subsubsection
  2152. Status
  2153. \end_layout
  2154. \begin_layout Standard
  2155. Deferred.
  2156. \end_layout
  2157. \end_body
  2158. \end_document