func tagHasPermission(tag string, uuidBytes uuid.UUID, uuidString string) bool { var hasPerm bool uuidarr := uuidBytes.Array() permcacheLock.Lock() taginfo, ok := permcache[tag] if !ok { /* Cache Miss: never seen this token */ taginfo = &TagInfo{name: tag, permissions: make(map[uuid.Array]bool)} lruListLock.Lock() taginfo.element = lruList.PushFront(taginfo) lruListLock.Unlock() permcache[tag] = taginfo } else { lruListLock.Lock() lruList.MoveToFront(taginfo.element) // most recently used lruListLock.Unlock() hasPerm, ok = taginfo.permissions[uuidBytes.Array()] if ok { /* Cache Hit */ permcacheLock.Unlock() return hasPerm } /* Cache Miss: never seen this UUID */ } permcacheLock.Unlock() /* Ask the metadata server for the metadata of the corresponding stream. */ query := fmt.Sprintf("select * where uuid = \"%s\";", uuidString) mdReq, err := http.NewRequest("POST", fmt.Sprintf("%s?tags=%s", mdServer, tag), strings.NewReader(query)) if err != nil { return false } mdReq.Header.Set("Content-Type", "text") mdReq.Header.Set("Content-Length", fmt.Sprintf("%v", len(query))) resp, err := http.DefaultClient.Do(mdReq) if err != nil { return false } /* If the response is [] we lack permission; if it's longer we have permission. */ buf := make([]byte, 3) n, err := io.ReadFull(resp.Body, buf) resp.Body.Close() if n == 3 && buf[0] == '[' { hasPerm = true } else if n == 2 && err == io.ErrUnexpectedEOF && buf[0] == '[' && buf[1] == ']' { hasPerm = false } else { /* Server error. */ fmt.Printf("Metadata server error: %v %c %c %c\n", n, buf[0], buf[1], buf[2]) return false } /* If we didn't return early due to some kind of error, cache the result and return it. */ permcacheLock.Lock() if taginfo.element != nil { // If this has been evicted from the cache, don't bother _, ok := taginfo.permissions[uuidarr] taginfo.permissions[uuidarr] = hasPerm // still update cached value if !ok { // If a different goroutine added it before we got here, then skip this part totalCached += 1 if totalCached > MAX_CACHED { // Make this access return quickly, so start pruning in a new goroutine fmt.Println("Pruning cache") go pruneCache() } } } permcacheLock.Unlock() return hasPerm }