forked from ravendb/ravendb
/
ForwardToRavenRespondersFactory.cs
138 lines (120 loc) · 3.5 KB
/
ForwardToRavenRespondersFactory.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
//-----------------------------------------------------------------------
// <copyright file="ForwardToRavenRespondersFactory.cs" company="Hibernating Rhinos LTD">
// Copyright (c) Hibernating Rhinos LTD. All rights reserved.
// </copyright>
//-----------------------------------------------------------------------
using System;
using System.Threading;
using System.Threading.Tasks;
using System.Web;
using System.Web.Hosting;
using Raven.Abstractions.Logging;
using Raven.Database;
using Raven.Database.Config;
using Raven.Database.Server;
using Raven.Database.Server.Abstractions;
namespace Raven.Web
{
public class ForwardToRavenRespondersFactory : IHttpHandlerFactory
{
internal static DocumentDatabase database;
internal static HttpServer server;
private static readonly object locker = new object();
private static ILog log = LogManager.GetCurrentClassLogger();
public class ReleaseRavenDBWhenAppDomainIsTornDown : IRegisteredObject
{
private Task shutdownTask;
public void Stop(bool immediate)
{
if (shutdownTask == null)
{
lock (this)
{
Thread.MemoryBarrier();
if (shutdownTask == null)
{
shutdownTask = Task.Factory.StartNew(Shutdown)
.ContinueWith(_ =>
{
GC.KeepAlive(_.Exception); // ensure no unobserved exception
HostingEnvironment.UnregisterObject(this);
});
}
}
}
if (immediate)
{
shutdownTask.Wait();
// we already called this from the task's continue with, but
// let us make sure that this is called _before_ we return
// from this method when immediate = true.
HostingEnvironment.UnregisterObject(this);
}
}
}
public IHttpHandler GetHandler(HttpContext context, string requestType, string url, string pathTranslated)
{
if (database == null)
throw new InvalidOperationException("Database has not been initialized properly");
if (server == null)
throw new InvalidOperationException("Server has not been initialized properly");
var reqUrl = UrlExtension.GetRequestUrlFromRawUrl(context.Request.RawUrl, database.Configuration);
if (HttpServer.ChangesQuery.IsMatch(reqUrl))
{
return new ChangesCurrentDatabaseForwardingHandler(server);
}
return new ForwardToRavenResponders(server);
}
public void ReleaseHandler(IHttpHandler handler)
{
}
public static void Init()
{
if (database != null)
return;
lock (locker)
{
if (database != null)
return;
log.Info("Setting up RavenDB Http Integration to the ASP.Net Pipeline");
try
{
var ravenConfiguration = new RavenConfiguration();
HttpEndpointRegistration.RegisterHttpEndpointTarget();
database = new DocumentDatabase(ravenConfiguration);
database.SpinBackgroundWorkers();
server = new HttpServer(ravenConfiguration, database);
server.Init();
}
catch
{
if (database != null)
{
database.Dispose();
database = null;
}
if (server != null)
{
server.Dispose();
server = null;
}
throw;
}
HostingEnvironment.RegisterObject(new ReleaseRavenDBWhenAppDomainIsTornDown());
}
}
public static void Shutdown()
{
lock (locker)
{
log.Info("Disposing of RavenDB Http Integration to the ASP.Net Pipeline");
if (server != null)
server.Dispose();
if (database != null)
database.Dispose();
server = null;
database = null;
}
}
}
}