123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220openPrintfmoduleHt=Hashtbltypefilename=stringtypeposition={off:int;len:int}typedb={data_fn:filename;index_fn:filename;data:Unix.file_descr;index:(string,position)Ht.t}moduleInternal=structletcreatefn=letdata_fn=fninletindex_fn=fn^".idx"inletdata=Unix.(openfiledata_fn[O_RDWR;O_CREAT;O_EXCL]0o600)in(* we just check there is not already an index file *)letindex_file=Unix.(openfileindex_fn[O_RDWR;O_CREAT;O_EXCL]0o600)inUnix.closeindex_file;letindex=Ht.create11in{data_fn;index_fn;data;index}letopen_rwfn=letdata_fn=fninletindex_fn=fn^".idx"inletdata=Unix.(openfiledata_fn[O_RDWR]0o600)inletindex=Utls.restoreindex_fnin{data_fn;index_fn;data;index}letopen_rofn=letdata_fn=fninletindex_fn=fn^".idx"inletdata=Unix.(openfiledata_fn[O_RDONLY]0o600)inletindex=Utls.restoreindex_fnin{data_fn;index_fn;data;index}letdummy()={data_fn="/dev/null";index_fn="/dev/null.idx";data=Unix.(openfile"/dev/null"[O_RDWR]0o600);index=Ht.create0}letclose_simpledb=Unix.closedb.dataletclose_sync_indexdb=Unix.closedb.data;Utls.savedb.index_fndb.indexletsyncdb=ExtUnix.All.fsyncdb.data;Utls.savedb.index_fndb.indexletdestroydb=Ht.resetdb.index;Unix.closedb.data;Sys.removedb.data_fn;Sys.removedb.index_fnletmemdbk=Ht.memdb.indexkletadddbkstr=(* go to end of data file *)letoff=Unix.(lseekdb.data0SEEK_END)inletlen=String.lengthstrinletwritten=Unix.write_substringdb.datastr0leninbeginifwritten<>lenthenleterr_msg=sprintf"Db.Internal.add: db: %s k: %s str: %s written: %d len: %d"db.data_fnkstrwrittenleninfailwitherr_msgend;Ht.adddb.indexk{off;len}letreplacedbkstr=(* go to end of data file *)letoff=Unix.(lseekdb.data0SEEK_END)inletlen=String.lengthstrinletwritten=Unix.write_substringdb.datastr0leninbeginifwritten<>lenthenleterr_msg=sprintf"Db.Internal.replace: db: %s k: %s str: %s written: %d len: %d"db.data_fnkstrwrittenleninfailwitherr_msgend;Ht.replacedb.indexk{off;len}letremovedbk=(* we just remove it from the index, not from the data file *)Ht.removedb.indexkletraw_readdbpos=letoff=pos.offinletlen=pos.leninletbuff=Bytes.createleninletoff'=Unix.(lseekdb.dataoffSEEK_SET)inbeginifoff'<>offthenleterr_msg=sprintf"Db.Internal.raw_read: db: %s off: %d len: %d off': %d"db.data_fnofflenoff'infailwitherr_msgend;letread=Unix.readdb.databuff0leninbeginifread<>lenthenleterr_msg=sprintf"Db.Internal.raw_read: db: %s off: %d len: %d read: %d"db.data_fnofflenreadinfailwitherr_msgend;Bytes.unsafe_to_stringbuffletfinddbk=letv_addr=Ht.finddb.indexkinraw_readdbv_addrletiterfdb=Ht.iter(funkv->fk(raw_readdbv))db.indexletfoldfdbinit=Ht.fold(funkvacc->fk(raw_readdbv)acc)db.indexinitendmoduleRO=structtypet=dbletopen_existingfn=Internal.open_rofnletdummy()=Internal.dummy()letclosedb=Internal.close_simpledbletmemdbk=Internal.memdbkletfinddbk=Internal.finddbkletraw_readdbpos=Internal.raw_readdbposletiterfdb=Internal.iterfdbletfoldfdbinit=Internal.foldfdbinitendmoduleRW=structtypet=dbletcreatefn=Internal.createfnletopen_existingfn=Internal.open_rwfnletdummy()=Internal.dummy()letclosedb=Internal.close_sync_indexdbletsyncdb=Internal.syncdbletdestroydb=Internal.destroydbletmemdbk=Internal.memdbkletadddbkstr=Internal.adddbkstrletreplacedbkstr=Internal.replacedbkstrletremovedbk=Internal.removedbkletfinddbk=Internal.finddbkletraw_readdbpos=Internal.raw_readdbposletiterfdb=Internal.iterfdbletfoldfdbinit=Internal.foldfdbinitend