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 3 // found in the LICENSE file. 4 5 #include "sync/notifier/sync_system_resources.h" 6 7 #include <cstdlib> 8 #include <cstring> 9 #include <string> 10 11 #include "base/bind.h" 12 #include "base/logging.h" 13 #include "base/message_loop/message_loop.h" 14 #include "base/stl_util.h" 15 #include "base/strings/string_util.h" 16 #include "base/strings/stringprintf.h" 17 #include "google/cacheinvalidation/deps/callback.h" 18 #include "google/cacheinvalidation/include/types.h" 19 #include "jingle/notifier/listener/push_client.h" 20 #include "sync/notifier/invalidation_util.h" 21 22 namespace syncer { 23 24 SyncLogger::SyncLogger() {} 25 SyncLogger::~SyncLogger() {} 26 27 void SyncLogger::Log(LogLevel level, const char* file, int line, 28 const char* format, ...) { 29 logging::LogSeverity log_severity = -2; // VLOG(2) 30 bool emit_log = false; 31 switch (level) { 32 case FINE_LEVEL: 33 log_severity = -2; // VLOG(2) 34 emit_log = VLOG_IS_ON(2); 35 break; 36 case INFO_LEVEL: 37 log_severity = -1; // VLOG(1) 38 emit_log = VLOG_IS_ON(1); 39 break; 40 case WARNING_LEVEL: 41 log_severity = logging::LOG_WARNING; 42 emit_log = LOG_IS_ON(WARNING); 43 break; 44 case SEVERE_LEVEL: 45 log_severity = logging::LOG_ERROR; 46 emit_log = LOG_IS_ON(ERROR); 47 break; 48 } 49 if (emit_log) { 50 va_list ap; 51 va_start(ap, format); 52 std::string result; 53 base::StringAppendV(&result, format, ap); 54 logging::LogMessage(file, line, log_severity).stream() << result; 55 va_end(ap); 56 } 57 } 58 59 void SyncLogger::SetSystemResources(invalidation::SystemResources* resources) { 60 // Do nothing. 61 } 62 63 SyncInvalidationScheduler::SyncInvalidationScheduler() 64 : weak_factory_(this), 65 created_on_loop_(base::MessageLoop::current()), 66 is_started_(false), 67 is_stopped_(false) { 68 CHECK(created_on_loop_); 69 } 70 71 SyncInvalidationScheduler::~SyncInvalidationScheduler() { 72 CHECK_EQ(created_on_loop_, base::MessageLoop::current()); 73 CHECK(is_stopped_); 74 } 75 76 void SyncInvalidationScheduler::Start() { 77 CHECK_EQ(created_on_loop_, base::MessageLoop::current()); 78 CHECK(!is_started_); 79 is_started_ = true; 80 is_stopped_ = false; 81 weak_factory_.InvalidateWeakPtrs(); 82 } 83 84 void SyncInvalidationScheduler::Stop() { 85 CHECK_EQ(created_on_loop_, base::MessageLoop::current()); 86 is_stopped_ = true; 87 is_started_ = false; 88 weak_factory_.InvalidateWeakPtrs(); 89 STLDeleteElements(&posted_tasks_); 90 posted_tasks_.clear(); 91 } 92 93 void SyncInvalidationScheduler::Schedule(invalidation::TimeDelta delay, 94 invalidation::Closure* task) { 95 DCHECK(invalidation::IsCallbackRepeatable(task)); 96 CHECK_EQ(created_on_loop_, base::MessageLoop::current()); 97 98 if (!is_started_) { 99 delete task; 100 return; 101 } 102 103 posted_tasks_.insert(task); 104 base::MessageLoop::current()->PostDelayedTask( 105 FROM_HERE, base::Bind(&SyncInvalidationScheduler::RunPostedTask, 106 weak_factory_.GetWeakPtr(), task), 107 delay); 108 } 109 110 bool SyncInvalidationScheduler::IsRunningOnThread() const { 111 return created_on_loop_ == base::MessageLoop::current(); 112 } 113 114 invalidation::Time SyncInvalidationScheduler::GetCurrentTime() const { 115 CHECK_EQ(created_on_loop_, base::MessageLoop::current()); 116 return base::Time::Now(); 117 } 118 119 void SyncInvalidationScheduler::SetSystemResources( 120 invalidation::SystemResources* resources) { 121 // Do nothing. 122 } 123 124 void SyncInvalidationScheduler::RunPostedTask(invalidation::Closure* task) { 125 CHECK_EQ(created_on_loop_, base::MessageLoop::current()); 126 task->Run(); 127 posted_tasks_.erase(task); 128 delete task; 129 } 130 131 SyncStorage::SyncStorage(StateWriter* state_writer, 132 invalidation::Scheduler* scheduler) 133 : state_writer_(state_writer), 134 scheduler_(scheduler) { 135 DCHECK(state_writer_); 136 DCHECK(scheduler_); 137 } 138 139 SyncStorage::~SyncStorage() {} 140 141 void SyncStorage::WriteKey(const std::string& key, const std::string& value, 142 invalidation::WriteKeyCallback* done) { 143 CHECK(state_writer_); 144 // TODO(ghc): actually write key,value associations, and don't invoke the 145 // callback until the operation completes. 146 state_writer_->WriteState(value); 147 cached_state_ = value; 148 // According to the cache invalidation API folks, we can do this as 149 // long as we make sure to clear the persistent state that we start 150 // up the cache invalidation client with. However, we musn't do it 151 // right away, as we may be called under a lock that the callback 152 // uses. 153 scheduler_->Schedule( 154 invalidation::Scheduler::NoDelay(), 155 invalidation::NewPermanentCallback( 156 this, &SyncStorage::RunAndDeleteWriteKeyCallback, 157 done)); 158 } 159 160 void SyncStorage::ReadKey(const std::string& key, 161 invalidation::ReadKeyCallback* done) { 162 DCHECK(scheduler_->IsRunningOnThread()) << "not running on scheduler thread"; 163 RunAndDeleteReadKeyCallback(done, cached_state_); 164 } 165 166 void SyncStorage::DeleteKey(const std::string& key, 167 invalidation::DeleteKeyCallback* done) { 168 // TODO(ghc): Implement. 169 LOG(WARNING) << "ignoring call to DeleteKey(" << key << ", callback)"; 170 } 171 172 void SyncStorage::ReadAllKeys(invalidation::ReadAllKeysCallback* done) { 173 // TODO(ghc): Implement. 174 LOG(WARNING) << "ignoring call to ReadAllKeys(callback)"; 175 } 176 177 void SyncStorage::SetSystemResources( 178 invalidation::SystemResources* resources) { 179 // Do nothing. 180 } 181 182 void SyncStorage::RunAndDeleteWriteKeyCallback( 183 invalidation::WriteKeyCallback* callback) { 184 callback->Run( 185 invalidation::Status(invalidation::Status::SUCCESS, std::string())); 186 delete callback; 187 } 188 189 void SyncStorage::RunAndDeleteReadKeyCallback( 190 invalidation::ReadKeyCallback* callback, const std::string& value) { 191 callback->Run(std::make_pair( 192 invalidation::Status(invalidation::Status::SUCCESS, std::string()), 193 value)); 194 delete callback; 195 } 196 197 SyncSystemResources::SyncSystemResources( 198 scoped_ptr<notifier::PushClient> push_client, 199 StateWriter* state_writer) 200 : is_started_(false), 201 logger_(new SyncLogger()), 202 internal_scheduler_(new SyncInvalidationScheduler()), 203 listener_scheduler_(new SyncInvalidationScheduler()), 204 storage_(new SyncStorage(state_writer, internal_scheduler_.get())), 205 push_client_channel_(push_client.Pass()) { 206 } 207 208 SyncSystemResources::~SyncSystemResources() { 209 Stop(); 210 } 211 212 void SyncSystemResources::Start() { 213 internal_scheduler_->Start(); 214 listener_scheduler_->Start(); 215 is_started_ = true; 216 } 217 218 void SyncSystemResources::Stop() { 219 internal_scheduler_->Stop(); 220 listener_scheduler_->Stop(); 221 } 222 223 bool SyncSystemResources::IsStarted() const { 224 return is_started_; 225 } 226 227 void SyncSystemResources::set_platform(const std::string& platform) { 228 platform_ = platform; 229 } 230 231 std::string SyncSystemResources::platform() const { 232 return platform_; 233 } 234 235 SyncLogger* SyncSystemResources::logger() { 236 return logger_.get(); 237 } 238 239 SyncStorage* SyncSystemResources::storage() { 240 return storage_.get(); 241 } 242 243 PushClientChannel* SyncSystemResources::network() { 244 return &push_client_channel_; 245 } 246 247 SyncInvalidationScheduler* SyncSystemResources::internal_scheduler() { 248 return internal_scheduler_.get(); 249 } 250 251 SyncInvalidationScheduler* SyncSystemResources::listener_scheduler() { 252 return listener_scheduler_.get(); 253 } 254 255 } // namespace syncer 256