-
Notifications
You must be signed in to change notification settings - Fork 7
/
ILdapCache.cs
177 lines (156 loc) · 7.71 KB
/
ILdapCache.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
// <copyright file="ILdapCache.cs" company="Visualisierungsinstitut der Universität Stuttgart">
// Copyright © 2024 Visualisierungsinstitut der Universität Stuttgart.
// Licensed under the MIT licence. See LICENCE file for details.
// </copyright>
// <author>Christoph Müller</author>
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Threading.Tasks;
namespace Visus.Ldap {
/// <summary>
/// The interface of a caching service that allows the library to hold
/// raw LDAP entries in memory for reuse without querying the LDAP server
/// every time.
/// </summary>
/// <typeparam name="TEntry">The type of raw LDAP entries cached by the
/// service.</typeparam>
public interface ILdapCache<TEntry> {
/// <summary>
/// Adds the given <paramref name="entries"/> to the cache, which must
/// come from the same query identified by <paramref name="key"/>.
/// </summary>
/// <param name="entries">The entries to be cached.</param>
/// <param name="key">The key, which comprises the filter string and the
/// attributes loaded.</param>
/// <exception cref="ArgumentNullException">If
/// <paramref name="entries"/> is <c>null</c>, or if
/// <paramref name="key"/> is <c>null</c>.</exception>
/// <exception cref="ArgumentException">If <paramref name="key"/> is
/// empty.</exception>
ILdapCache<TEntry> Add(IEnumerable<TEntry> entries,
IEnumerable<string> key);
/// <summary>
/// Adds the given <paramref name="entries"/> to the cache, which was
/// retrieved by the given <paramref name="filter"/> and include the
/// given <paramref name="attributes"/>.
/// </summary>
/// <param name="entries">The entries to be cached.</param>
/// <param name="filter">The LDAP filter used to obtain the
/// <paramref name="entries"/>.</param>
/// <param name="attributes">The attributes that have been loaded for
/// <paramref name="entries"/>.</param>
/// <exception cref="ArgumentNullException">If
/// <paramref name="entries"/> is <c>null</c>, or if
/// <paramref name="key"/> is <c>null</c>.</exception>
/// <exception cref="ArgumentException">If <paramref name="key"/> is
/// empty.</exception>
ILdapCache<TEntry> Add(IEnumerable<TEntry> entries,
string filter,
IEnumerable<string> attributes)
=> this.Add(entries, attributes?.Append(filter)!);
/// <summary>
/// Adds the given <paramref name="entry"/> to the cache, which was
/// retrieved by the given <paramref name="filter"/> and includes the
/// given <paramref name="attributes"/>.
/// </summary>
/// <param name="entry">The entry to be cached.</param>
/// <param name="filter">The LDAP filter used to obtain the
/// <paramref name="entry"/>.</param>
/// <param name="attributes">The attributes that have been loaded for
/// <paramref name="entry"/>.</param>
/// <exception cref="ArgumentNullException">If
/// <paramref name="entry"/> is <c>null</c>, or if
/// <paramref name="key"/> is <c>null</c>.</exception>
/// <exception cref="ArgumentException">If <paramref name="key"/> is
/// empty.</exception>
ILdapCache<TEntry> Add(TEntry entry,
string filter,
IEnumerable<string> attributes)
=> this.Add([entry], filter, attributes);
/// <summary>
/// Gets cached LDAP entries which matches the key, which is a
/// combination of the filter and the attributes that have been loaded.
/// </summary>
/// <param name="key">The key of the entries to retrieve, which are a
/// combination of the LDAP search filter and the names of the loaded
/// atrributes..</param>
/// <returns>The entries that have been cached or <c>null</c> if there
/// was no cache entry.</returns>
/// <exception cref="ArgumentNullException">If
/// <paramref name="key"/> is <c>null</c>.</exception>
/// <exception cref="ArgumentException">If <paramref name="key"/> is
/// empty.</exception>
IEnumerable<TEntry>? Get(IEnumerable<string> key);
/// <summary>
/// Gets cached LDAP entries for the given <paramref name="filter"/>
/// expression and the set of loaded <paramref name="attributes"/>.
/// </summary>
/// <param name="filter">The filter to look for.</param>
/// <param name="attributes">The attributes the cached entries must
/// have.</param>
/// <returns>The entries that have been cached or <c>null</c> if there
/// was no cache entry.</returns>
/// <exception cref="ArgumentNullException">If
/// <paramref name="attributes"/> is <c>null</c>.</exception>
IEnumerable<TEntry>? Get(string filter, IEnumerable<string> attributes)
=> this.Get(attributes?.Append(filter)!);
bool GetOrAdd(string filter,
IEnumerable<string> attributes,
Func<IEnumerable<TEntry>> fallback,
out IEnumerable<TEntry> retval) {
ArgumentNullException.ThrowIfNull(filter);
ArgumentNullException.ThrowIfNull(attributes);
ArgumentNullException.ThrowIfNull(fallback);
var key = attributes.Append(filter);
retval = this.Get(key)!;
if (retval != null) {
return true;
}
retval = fallback();
if (retval != null) {
this.Add(retval, key);
}
return false;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
IEnumerable<TEntry> GetOrAdd(string filter,
IEnumerable<string> attributes,
Func<IEnumerable<TEntry>> fallback) {
this.GetOrAdd(filter, attributes, fallback, out var retval);
return retval;
}
/// <summary>
/// Gets a cached entry which matches the given filter or obtains a new
/// entry from <paramref name="fallback"/> and caches it for future use.
/// </summary>
/// <param name="filter">The LDAP filter selecting the entry to look
/// for.</param>
/// <param name="fallback">A function to produce the entry from
/// <parmref name="filter" /> if it was not found in the cache.</param>
/// <param name="name">The name of the entry to look for.</param>
/// <returns>The entry or <c>null</c> if no entry matching the query
/// was found.</returns>
/// <exception cref="ArgumentNullException">If
/// <paramref name="filter"/> is <c>null</c>, or if
/// <paramref name="fallback"/> is <c>null</c>.</exception>
public async Task<IEnumerable<TEntry>> GetOrAdd(string filter,
IEnumerable<string> attributes,
Func<Task<IEnumerable<TEntry>>> fallback) {
ArgumentNullException.ThrowIfNull(filter);
ArgumentNullException.ThrowIfNull(attributes);
ArgumentNullException.ThrowIfNull(fallback);
var key = attributes.Append(filter);
var retval = this.Get(key);
if (retval != null) {
return retval;
}
retval = await fallback();
if (retval != null) {
this.Add(retval, key);
}
return retval!;
}
}
}