code: func (s *Store) kvsListTxn(tx *memdb.Txn, ws memdb.WatchSet, prefix string) (uint64, structs.DirEntries, error) {
  	// Get the table indexes.
  	idx := maxIndexTxn(tx, "kvs", "tombstones")
  
  	// Query the prefix and list the available keys
  	entries, err := tx.Get("kvs", "id_prefix", prefix)
  	if err != nil {
  		return 0, nil, fmt.Errorf("failed kvs lookup: %s", err)
  	}
  	ws.Add(entries.WatchCh())
  
  	// Gather all of the keys found in the store
  	var ents structs.DirEntries
  	var lindex uint64
  	for entry := entries.Next(); entry != nil; entry = entries.Next() {
  		e := entry.(*structs.DirEntry)
  		ents = append(ents, e)
  		if e.ModifyIndex > lindex {
  			lindex = e.ModifyIndex
  		}
  	}
  
  	// Check for the highest index in the graveyard. If the prefix is empty
  	// then just use the full table indexes since we are listing everything.
  	if prefix != "" {
  		gindex, err := s.kvsGraveyard.GetMaxIndexTxn(tx, prefix)
  		if err != nil {
  			return 0, nil, fmt.Errorf("failed graveyard lookup: %s", err)
  		}
  		if gindex > lindex {
  			lindex = gindex
  		}
  	} else {
  		lindex = idx
  	}
  
  	// Use the sub index if it was set and there are entries, otherwise use
  	// the full table index from above.
  	if lindex != 0 {
  		idx = lindex
  	}
  	return idx, ents, nil
  }
docs: // kvsListTxn is the inner method that gets a list of KVS entries matching a
  // prefix.