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

     1  /*
     2  	This file supports keyspaces for the labelsz data type.
     3  */
     4  
     5  package labelsz
     6  
     7  import (
     8  	"encoding/binary"
     9  	"fmt"
    10  	"math"
    11  
    12  	"github.com/janelia-flyem/dvid/datastore"
    13  	"github.com/janelia-flyem/dvid/datatype/annotation"
    14  	"github.com/janelia-flyem/dvid/storage"
    15  )
    16  
    17  const (
    18  	// keyUnknown should never be used and is a check for corrupt or incorrectly set keys
    19  	keyUnknown storage.TKeyClass = iota
    20  
    21  	// reserved type-specific key for metadata
    22  	keyProperties = datastore.PropertyTKeyClass
    23  
    24  	// key is index type + size + label
    25  	keyTypeSizeLabel = 97
    26  
    27  	// key is index type + label, with value equal to size, necessary to delete old indices.
    28  	keyTypeLabel = 98
    29  )
    30  
    31  // DescribeTKeyClass returns a string explanation of what a particular TKeyClass
    32  // is used for.  Implements the datastore.TKeyClassDescriber interface.
    33  func (d *Data) DescribeTKeyClass(tkc storage.TKeyClass) string {
    34  	switch tkc {
    35  	case keyTypeLabel:
    36  		return "labelsz index type + label key"
    37  	case keyTypeSizeLabel:
    38  		return "labelsz index type + size + label key"
    39  	default:
    40  	}
    41  	return "unknown labelsz key"
    42  }
    43  
    44  const (
    45  	UnknownIndex IndexType = iota
    46  	PostSyn                // Post-synaptic element
    47  	PreSyn                 // Pre-synaptic element
    48  	Gap                    // Gap junction
    49  	Note                   // A note or bookmark with some description
    50  	AllSyn                 // PostSyn, PreSyn, or Gap
    51  	Voxels                 // Number of voxels
    52  )
    53  
    54  // IndexType gives the type of index.
    55  type IndexType uint8
    56  
    57  func (i IndexType) String() string {
    58  	switch i {
    59  	case PostSyn:
    60  		return "PostSyn"
    61  	case PreSyn:
    62  		return "PreSyn"
    63  	case Gap:
    64  		return "Gap"
    65  	case Note:
    66  		return "Note"
    67  	case AllSyn:
    68  		return "AllSyn"
    69  	case Voxels:
    70  		return "Voxels"
    71  	default:
    72  		return "Unknown IndexType"
    73  	}
    74  }
    75  
    76  // StringToIndexType converts a string to an IndexType
    77  func StringToIndexType(s string) IndexType {
    78  	switch s {
    79  	case "PostSyn":
    80  		return PostSyn
    81  	case "PreSyn":
    82  		return PreSyn
    83  	case "Gap":
    84  		return Gap
    85  	case "Note":
    86  		return Note
    87  	case "AllSyn":
    88  		return AllSyn
    89  	case "Voxels":
    90  		return Voxels
    91  	default:
    92  		return UnknownIndex
    93  	}
    94  }
    95  
    96  func elementToIndexType(e annotation.ElementType) (i IndexType) {
    97  	switch e {
    98  	case annotation.PostSyn:
    99  		i = PostSyn
   100  	case annotation.PreSyn:
   101  		i = PreSyn
   102  	case annotation.Gap:
   103  		i = Gap
   104  	case annotation.Note:
   105  		i = Note
   106  	default:
   107  		i = UnknownIndex
   108  	}
   109  	return
   110  }
   111  
   112  // can be used as map index and holds serialized (IndexType, Label)
   113  type indexedLabel string
   114  
   115  func (il indexedLabel) String() string {
   116  	i := IndexType(il[0])
   117  	labelBytes := []byte(il[1:])
   118  	label := binary.BigEndian.Uint64(labelBytes)
   119  	return fmt.Sprintf("[label %d, index %s]", label, i.String())
   120  }
   121  
   122  func toIndexedLabel(e annotation.ElementPos) indexedLabel {
   123  	return newIndexedLabel(elementToIndexType(e.Kind), e.Label)
   124  }
   125  
   126  func newIndexedLabel(i IndexType, label uint64) indexedLabel {
   127  	buf := make([]byte, 9)
   128  	buf[0] = byte(i)
   129  	binary.BigEndian.PutUint64(buf[1:], label)
   130  	return indexedLabel(buf)
   131  }
   132  
   133  func decodeIndexedLabel(il indexedLabel) (i IndexType, label uint64, err error) {
   134  	if len(il) != 9 {
   135  		err = fmt.Errorf("indexed label %v is supposed to be 9 bytes but is %d bytes", il, len(il))
   136  		return
   137  	}
   138  	i = IndexType(il[0])
   139  	labelBytes := []byte(il[1:])
   140  	label = binary.BigEndian.Uint64(labelBytes)
   141  	return
   142  }
   143  
   144  // NewTypeSizeLabelTKey returns a type-specific key for the (index type, size, label) tuple.
   145  func NewTypeSizeLabelTKey(i IndexType, sz uint32, label uint64) storage.TKey {
   146  	// Since we want biggest -> smallest sort and initially only have forward range queries,
   147  	// modify size to make smallest <-> largest.
   148  	rsz := math.MaxUint32 - sz
   149  
   150  	buf := make([]byte, 8+1+4)
   151  	buf[0] = byte(i)
   152  	binary.BigEndian.PutUint32(buf[1:5], rsz)
   153  	binary.BigEndian.PutUint64(buf[5:], label)
   154  	return storage.NewTKey(keyTypeSizeLabel, buf)
   155  }
   156  
   157  // DecodeTypeSizeLabelTKey decodes a type-specific key into a (index type, size, label) tuple.
   158  func DecodeTypeSizeLabelTKey(tk storage.TKey) (i IndexType, sz uint32, label uint64, err error) {
   159  	var ibytes []byte
   160  	ibytes, err = tk.ClassBytes(keyTypeSizeLabel)
   161  	if err != nil {
   162  		return
   163  	}
   164  	if len(ibytes) != 13 {
   165  		err = fmt.Errorf("labelsz element size type-specific key is wrong size: expected 13, got %d bytes", len(ibytes))
   166  		return
   167  	}
   168  	i = IndexType(ibytes[0])
   169  	sz = math.MaxUint32 - binary.BigEndian.Uint32(ibytes[1:5])
   170  	label = binary.BigEndian.Uint64(ibytes[5:])
   171  	return
   172  }
   173  
   174  // NewTypeLabelTKey returns a type-specific key for the (index type, label) tuple.
   175  func NewTypeLabelTKey(i IndexType, label uint64) storage.TKey {
   176  	buf := make([]byte, 1+8)
   177  	buf[0] = byte(i)
   178  	binary.BigEndian.PutUint64(buf[1:], label)
   179  	return storage.NewTKey(keyTypeLabel, buf)
   180  }
   181  
   182  // DecodeTypeLabelTKey decodes a type-specific key into a (index type, label) tuple.
   183  func DecodeTypeLabelTKey(tk storage.TKey) (i IndexType, label uint64, err error) {
   184  	var ibytes []byte
   185  	ibytes, err = tk.ClassBytes(keyTypeLabel)
   186  	if err != nil {
   187  		return
   188  	}
   189  	if len(ibytes) != 9 {
   190  		err = fmt.Errorf("labelsz label size type-specific key is wrong size: expected 9, got %d bytes", len(ibytes))
   191  		return
   192  	}
   193  	i = IndexType(ibytes[0])
   194  	label = binary.BigEndian.Uint64(ibytes[1:])
   195  	return
   196  }