// ----------------------------------------------------------------------------
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
// ----------------------------------------------------------------------------
namespace Microsoft.Singularity.Security
{
using System;
using System.Collections;
using System.Threading;
using Microsoft.SingSharp;
using Microsoft.Contracts;
using Microsoft.Singularity.Channels;
using Microsoft.Singularity.Directory;
///
/// A ChannelPool
maintains a pool of open channels.
/// (to the security service). It should be possible to parameterize this
/// class for general use.
///
internal class ChannelPool
{
#if POOLED
const int POOL_CAPACITY = 10;
#else
const int POOL_CAPACITY = 1;
#endif
///
/// The unused channels
///
TRef[]! trefs;
int capacity = POOL_CAPACITY;
int nalloc = 0;
int navail = 0;
///
/// Synchronization token
///
object token;
bool disposed;
public ChannelPool()
{
int i;
trefs = new TRef[capacity];
token = new object();
disposed = false;
}
// opens a connection to the security service
private static SecurityDiagnosticsContract.Imp OpenChannel()
{
SecurityDiagnosticsContract.Imp! imp;
SecurityDiagnosticsContract.Exp! exp;
SecurityDiagnosticsContract.NewChannel(out imp, out exp);
// open a channel to the nameservice
DirectoryServiceContract.Imp ns = DirectoryService.NewClientEndpoint();
// try to bind
ns.SendBind(Bitter.FromString2(SecurityDiagnosticsContract.ModuleName), exp);
switch receive {
case ns.AckBind():
break;
case ns.NakBind(rejected, error):
delete imp;
delete rejected;
delete ns;
return null;
}
delete ns;
imp.RecvReady();
return imp;
}
///
/// Returns a free channel. Blocks if none is available.
///
public SecurityDiagnosticsContract.Imp! Acquire()
{
lock (token) {
// wait if no channel is available
while (true) {
if (navail != 0) {
navail--;
return ((!)trefs[navail]).Acquire();
}
if (nalloc < capacity) {
SecurityDiagnosticsContract.Imp imp = OpenChannel();
if (imp != null) {
trefs[nalloc] = new
TRef
(imp);
return ((!)trefs[nalloc++]).Acquire();
}
}
Monitor.Wait(token);
}
}
}
///
/// Releases a channel
///
public void Release([Claims]SecurityDiagnosticsContract.Imp! imp)
{
lock (token) {
((!)trefs[navail++]).Release(imp);
Monitor.PulseAll(token);
}
}
///
/// Closes the channels
///
public void Dispose()
{
lock (token) {
if (!disposed) {
int i;
for (i = 0; i < navail; i++) {
SecurityDiagnosticsContract.Imp! imp = ((!)trefs[i]).Acquire();
delete imp;
}
disposed = true;
}
}
}
}
}