00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00018
00019 #ifndef NET_INSTAWEB_REWRITER_PUBLIC_REWRITE_CONTEXT_H_
00020 #define NET_INSTAWEB_REWRITER_PUBLIC_REWRITE_CONTEXT_H_
00021
00022 #include <set>
00023 #include <vector>
00024
00025 #include "base/scoped_ptr.h"
00026 #include "net/instaweb/http/public/http_cache.h"
00027 #include "net/instaweb/rewriter/public/output_resource_kind.h"
00028 #include "net/instaweb/rewriter/public/resource.h"
00029 #include "net/instaweb/rewriter/public/resource_manager.h"
00030 #include "net/instaweb/rewriter/public/resource_slot.h"
00031 #include "net/instaweb/rewriter/public/rewrite_context.h"
00032 #include "net/instaweb/rewriter/public/rewrite_result.h"
00033 #include "net/instaweb/util/public/basictypes.h"
00034 #include "net/instaweb/util/public/cache_interface.h"
00035 #include "net/instaweb/util/public/string.h"
00036 #include "net/instaweb/util/public/string_util.h"
00037 #include "net/instaweb/util/public/url_segment_encoder.h"
00038
00039 namespace net_instaweb {
00040
00041 class AsyncFetch;
00042 class CachedResult;
00043 class GoogleUrl;
00044 class InputInfo;
00045 class MessageHandler;
00046 class NamedLock;
00047 class OutputPartitions;
00048 class ResourceContext;
00049 class ResponseHeaders;
00050 class RewriteDriver;
00051 class RewriteOptions;
00052 class SharedString;
00053 class Writer;
00054
00095 class RewriteContext {
00096 public:
00099 RewriteContext(RewriteDriver* driver,
00100 RewriteContext* parent,
00101 ResourceContext* resource_context);
00102 virtual ~RewriteContext();
00103
00108 int num_slots() const { return slots_.size(); }
00109 ResourceSlotPtr slot(int index) const { return slots_[index]; }
00110
00113 int num_outputs() const { return outputs_.size(); }
00114 OutputResourcePtr output(int i) const { return outputs_[i]; }
00115
00118 int num_output_partitions() const;
00119 const CachedResult* output_partition(int i) const;
00120 CachedResult* output_partition(int i);
00121
00124 bool chained() const { return chained_ != 0; }
00125
00129 void AddSlot(const ResourceSlotPtr& slot);
00130
00133 void RemoveLastSlot();
00134
00145 void Initiate();
00146
00154 bool Fetch(const OutputResourcePtr& output_resource,
00155 AsyncFetch* fetch,
00156 MessageHandler* message_handler);
00157
00181 void Propagate(bool render_slots);
00182
00185 bool slow() const { return slow_; }
00186
00188 bool has_parent() const { return parent_ != NULL; }
00189
00191 RewriteContext* parent() { return parent_; }
00192 const RewriteContext* parent() const { return parent_; }
00193
00196 void AddNestedContext(RewriteContext* context);
00197
00199 void set_force_rewrite(bool x) { force_rewrite_ = x; }
00200
00201 protected:
00202 typedef std::vector<InputInfo*> InputInfoStarVector;
00203 typedef std::vector<GoogleUrl*> GoogleUrlStarVector;
00204
00206
00210 ResourceManager* Manager() const;
00211 const RewriteOptions* Options();
00212 RewriteDriver* Driver() const;
00213 const ResourceContext* resource_context() { return resource_context_.get(); }
00214
00222 bool IsCachedResultValid(CachedResult* partition,
00223 bool* can_revalidate,
00224 InputInfoStarVector* revalidate);
00225
00228 bool IsOtherDependencyValid(const OutputPartitions* partitions);
00229
00231 bool IsInputValid(const InputInfo& input_info);
00232
00235 void AddRecheckDependency();
00236
00240 void RenderPartitionOnDetach(int partition_index);
00241
00246 void RewriteDone(RewriteResult result, int partition_index);
00247
00252 void NestedRewriteDone(const RewriteContext* context);
00253
00257 void StartNestedTasks();
00258
00270 bool TryDecodeCacheResult(CacheInterface::KeyState state,
00271 const SharedString& value,
00272 bool* can_revalidate,
00273 InputInfoStarVector* revalidate);
00274
00277 bool CreateOutputResourceForCachedOutput(const CachedResult* cached_result,
00278 OutputResourcePtr* output_resource);
00279
00283 virtual bool OptimizationOnly() const { return true; }
00284
00302 virtual bool Partition(OutputPartitions* partitions,
00303 OutputResourceVector* outputs);
00304
00310 virtual void PartitionAsync(OutputPartitions* partitions,
00311 OutputResourceVector* outputs);
00312
00316 void PartitionDone(bool result);
00317
00320 void CrossThreadPartitionDone(bool result);
00321
00333 virtual void Rewrite(int partition_index,
00334 CachedResult* partition,
00335 const OutputResourcePtr& output) = 0;
00336
00341 virtual void Harvest();
00342
00352 virtual void Render();
00353
00356
00363 virtual const UrlSegmentEncoder* encoder() const;
00364
00367 virtual GoogleString CacheKeySuffix() const;
00368
00370 virtual const char* id() const = 0;
00371
00380 virtual OutputResourceKind kind() const = 0;
00381
00391 virtual void StartFetchReconstruction();
00392
00398 void DetachFetch();
00399
00404 virtual bool DecodeFetchUrls(const OutputResourcePtr& output_resource,
00405 MessageHandler* message_handler,
00406 GoogleUrlStarVector* url_vector);
00407
00411 virtual void FixFetchFallbackHeaders(ResponseHeaders* headers);
00412
00415 virtual void FetchCallbackDone(bool success);
00416
00423 virtual bool AbsolutifyIfNeeded(const StringPiece& input_contents,
00424 Writer* writer, MessageHandler* handler);
00425
00430 virtual void FetchTryFallback(const GoogleString& url,
00431 const StringPiece& hash);
00432
00434 void Freshen();
00435
00437 int num_nested() const { return nested_.size(); }
00438 RewriteContext* nested(int i) const { return nested_[i]; }
00439
00440 OutputPartitions* partitions() { return partitions_.get(); }
00441
00442 void set_notify_driver_on_fetch_done(bool value) {
00443 notify_driver_on_fetch_done_ = value;
00444 }
00445
00447 AsyncFetch* async_fetch();
00448
00450 MessageHandler* fetch_message_handler();
00451
00453 bool stale_rewrite() const { return stale_rewrite_; }
00454
00455 private:
00456 class OutputCacheCallback;
00457 friend class OutputCacheCallback;
00458 class HTTPCacheCallback;
00459 friend class HTTPCacheCallback;
00460 class ResourceCallbackUtils;
00461 friend class ResourceCallbackUtils;
00462 class ResourceFetchCallback;
00463 class ResourceReconstructCallback;
00464 class ResourceRevalidateCallback;
00465 friend class ResourceRevalidateCallback;
00466 class InvokeRewriteFunction;
00467 friend class InvokeRewriteFunction;
00468 class RewriteFreshenCallback;
00469
00470 typedef std::set<RewriteContext*> ContextSet;
00471
00475 enum FallbackCondition {
00476 kFallbackDiscretional,
00477
00478 kFallbackEmergency
00479
00480 };
00481
00483 void Start();
00484 void SetPartitionKey();
00485 void StartFetch();
00486 void OutputCacheDone(CacheInterface::KeyState state, SharedString value);
00487 void OutputCacheHit(bool write_partitions);
00488 void OutputCacheRevalidate(const InputInfoStarVector& to_revalidate);
00489 void OutputCacheMiss();
00490 void ResourceFetchDone(bool success, ResourcePtr resource, int slot_index);
00491 void ResourceRevalidateDone(InputInfo* input_info, bool success);
00492
00497 void RepeatedSuccess(const RewriteContext* primary);
00498 void RepeatedFailure();
00499
00508 void Finalize();
00509
00511 NamedLock* Lock();
00512
00522 void FetchInputs();
00523
00527 void Activate();
00528
00535 void StartRewriteForHtml();
00536 void StartRewriteForFetch();
00537
00544 bool ReadyToRewrite() const;
00545
00548 void RunSuccessors();
00549
00552 void WritePartition();
00553
00563 void FinalizeRewriteForHtml();
00564
00567 void MarkSlow();
00568
00571 void MarkTooBusy();
00572
00576 void CollectDependentTopLevel(ContextSet* contexts);
00577
00580 void RewriteDoneImpl(RewriteResult result, int partition_index);
00581
00584 void StartNestedTasksImpl();
00585
00587 void FetchCacheDone(CacheInterface::KeyState state, SharedString value);
00588
00591 void FetchFallbackCacheDone(HTTPCache::FindResult result,
00592 HTTPCache::Callback* data);
00593
00598 bool CanFetchFallbackToOriginal(FallbackCondition circumstance) const;
00599
00601 ResourceSlotVector slots_;
00602
00606 std::vector<bool> render_slots_;
00607
00618
00619 bool started_;
00620 scoped_ptr<OutputPartitions> partitions_;
00621 OutputResourceVector outputs_;
00622 int outstanding_fetches_;
00623 int outstanding_rewrites_;
00624 scoped_ptr<ResourceContext> resource_context_;
00625 GoogleString partition_key_;
00626
00627 UrlSegmentEncoder default_encoder_;
00628
00631 scoped_ptr<NamedLock> lock_;
00632
00636 class FetchContext;
00637 scoped_ptr<FetchContext> fetch_;
00638
00641 std::vector<RewriteContext*> successors_;
00642
00646 std::vector<RewriteContext*> repeated_;
00647
00651 int num_pending_nested_;
00652 std::vector<RewriteContext*> nested_;
00653
00655 RewriteContext* parent_;
00656
00666 RewriteDriver* driver_;
00667
00669 int num_predecessors_;
00670
00673 bool chained_;
00674
00692
00694 bool rewrite_done_;
00695
00700 bool ok_to_write_output_partitions_;
00701
00704 bool was_too_busy_;
00705
00709 bool slow_;
00710
00712 bool revalidate_ok_;
00713
00716 bool notify_driver_on_fetch_done_;
00717
00720 bool force_rewrite_;
00721
00724 bool stale_rewrite_;
00725
00726 DISALLOW_COPY_AND_ASSIGN(RewriteContext);
00727 };
00728
00729 }
00730
00731 #endif ///< NET_INSTAWEB_REWRITER_PUBLIC_REWRITE_CONTEXT_H_