Skip to content

Commit

Permalink
Added Locks to each endpoint; Added new busy endpoint; Removed some u…
Browse files Browse the repository at this point in the history
…nused imports
  • Loading branch information
OCopping committed Mar 14, 2022
1 parent a680c05 commit d64191d
Show file tree
Hide file tree
Showing 6 changed files with 94 additions and 83 deletions.
25 changes: 13 additions & 12 deletions webapp/blueprints/meta.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
from fastapi import APIRouter
import h5py
import os
from ..utils import NumpySafeJSONResponse
from ..utils import NumpySafeJSONResponse, LOCK

router = APIRouter()

Expand All @@ -16,20 +16,21 @@ def get_meta(path: str, subpath: str = "/"):
Returns:
template: A rendered Jinja2 HTML template
"""
with LOCK:
try:

path = "/" + path
path = "/" + path

try:
with h5py.File(path, "r", swmr=SWMR_DEFAULT, libver="latest") as file:
if subpath:
meta = NumpySafeJSONResponse(metadata(file[subpath]))
else:
meta = NumpySafeJSONResponse(metadata(file["/"]))
return meta
with h5py.File(path, "r", swmr=SWMR_DEFAULT, libver="latest") as file:
if subpath:
meta = NumpySafeJSONResponse(metadata(file[subpath]))
else:
meta = NumpySafeJSONResponse(metadata(file["/"]))
return meta

except Exception as e:
print(e)
# print(f"File {file} can not be opened yet.")
except Exception as e:
print(e)
# print(f"File {file} can not be opened yet.")


def metadata(node: h5py.HLObject) -> Mapping[str, Any]:
Expand Down
25 changes: 13 additions & 12 deletions webapp/blueprints/search.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
from ast import Num
import time
from fastapi import APIRouter
import h5py
import os
from ..utils import NumpySafeJSONResponse
from ..utils import NumpySafeJSONResponse, LOCK

router = APIRouter()

Expand All @@ -16,19 +16,20 @@ def get_nodes(path: str, subpath: str = "/"):
Returns:
template: A rendered Jinja2 HTML template
"""
path = "/" + path
with LOCK:

try:
path = "/" + path

with h5py.File(path, "r", swmr=SWMR_DEFAULT, libver="latest") as file:
if subpath:
nodes = NumpySafeJSONResponse(search(file[subpath]))
else:
nodes = NumpySafeJSONResponse(search(file["/"]))
return nodes
try:
with h5py.File(path, "r", swmr=SWMR_DEFAULT, libver="latest") as file:
if subpath:
nodes = NumpySafeJSONResponse(search(file[subpath]))
else:
nodes = NumpySafeJSONResponse(search(file["/"]))
return nodes

except:
print(f"File {file} can not be opened yet.")
except:
print(f"File {file} can not be opened yet.")


def search(node):
Expand Down
66 changes: 33 additions & 33 deletions webapp/blueprints/slice.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
import os
import re
from fastapi import APIRouter
from ..utils import safe_json_dump
from ..utils import safe_json_dump, LOCK

router = APIRouter()

Expand All @@ -16,36 +16,36 @@ def get_slice(path: str, subpath: str = "/", slice: str = None):
Returns:
template: A rendered Jinja2 HTML template
"""

path = "/" + path

if slice is not None:
slices = re.search("(\d+):(\d+):(\d+)", slice)
if slice:
slice_start = int(slices[1])
slice_stop = int(slices[2])
slice_step = int(slices[3])
with LOCK:
path = "/" + path

if slice is not None:
slices = re.search("(\d+):(\d+):(\d+)", slice)
if slice:
slice_start = int(slices[1])
slice_stop = int(slices[2])
slice_step = int(slices[3])
else:
print("Defaulting to 'all'.")
slice_start = 0
slice_stop = 0
slice_step = 0
else:
print("Defaulting to 'all'.")
slice_start = 0
slice_stop = 0
slice_step = 0
else:
return "Please enter a valid url, e.g. \
'/slice/<path>?subpath=<subpath>?slice=<slice>'"

try:
with h5py.File(path, "r", swmr=SWMR_DEFAULT, libver="latest") as file:
try:
if subpath and isinstance(file[subpath], h5py.Dataset):
sliced = file[subpath][slice_start:slice_stop:slice_step]
return safe_json_dump(sliced)
else:
# meta = metadata(file["/"])
print("Path not valid or not a dataset.")
# return meta
except Exception as e:
print(e)

except:
print(f"File {file} can not be opened yet.")
return "Please enter a valid url, e.g. \
'/slice/<path>?subpath=<subpath>?slice=<slice>'"

try:
with h5py.File(path, "r", swmr=SWMR_DEFAULT, libver="latest") as file:
try:
if subpath and isinstance(file[subpath], h5py.Dataset):
sliced = file[subpath][slice_start:slice_stop:slice_step]
return safe_json_dump(sliced)
else:
# meta = metadata(file["/"])
print("Path not valid or not a dataset.")
# return meta
except Exception as e:
print(e)

except:
print(f"File {file} can not be opened yet.")
47 changes: 23 additions & 24 deletions webapp/blueprints/tree.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
from collections import defaultdict
import os
from typing import Any, Dict, List, Union
import numpy
import h5py
from fastapi import APIRouter

from webapp.blueprints.meta import metadata
from webapp.utils import NumpySafeJSONResponse
from webapp.utils import NumpySafeJSONResponse, LOCK

SWMR_DEFAULT = bool(int(os.getenv("HDF5_SWMR_DEFAULT", "1")))

Expand All @@ -20,25 +19,25 @@ def show_tree(path: str, subpath: str = "/"):
Returns:
template: A rendered Jinja2 HTML template
"""

path = "/" + path

tr = defaultdict(dict)

def visit_node(addr: Union[str, List[str]], node: h5py.HLObject, tree: Dict[str, Any] = tr) -> None:
if isinstance(addr, str):
return visit_node(addr.split("/"), node)
elif len(addr) > 1:
return visit_node(addr[1:], node, tree[addr[0]]["subnodes"])
else:
tree[addr[0]] = {
"subnodes": defaultdict(dict),
"metadata": metadata(node)
}

try:
with h5py.File(path, "r", swmr=SWMR_DEFAULT, libver="latest") as file:
file.visititems(visit_node)
return NumpySafeJSONResponse(tr)
except Exception as e:
return e
with LOCK:
path = "/" + path

tr = defaultdict(dict)

def visit_node(addr: Union[str, List[str]], node: h5py.HLObject, tree: Dict[str, Any] = tr) -> None:
if isinstance(addr, str):
return visit_node(addr.split("/"), node)
elif len(addr) > 1:
return visit_node(addr[1:], node, tree[addr[0]]["subnodes"])
else:
tree[addr[0]] = {
"subnodes": defaultdict(dict),
"metadata": metadata(node)
}

try:
with h5py.File(path, "r", swmr=SWMR_DEFAULT, libver="latest") as file:
file.visititems(visit_node)
return NumpySafeJSONResponse(tr)
except Exception as e:
return e
11 changes: 9 additions & 2 deletions webapp/main.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import os
from markupsafe import escape
from .utils import LOCK

from fastapi import FastAPI
from fastapi import FastAPI, Response, status

# Setup the app
app = FastAPI(root_path=os.path.abspath(os.path.dirname(__file__)))
Expand All @@ -20,3 +20,10 @@
@app.get("/")
def index():
return {"INFO": "Please provide a path to the HDF5 file, e.g. '/file/<path>'."}


@app.get("/busy")
def busy(response: Response):
if LOCK.locked():
response.status_code = status.HTTP_423_LOCKED
return {"busy": LOCK.locked()}
3 changes: 3 additions & 0 deletions webapp/utils.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
import threading
import sys
from typing import Any
from starlette.responses import JSONResponse

LOCK = threading.Lock()

def safe_json_dump(content):
"""
Try to use native orjson path; fall back to going through Python list.
Expand Down

0 comments on commit d64191d

Please sign in to comment.