OLD | NEW |
---|---|
1 # Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 # Copyright (c) 2012 The Chromium Authors. All rights reserved. |
2 # Use of this source code is governed by a BSD-style license that can be | 2 # Use of this source code is governed by a BSD-style license that can be |
3 # found in the LICENSE file. | 3 # found in the LICENSE file. |
4 | 4 |
5 import logging | 5 import logging |
6 import os | 6 import os |
7 from StringIO import StringIO | 7 from StringIO import StringIO |
8 import sys | 8 import sys |
9 | 9 |
10 from appengine_wrappers import webapp | 10 from appengine_wrappers import webapp |
(...skipping 14 matching lines...) Expand all Loading... | |
25 from known_issues_data_source import KnownIssuesDataSource | 25 from known_issues_data_source import KnownIssuesDataSource |
26 from local_file_system import LocalFileSystem | 26 from local_file_system import LocalFileSystem |
27 from memcache_file_system import MemcacheFileSystem | 27 from memcache_file_system import MemcacheFileSystem |
28 from reference_resolver import ReferenceResolver | 28 from reference_resolver import ReferenceResolver |
29 from samples_data_source import SamplesDataSource | 29 from samples_data_source import SamplesDataSource |
30 from server_instance import ServerInstance | 30 from server_instance import ServerInstance |
31 from sidenav_data_source import SidenavDataSource | 31 from sidenav_data_source import SidenavDataSource |
32 from subversion_file_system import SubversionFileSystem | 32 from subversion_file_system import SubversionFileSystem |
33 from template_data_source import TemplateDataSource | 33 from template_data_source import TemplateDataSource |
34 from third_party.json_schema_compiler.model import UnixName | 34 from third_party.json_schema_compiler.model import UnixName |
35 from chrome_version_data_source import ChromeVersionDataSource | |
36 from availability_data_source import AvailabilityDataSource | |
35 import url_constants | 37 import url_constants |
36 | 38 |
37 # Increment this version to force the server to reload all pages in the first | 39 # Increment this version to force the server to reload all pages in the first |
38 # cron job that is run. | 40 # cron job that is run. |
39 _VERSION = 1 | 41 _VERSION = 2 |
40 | 42 |
41 # The default channel to serve docs for if no channel is specified. | 43 # The default channel to serve docs for if no channel is specified. |
42 _DEFAULT_CHANNEL = 'stable' | 44 _DEFAULT_CHANNEL = 'stable' |
43 | 45 |
44 BRANCH_UTILITY_MEMCACHE = InMemoryObjectStore('branch_utility') | 46 BRANCH_UTILITY_MEMCACHE = InMemoryObjectStore('branch_utility') |
45 BRANCH_UTILITY = BranchUtility(url_constants.OMAHA_PROXY_URL, | 47 BRANCH_UTILITY = BranchUtility(url_constants.OMAHA_PROXY_URL, |
46 AppEngineUrlFetcher(None), | 48 AppEngineUrlFetcher(None), |
47 BRANCH_UTILITY_MEMCACHE) | 49 BRANCH_UTILITY_MEMCACHE) |
48 | 50 |
51 AVAILABILITY_DATA_SOURCE_MEMCACHE = InMemoryObjectStore( | |
52 'availability_data_source') | |
53 | |
54 CHROME_VERSION_DATA_SOURCE_MEMCACHE = InMemoryObjectStore( | |
55 'chrome_version_data_source') | |
56 CHROME_VERSION_DATA_SOURCE = ChromeVersionDataSource( | |
57 url_constants.OMAHA_BETA_HISTORY, | |
58 AppEngineUrlFetcher(None), | |
59 CHROME_VERSION_DATA_SOURCE_MEMCACHE) | |
60 | |
49 GITHUB_MEMCACHE = InMemoryObjectStore('github') | 61 GITHUB_MEMCACHE = InMemoryObjectStore('github') |
50 GITHUB_FILE_SYSTEM = GithubFileSystem( | 62 GITHUB_FILE_SYSTEM = GithubFileSystem( |
51 AppEngineUrlFetcher(url_constants.GITHUB_URL), | 63 AppEngineUrlFetcher(url_constants.GITHUB_URL), |
52 GITHUB_MEMCACHE, | 64 GITHUB_MEMCACHE, |
53 AppEngineBlobstore()) | 65 AppEngineBlobstore()) |
54 GITHUB_COMPILED_FILE_SYSTEM = CompiledFileSystem.Factory(GITHUB_FILE_SYSTEM, | 66 GITHUB_COMPILED_FILE_SYSTEM = CompiledFileSystem.Factory( |
cduvall
2013/03/21 18:43:53
revert
epeterson
2013/03/25 19:35:11
Done.
| |
55 GITHUB_MEMCACHE) | 67 GITHUB_FILE_SYSTEM, |
68 GITHUB_MEMCACHE) | |
56 | 69 |
57 EXTENSIONS_PATH = 'chrome/common/extensions' | 70 EXTENSIONS_PATH = 'chrome/common/extensions' |
58 DOCS_PATH = 'docs' | 71 DOCS_PATH = 'docs' |
59 API_PATH = 'api' | 72 API_PATH = 'api' |
60 TEMPLATE_PATH = DOCS_PATH + '/templates' | 73 TEMPLATE_PATH = DOCS_PATH + '/templates' |
61 INTRO_PATH = TEMPLATE_PATH + '/intros' | 74 INTRO_PATH = TEMPLATE_PATH + '/intros' |
62 ARTICLE_PATH = TEMPLATE_PATH + '/articles' | 75 ARTICLE_PATH = TEMPLATE_PATH + '/articles' |
63 PUBLIC_TEMPLATE_PATH = TEMPLATE_PATH + '/public' | 76 PUBLIC_TEMPLATE_PATH = TEMPLATE_PATH + '/public' |
64 PRIVATE_TEMPLATE_PATH = TEMPLATE_PATH + '/private' | 77 PRIVATE_TEMPLATE_PATH = TEMPLATE_PATH + '/private' |
65 EXAMPLES_PATH = DOCS_PATH + '/examples' | 78 EXAMPLES_PATH = DOCS_PATH + '/examples' |
66 JSON_PATH = TEMPLATE_PATH + '/json' | 79 JSON_PATH = TEMPLATE_PATH + '/json' |
67 | 80 |
81 | |
cduvall
2013/03/21 18:43:53
Remove newline
epeterson
2013/03/25 19:35:11
Done.
| |
68 # Global cache of instances because Handler is recreated for every request. | 82 # Global cache of instances because Handler is recreated for every request. |
69 SERVER_INSTANCES = {} | 83 SERVER_INSTANCES = {} |
70 | 84 |
71 def _GetURLFromBranch(branch): | 85 def _GetURLFromBranch(branch): |
72 if branch == 'trunk': | 86 if branch == 'trunk': |
73 return url_constants.SVN_TRUNK_URL + '/src' | 87 return url_constants.SVN_TRUNK_URL + '/src' |
74 return url_constants.SVN_BRANCH_URL + '/' + branch + '/src' | 88 return url_constants.SVN_BRANCH_URL + '/' + branch + '/src' |
75 | 89 |
76 def _SplitFilenameUnix(base_dir, files): | 90 def _SplitFilenameUnix(base_dir, files): |
77 return [UnixName(os.path.splitext(f.split('/')[-1])[0]) for f in files] | 91 return [UnixName(os.path.splitext(f.split('/')[-1])[0]) for f in files] |
78 | 92 |
79 def _CreateMemcacheFileSystem(branch, branch_memcache): | 93 def _CreateMemcacheFileSystem(branch, branch_memcache): |
80 svn_url = _GetURLFromBranch(branch) + '/' + EXTENSIONS_PATH | 94 svn_url = _GetURLFromBranch(branch) + '/' + EXTENSIONS_PATH |
81 stat_fetcher = AppEngineUrlFetcher( | 95 stat_fetcher = AppEngineUrlFetcher( |
82 svn_url.replace(url_constants.SVN_URL, url_constants.VIEWVC_URL)) | 96 svn_url.replace(url_constants.SVN_URL, url_constants.VIEWVC_URL)) |
83 fetcher = AppEngineUrlFetcher(svn_url) | 97 fetcher = AppEngineUrlFetcher(svn_url) |
84 return MemcacheFileSystem(SubversionFileSystem(fetcher, stat_fetcher), | 98 return MemcacheFileSystem(SubversionFileSystem(fetcher, stat_fetcher), |
85 branch_memcache) | 99 branch_memcache) |
86 | 100 |
87 _default_branch = BRANCH_UTILITY.GetBranchNumberForChannelName(_DEFAULT_CHANNEL) | 101 _default_branch = BRANCH_UTILITY.GetBranchAndVersionForChannelName( |
102 _DEFAULT_CHANNEL)['branch'] | |
88 APPS_MEMCACHE = InMemoryObjectStore(_default_branch) | 103 APPS_MEMCACHE = InMemoryObjectStore(_default_branch) |
89 APPS_FILE_SYSTEM = _CreateMemcacheFileSystem(_default_branch, APPS_MEMCACHE) | 104 APPS_FILE_SYSTEM = _CreateMemcacheFileSystem(_default_branch, APPS_MEMCACHE) |
90 APPS_COMPILED_FILE_SYSTEM = CompiledFileSystem.Factory( | 105 APPS_COMPILED_FILE_SYSTEM = CompiledFileSystem.Factory( |
91 APPS_FILE_SYSTEM, | 106 APPS_FILE_SYSTEM, |
92 APPS_MEMCACHE).Create(_SplitFilenameUnix, compiled_fs.APPS_FS) | 107 APPS_MEMCACHE).Create(_SplitFilenameUnix, |
cduvall
2013/03/21 18:43:53
revert
epeterson
2013/03/25 19:35:11
Done.
| |
108 compiled_fs.APPS_FS) | |
93 | 109 |
94 EXTENSIONS_MEMCACHE = InMemoryObjectStore(_default_branch) | 110 EXTENSIONS_MEMCACHE = InMemoryObjectStore(_default_branch) |
95 EXTENSIONS_FILE_SYSTEM = _CreateMemcacheFileSystem(_default_branch, | 111 EXTENSIONS_FILE_SYSTEM = _CreateMemcacheFileSystem(_default_branch, |
96 EXTENSIONS_MEMCACHE) | 112 EXTENSIONS_MEMCACHE) |
97 EXTENSIONS_COMPILED_FILE_SYSTEM = CompiledFileSystem.Factory( | 113 EXTENSIONS_COMPILED_FILE_SYSTEM = CompiledFileSystem.Factory( |
98 EXTENSIONS_FILE_SYSTEM, | 114 EXTENSIONS_FILE_SYSTEM, |
99 EXTENSIONS_MEMCACHE).Create(_SplitFilenameUnix, compiled_fs.EXTENSIONS_FS) | 115 EXTENSIONS_MEMCACHE).Create(_SplitFilenameUnix, |
cduvall
2013/03/21 18:43:53
revert
epeterson
2013/03/25 19:35:11
Done.
| |
116 compiled_fs.EXTENSIONS_FS) | |
100 | 117 |
101 KNOWN_ISSUES_DATA_SOURCE = KnownIssuesDataSource( | 118 KNOWN_ISSUES_DATA_SOURCE = KnownIssuesDataSource( |
102 InMemoryObjectStore('KnownIssues'), | 119 InMemoryObjectStore('KnownIssues'), |
103 AppEngineUrlFetcher(None)) | 120 AppEngineUrlFetcher(None)) |
104 | 121 |
105 def _MakeInstanceKey(branch, number): | 122 def _MakeInstanceKey(branch, number): |
106 return '%s/%s' % (branch, number) | 123 return '%s/%s' % (branch, number) |
107 | 124 |
108 def _GetInstanceForBranch(channel_name, local_path): | 125 def _GetInstanceForBranch(channel_name, local_path): |
109 branch = BRANCH_UTILITY.GetBranchNumberForChannelName(channel_name) | 126 branchAndVersion = BRANCH_UTILITY.GetBranchAndVersionForChannelName( |
cduvall
2013/03/21 18:43:53
use unix_hacker style names.
but this can just be
epeterson
2013/03/25 19:35:11
I reworked this. branchAndVersion actually contain
| |
127 channel_name) | |
128 | |
129 branch = branchAndVersion['branch'] | |
130 version = branchAndVersion['version'] | |
110 | 131 |
111 # The key for the server is a tuple of |channel_name| with |branch|, since | 132 # The key for the server is a tuple of |channel_name| with |branch|, since |
112 # sometimes stable and beta point to the same branch. | 133 # sometimes stable and beta point to the same branch. |
113 instance_key = _MakeInstanceKey(channel_name, branch) | 134 instance_key = _MakeInstanceKey(channel_name, branch) |
114 instance = SERVER_INSTANCES.get(instance_key, None) | 135 instance = SERVER_INSTANCES.get(instance_key, None) |
115 if instance is not None: | 136 if instance is not None: |
116 return instance | 137 return instance |
117 | 138 |
118 branch_memcache = InMemoryObjectStore(branch) | 139 branch_memcache = InMemoryObjectStore(branch) |
119 file_system = _CreateMemcacheFileSystem(branch, branch_memcache) | 140 file_system = _CreateMemcacheFileSystem(branch, branch_memcache) |
120 cache_factory = CompiledFileSystem.Factory(file_system, branch_memcache) | 141 cache_factory = CompiledFileSystem.Factory( |
cduvall
2013/03/21 18:43:53
revert
epeterson
2013/03/25 19:35:11
Done.
| |
142 file_system, | |
143 branch_memcache) | |
121 api_list_data_source_factory = APIListDataSource.Factory(cache_factory, | 144 api_list_data_source_factory = APIListDataSource.Factory(cache_factory, |
122 file_system, | 145 file_system, |
123 API_PATH, | 146 API_PATH, |
124 PUBLIC_TEMPLATE_PATH) | 147 PUBLIC_TEMPLATE_PATH) |
148 availability_data_source = AvailabilityDataSource( | |
149 CHROME_VERSION_DATA_SOURCE, | |
150 version, | |
151 AVAILABILITY_DATA_SOURCE_MEMCACHE) | |
125 api_data_source_factory = APIDataSource.Factory( | 152 api_data_source_factory = APIDataSource.Factory( |
126 cache_factory, | 153 cache_factory, |
127 API_PATH) | 154 API_PATH, |
155 availability_data_source) | |
128 | 156 |
129 # Give the ReferenceResolver a memcache, to speed up the lookup of | 157 # Give the ReferenceResolver a memcache, to speed up the lookup of |
130 # duplicate $refs. | 158 # duplicate $refs. |
131 ref_resolver_factory = ReferenceResolver.Factory( | 159 ref_resolver_factory = ReferenceResolver.Factory( |
132 api_data_source_factory, | 160 api_data_source_factory, |
133 api_list_data_source_factory, | 161 api_list_data_source_factory, |
134 branch_memcache) | 162 branch_memcache) |
135 api_data_source_factory.SetReferenceResolverFactory(ref_resolver_factory) | 163 api_data_source_factory.SetReferenceResolverFactory(ref_resolver_factory) |
136 samples_data_source_factory = SamplesDataSource.Factory( | 164 samples_data_source_factory = SamplesDataSource.Factory( |
137 channel_name, | 165 channel_name, |
(...skipping 15 matching lines...) Expand all Loading... | |
153 channel_name, | 181 channel_name, |
154 api_data_source_factory, | 182 api_data_source_factory, |
155 api_list_data_source_factory, | 183 api_list_data_source_factory, |
156 intro_data_source_factory, | 184 intro_data_source_factory, |
157 samples_data_source_factory, | 185 samples_data_source_factory, |
158 KNOWN_ISSUES_DATA_SOURCE, | 186 KNOWN_ISSUES_DATA_SOURCE, |
159 sidenav_data_source_factory, | 187 sidenav_data_source_factory, |
160 cache_factory, | 188 cache_factory, |
161 ref_resolver_factory, | 189 ref_resolver_factory, |
162 PUBLIC_TEMPLATE_PATH, | 190 PUBLIC_TEMPLATE_PATH, |
163 PRIVATE_TEMPLATE_PATH) | 191 PRIVATE_TEMPLATE_PATH, |
192 BRANCH_UTILITY.GetBranchAndVersionForAllChannels()) | |
164 example_zipper = ExampleZipper(file_system, | 193 example_zipper = ExampleZipper(file_system, |
165 cache_factory, | 194 cache_factory, |
166 DOCS_PATH) | 195 DOCS_PATH) |
167 | 196 |
197 #hacky solution for creating a bunch of memcaches in ChromeVersionDataSource | |
198 def _CreateMemcacheForBranch(branch_number): | |
199 """Passed to the global instance of chromeVersionDataSource. Allows for | |
200 the creation of api_data_sources linked to |branch_number|, which is the | |
201 maximum branch number from a given version of chrome. | |
202 """ | |
203 branch_memcache = InMemoryObjectStore(branch_number) | |
204 file_system = _CreateMemcacheFileSystem(branch_number, branch_memcache) | |
205 cache_factory = CompiledFileSystem.Factory( | |
206 file_system, | |
207 branch_memcache, | |
208 branch_number) | |
209 api_list_data_source_factory = APIListDataSource.Factory( | |
210 cache_factory, | |
211 file_system, | |
212 API_PATH, | |
213 PUBLIC_TEMPLATE_PATH) | |
214 api_data_source_factory = APIDataSource.Factory(cache_factory, | |
215 API_PATH) | |
216 ref_resolver_factory = ReferenceResolver.Factory( | |
217 api_data_source_factory, | |
218 api_list_data_source_factory, | |
219 branch_memcache) | |
220 api_data_source_factory.SetReferenceResolverFactory(ref_resolver_factory) | |
221 samples_data_source_factory = SamplesDataSource.Factory( | |
222 channel_name, | |
223 file_system, | |
224 GITHUB_FILE_SYSTEM, | |
225 cache_factory, | |
226 GITHUB_COMPILED_FILE_SYSTEM, | |
227 ref_resolver_factory, | |
228 EXAMPLES_PATH) | |
229 api_data_source_factory.SetSamplesDataSourceFactory( | |
230 samples_data_source_factory) | |
231 return api_data_source_factory.Create(None) | |
232 | |
233 CHROME_VERSION_DATA_SOURCE.SetCreateMemcacheForBranch( | |
cduvall
2013/03/21 18:43:53
Can you just pass this into the ChromeVersionDataS
epeterson
2013/03/25 19:35:11
Done. Yep.
| |
234 _CreateMemcacheForBranch) | |
235 | |
168 instance = ServerInstance(template_data_source_factory, | 236 instance = ServerInstance(template_data_source_factory, |
169 example_zipper, | 237 example_zipper, |
170 cache_factory) | 238 cache_factory) |
171 SERVER_INSTANCES[instance_key] = instance | 239 SERVER_INSTANCES[instance_key] = instance |
172 return instance | 240 return instance |
173 | 241 |
174 def _CleanBranches(): | 242 def _CleanBranches(): |
175 keys = [_MakeInstanceKey(branch, number) | 243 keys = [_MakeInstanceKey(branch, number) |
176 for branch, number in BRANCH_UTILITY.GetAllBranchNumbers()] | 244 for branch, number in BRANCH_UTILITY.GetAllBranchNumbers()] |
177 for key in SERVER_INSTANCES.keys(): | 245 for key in SERVER_INSTANCES.keys(): |
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
255 # We could list all files in PUBLIC_TEMPLATE_PATH then render them. However, | 323 # We could list all files in PUBLIC_TEMPLATE_PATH then render them. However, |
256 # this would be inefficient in the common case where files haven't changed | 324 # this would be inefficient in the common case where files haven't changed |
257 # since the last cron. | 325 # since the last cron. |
258 # | 326 # |
259 # Instead, let the CompiledFileSystem give us clues when to re-render: we | 327 # Instead, let the CompiledFileSystem give us clues when to re-render: we |
260 # use the CFS to check whether the templates, examples, or API folders have | 328 # use the CFS to check whether the templates, examples, or API folders have |
261 # been changed. If there has been a change, the compilation function will | 329 # been changed. If there has been a change, the compilation function will |
262 # be called. The same is then done separately with the apps samples page, | 330 # be called. The same is then done separately with the apps samples page, |
263 # since it pulls its data from Github. | 331 # since it pulls its data from Github. |
264 channel = path.split('/')[-1] | 332 channel = path.split('/')[-1] |
265 branch = BRANCH_UTILITY.GetBranchNumberForChannelName(channel) | 333 branch = BRANCH_UTILITY.GetBranchAndVersionForChannelName(channel)['branch'] |
266 logging.info('Running cron job for %s.' % branch) | 334 logging.info('Running cron job for %s.' % branch) |
267 branch_memcache = InMemoryObjectStore(branch) | 335 branch_memcache = InMemoryObjectStore(branch) |
268 file_system = _CreateMemcacheFileSystem(branch, branch_memcache) | 336 file_system = _CreateMemcacheFileSystem(branch, branch_memcache) |
269 factory = CompiledFileSystem.Factory(file_system, branch_memcache) | 337 factory = CompiledFileSystem.Factory(file_system, |
cduvall
2013/03/21 18:43:53
revert
epeterson
2013/03/25 19:35:11
Done.
| |
338 branch_memcache) | |
270 | 339 |
271 needs_render = self._ValueHolder(False) | 340 needs_render = self._ValueHolder(False) |
272 invalidation_cache = factory.Create(lambda _, __: needs_render.Set(True), | 341 invalidation_cache = factory.Create(lambda _, __: needs_render.Set(True), |
273 compiled_fs.CRON_INVALIDATION, | 342 compiled_fs.CRON_INVALIDATION, |
274 version=_VERSION) | 343 version=_VERSION) |
275 for path in [TEMPLATE_PATH, EXAMPLES_PATH, API_PATH]: | 344 for path in [TEMPLATE_PATH, EXAMPLES_PATH, API_PATH]: |
276 invalidation_cache.GetFromFile(path + '/') | 345 invalidation_cache.GetFromFile(path + '/') |
277 | 346 |
278 if needs_render.Get(): | 347 if needs_render.Get(): |
279 file_listing_cache = factory.Create(lambda _, x: x, | 348 file_listing_cache = factory.Create(lambda _, x: x, |
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
363 | 432 |
364 # Redirect paths like "directory" to "directory/". This is so relative | 433 # Redirect paths like "directory" to "directory/". This is so relative |
365 # file paths will know to treat this as a directory. | 434 # file paths will know to treat this as a directory. |
366 if os.path.splitext(path)[1] == '' and path[-1] != '/': | 435 if os.path.splitext(path)[1] == '' and path[-1] != '/': |
367 self.redirect(path + '/') | 436 self.redirect(path + '/') |
368 return | 437 return |
369 | 438 |
370 path = path.strip('/') | 439 path = path.strip('/') |
371 if not self._RedirectFromCodeDotGoogleDotCom(path): | 440 if not self._RedirectFromCodeDotGoogleDotCom(path): |
372 self._HandleGet(path) | 441 self._HandleGet(path) |
OLD | NEW |