# manage the files on one host
resource DirServer
  import Defs, Utilities, FileServer
  op fcreate(name user, name fname, accessmode m) returns file_descriptor  fd
  op fopen(name user, name fname, accessmode m) returns file_descriptor  fd
  op fremove(name user, name fname) returns bool  result
  op check(name user) returns bool  valid
  op list(name user, res name files[FILES]) returns int  cnt
body DirServer()

  name  accounts[USERS]
  name  files[USERS,FILES]
  int  nfiles[USERS]

  # read in names of users and their files
  file f = open("dfs/Accounts", READ)
  int nusers = 0
  while (read(f, accounts[nusers+1]) != EOF) { nusers++ }
  for [ u = 1 to nusers ] {
    file f = open("dfs/" || accounts[u] || "/Files", READ)
    if (f == null) { nfiles[u] = 0; next }  # no files
    int j = 1
    while (read(f, files[u,j]) != EOF) { j++ }
    nfiles[u] = j-1
  }

  proc check(user) returns valid  {
    valid = true
    if (lookup(user, accounts) == 0) { valid = false }
  }

  proc list(user, fls) returns cnt  {
    int u = lookup(user, accounts)
    fls = files[u]; cnt = nfiles[u]
  }

  process ds  {
    while (true) {
      in fcreate(user, fname, m) returns fd ->
	  # look up user's index in accounts
	  int u = lookup(user, accounts)
	  # see if file exists; if not, add it to database
	  int f = lookup(fname, files[u,*])
	  if (f == 0) { nfiles[u]++
		      files[u, nfiles[u]] = fname
	  }
	  # create file server and forward open to it
	  cap FileServer fscap = create FileServer()
	  forward fscap.fopen(user, fname, WRITE)
      [] fopen(user, fname, m) returns fd ->
	  # create file server and forward open to it
	  cap FileServer fscap = create FileServer()
	  forward fscap.fopen(user, fname, m)
      [] fremove(user, fname) returns result ->
	  # look up user's index in accounts
	  int u = lookup(user, accounts)
	  # look up file name in database of files
	  int f = lookup(fname, files[u,*])
	  if (f == 0) { result = false; exit }
	  # remove file name from database
	  files[u,f] = files[u,nfiles[u]]
	  nfiles[u]--; result = true
      ni
    }
  }

  final {
    for [ i = 1 to nusers ] {
      file f = open("dfs/" || accounts[i] || "/Files", WRITE)
      for [ j = 1 to nfiles[i] ] {
	write(f, files[i,j])
      }
    }
  }
end DirServer
