getEntries consults the cache and either retrieves the contents of directory listing from the cache or invokes the provides callback and adds the results to cache.
(ctx context.Context, id string, expirationTime time.Duration, cb Loader, w EntryWrapper)
| 141 | // getEntries consults the cache and either retrieves the contents of directory listing from the cache |
| 142 | // or invokes the provides callback and adds the results to cache. |
| 143 | func (c *Cache) getEntries(ctx context.Context, id string, expirationTime time.Duration, cb Loader, w EntryWrapper) ([]fs.Entry, error) { |
| 144 | if c == nil { |
| 145 | return cb(ctx) |
| 146 | } |
| 147 | |
| 148 | c.mu.Lock() |
| 149 | defer c.mu.Unlock() |
| 150 | |
| 151 | if entries := c.getEntriesFromCacheLocked(ctx, id); entries != nil { |
| 152 | return entries, nil |
| 153 | } |
| 154 | |
| 155 | if c.debug { |
| 156 | log(ctx).Debugf("cache miss for %q", id) |
| 157 | } |
| 158 | |
| 159 | raw, err := cb(ctx) |
| 160 | if err != nil { |
| 161 | return nil, err |
| 162 | } |
| 163 | |
| 164 | wrapped := make([]fs.Entry, len(raw)) |
| 165 | for i, entry := range raw { |
| 166 | wrapped[i] = w(entry) |
| 167 | } |
| 168 | |
| 169 | if len(wrapped) > c.maxDirectoryEntries { |
| 170 | // no point caching since it would not fit anyway, just return it. |
| 171 | return wrapped, nil |
| 172 | } |
| 173 | |
| 174 | entry := &cacheEntry{ |
| 175 | id: id, |
| 176 | entries: wrapped, |
| 177 | expireAfter: clock.Now().Add(expirationTime), |
| 178 | } |
| 179 | |
| 180 | c.addToHead(entry) |
| 181 | c.data[id] = entry |
| 182 | |
| 183 | c.totalDirectoryEntries += len(wrapped) |
| 184 | for c.totalDirectoryEntries > c.maxDirectoryEntries || len(c.data) > c.maxDirectories { |
| 185 | c.removeEntryLocked(c.tail) |
| 186 | } |
| 187 | |
| 188 | return raw, nil |
| 189 | } |
| 190 | |
| 191 | func (c *Cache) removeEntryLocked(toremove *cacheEntry) { |
| 192 | c.remove(toremove) |