func cachedAdj(n Node, dt *Digraph, count bytes_int.MultiMap, cache bytes_bytes.MultiMap) (nodes []lattice.Node, has bool, err error) { if dt.Mode&Caching == 0 { return nil, false, nil } dt.lock.RLock() defer dt.lock.RUnlock() key := n.Label() if has, err := count.Has(key); err != nil { return nil, false, err } else if !has { return nil, false, nil } // errors.Logf("DEBUG", "loading %v", n) err = cache.DoFind(key, func(_, adj []byte) (err error) { // WHY DO WE NEED TO UNLOCK? // We will aquire this lock in the course of LoadEmbList in READ MODE // This is fine to re-aquire in READ // However, if another thread tries to aquire in WRITE before we re-aquire // There will be a waiting WRITE when we try to aquire READ // A waiting WRITE will prevent all READ aquisitions // DEADLOCK. dt.lock.RUnlock() defer dt.lock.RLock() node, err := LoadEmbListNode(dt, adj) if err != nil { return err } if node == nil { errors.Logf("ERROR", "node is nil") panic("node was nil") } nodes = append(nodes, node) return nil }) if err != nil { return nil, false, err } if false { pat, _ := LoadSubgraphPattern(dt, key) errors.Logf("LOAD-DEBUG", "Loaded Cached Adj %v adj %v", pat.Pat, len(nodes)) } return nodes, true, nil }
func count(n Node, compute func() ([]lattice.Node, error), counts bytes_int.MultiMap) (int, error) { if has, err := counts.Has(n.Label()); err != nil { return 0, err } else if !has { nodes, err := compute() if err != nil { return 0, err } return len(nodes), nil } var count int32 err := counts.DoFind(n.Label(), func(_ []byte, c int32) error { count = c return nil }) if err != nil { return 0, err } return int(count), nil }
func cacheAdj(dt *Digraph, count bytes_int.MultiMap, cache bytes_bytes.MultiMap, key []byte, nodes []lattice.Node) (err error) { if dt.Mode&Caching == 0 { return nil } dt.lock.Lock() defer dt.lock.Unlock() if has, err := count.Has(key); err != nil { return err } else if has { return nil } err = count.Add(key, int32(len(nodes))) if err != nil { return err } for _, n := range nodes { err = cache.Add(key, n.Pattern().Label()) if err != nil { return err } } return nil }