1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889(*
* Copyright (c) 2011-2015 Anil Madhavapeddy <anil@recoil.org>
* Copyright (c) 2013-2015 Thomas Gazagnaire <thomas@gazagnaire.org>
* Copyright (c) 2013 Citrix Systems Inc
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*)moduleKey=structtypet=stringlist(* Store the path as a reverse list to optimise basename and (/)
operations *)leterr_invalid_segmentx=Fmt.failwith"%S is not a valid segment"xletcheck_segmentx=String.iter(function'/'->err_invalid_segmentx|_->())x;xletempty=[]letvs=List.filter((<>)"")@@List.rev(String.split_on_char'/'s)letaddtv=(check_segmentv)::tlet(/)=addletappendxy=y@xlet(//)=appendletsegments=List.revletbasename=function|[]->""|hd::_->hdletparent=function|_::tl->tl|[]->[]letcompare=compareletequal=(=)letppppfl=Fmt.pfppf"/%a"Fmt.(list~sep:(any"/")string)(List.revl)letto_string=Fmt.to_to_stringppendtypekey=Key.ttypeerror=[|`Not_foundofkey|`Dictionary_expectedofkey|`Value_expectedofkey]letpp_errorppf=function|`Not_foundk->Fmt.pfppf"Cannot find the key %a"Key.ppk|`Dictionary_expectedk->Fmt.pfppf"Expecting a dictionary for the key %a"Key.ppk|`Value_expectedk->Fmt.pfppf"Expecting a value for the key %a"Key.ppkmoduletypeRO=sigtypenonrecerror=private[>error]valpp_error:errorFmt.ttypetvaldisconnect:t->unitLwt.ttypekey=Key.tvalexists:t->key->([`Value|`Dictionary]option,error)resultLwt.tvalget:t->key->(string,error)resultLwt.tvallist:t->key->((string*[`Value|`Dictionary])list,error)resultLwt.tvallast_modified:t->key->(int*int64,error)resultLwt.tvaldigest:t->key->(string,error)resultLwt.tendtypewrite_error=[error|`No_space|`Too_many_retriesofint]letpp_write_errorppf=function|#errorase->pp_errorppfe|`No_space->Fmt.pfppf"No space left on device"|`Too_many_retriesn->Fmt.pfppf"Aborting after %d attempts to apply the batch operations."nmoduletypeRW=sigincludeROtypenonrecwrite_error=private[>write_error]valpp_write_error:write_errorFmt.tvalset:t->key->string->(unit,write_error)resultLwt.tvalremove:t->key->(unit,write_error)resultLwt.tvalbatch:t->?retries:int->(t->'aLwt.t)->'aLwt.tend