github.com/janelia-flyem/dvid@v1.0.0/datatype/neuronjson/schema.go (about)

     1  package neuronjson
     2  
     3  import (
     4  	"fmt"
     5  
     6  	"github.com/janelia-flyem/dvid/datastore"
     7  	"github.com/janelia-flyem/dvid/dvid"
     8  	"github.com/janelia-flyem/dvid/storage"
     9  	"github.com/santhosh-tekuri/jsonschema/v5"
    10  )
    11  
    12  // Metadata key-value support (all non-neuron annotations)
    13  
    14  // load metadata from storage
    15  func (d *Data) loadMetadata(ctx storage.VersionedCtx, meta Schema) (val []byte, err error) {
    16  	var tkey storage.TKey
    17  	if tkey, err = getMetadataKey(meta); err != nil {
    18  		return
    19  	}
    20  	var db storage.KeyValueDB
    21  	if db, err = datastore.GetKeyValueDB(d); err != nil {
    22  		return
    23  	}
    24  	var byteVal []byte
    25  	if byteVal, err = db.Get(ctx, tkey); err != nil {
    26  		return
    27  	}
    28  	return byteVal, nil
    29  }
    30  
    31  // gets metadata from either in-memory db if HEAD or from store
    32  func (d *Data) getMetadata(ctx storage.VersionedCtx, meta Schema) (val []byte, err error) {
    33  	if ctx.Head() {
    34  		d.metadataMu.RLock()
    35  		defer d.metadataMu.RUnlock()
    36  		if val, found := d.metadata[meta]; found {
    37  			return val, nil
    38  		} else {
    39  			return nil, nil
    40  		}
    41  	}
    42  	return d.loadMetadata(ctx, meta)
    43  }
    44  
    45  // get fully compiled JSON schema for use -- TODO
    46  func (d *Data) getJSONSchema(ctx storage.VersionedCtx) (sch *jsonschema.Schema, err error) {
    47  	if ctx.Head() {
    48  		d.metadataMu.RLock()
    49  		sch = d.compiledSchema
    50  		d.metadataMu.RUnlock()
    51  		if sch != nil {
    52  			return
    53  		}
    54  	}
    55  
    56  	var tkey storage.TKey
    57  	if tkey, err = getMetadataKey(JSONSchema); err != nil {
    58  		return
    59  	}
    60  	var db storage.KeyValueDB
    61  	if db, err = datastore.GetKeyValueDB(d); err != nil {
    62  		return
    63  	}
    64  	var byteVal []byte
    65  	if byteVal, err = db.Get(ctx, tkey); err != nil {
    66  		return
    67  	}
    68  	if len(byteVal) == 0 {
    69  		return nil, fmt.Errorf("no JSON Schema available")
    70  	}
    71  	if ctx.Head() {
    72  		d.metadataMu.RLock()
    73  		d.metadata[JSONSchema] = byteVal
    74  		d.metadataMu.RUnlock()
    75  	}
    76  
    77  	sch, err = jsonschema.CompileString("schema.json", string(byteVal))
    78  	if err != nil {
    79  		return
    80  	}
    81  	if sch == nil {
    82  		return nil, fmt.Errorf("no JSON Schema available")
    83  	}
    84  	return
    85  }
    86  
    87  func (d *Data) putMetadata(ctx storage.VersionedCtx, val []byte, meta Schema) (err error) {
    88  	var tkey storage.TKey
    89  	if tkey, err = getMetadataKey(meta); err != nil {
    90  		return
    91  	}
    92  	var db storage.KeyValueDB
    93  	if db, err = datastore.GetKeyValueDB(d); err != nil {
    94  		return
    95  	}
    96  	if err = db.Put(ctx, tkey, val); err != nil {
    97  		return
    98  	}
    99  
   100  	// If we could persist metadata, add it to in-memory db if head.
   101  	if ctx.Head() {
   102  		d.metadataMu.Lock()
   103  		d.metadata[meta] = val
   104  		if meta == JSONSchema {
   105  			d.compiledSchema, err = jsonschema.CompileString("schema.json", string(val))
   106  			if err != nil {
   107  				d.compiledSchema = nil
   108  				dvid.Errorf("Unable to compile json schema: %v\n", err)
   109  			}
   110  		}
   111  		d.metadataMu.Unlock()
   112  	}
   113  	return nil
   114  }
   115  
   116  func (d *Data) metadataExists(ctx storage.VersionedCtx, meta Schema) (exists bool, err error) {
   117  	if ctx.Head() {
   118  		d.metadataMu.RLock()
   119  		defer d.metadataMu.RUnlock()
   120  		_, found := d.metadata[meta]
   121  		return found, nil
   122  	}
   123  	var tkey storage.TKey
   124  	if tkey, err = getMetadataKey(meta); err != nil {
   125  		return
   126  	}
   127  	var db storage.KeyValueDB
   128  	if db, err = datastore.GetKeyValueDB(d); err != nil {
   129  		return
   130  	}
   131  	return db.Exists(ctx, tkey)
   132  }
   133  
   134  func (d *Data) deleteMetadata(ctx storage.VersionedCtx, meta Schema) (err error) {
   135  	var tkey storage.TKey
   136  	if tkey, err = getMetadataKey(meta); err != nil {
   137  		return
   138  	}
   139  	var db storage.KeyValueDB
   140  	if db, err = datastore.GetKeyValueDB(d); err != nil {
   141  		return
   142  	}
   143  	if err = db.Delete(ctx, tkey); err != nil {
   144  		return
   145  	}
   146  	if ctx.Head() {
   147  		d.metadataMu.Lock()
   148  		defer d.metadataMu.Unlock()
   149  		delete(d.metadata, meta)
   150  	}
   151  	return nil
   152  }