source: box/trunk/bin/bbstored/BBStoreDHousekeeping.cpp @ 3108

Revision 3108, 6.0 KB checked in by chris, 3 weeks ago (diff)

Tag housekeeping logging with the account number and name.

  • Property svn:eol-style set to native
Line 
1// --------------------------------------------------------------------------
2//
3// File
4//              Name:    BBStoreDHousekeeping.cpp
5//              Purpose: Implementation of housekeeping functions for bbstored
6//              Created: 11/12/03
7//
8// --------------------------------------------------------------------------
9
10#include "Box.h"
11
12#include <stdio.h>
13
14#include "BackupStoreDaemon.h"
15#include "BackupStoreAccountDatabase.h"
16#include "BackupStoreAccounts.h"
17#include "HousekeepStoreAccount.h"
18#include "BoxTime.h"
19#include "Configuration.h"
20
21#include "MemLeakFindOn.h"
22
23// --------------------------------------------------------------------------
24//
25// Function
26//              Name:    BackupStoreDaemon::HousekeepingProcess()
27//              Purpose: Do housekeeping
28//              Created: 11/12/03
29//
30// --------------------------------------------------------------------------
31void BackupStoreDaemon::HousekeepingInit()
32{
33
34        mLastHousekeepingRun = 0;
35}
36
37void BackupStoreDaemon::HousekeepingProcess()
38{
39        HousekeepingInit();
40
41        // Get the time between housekeeping runs
42        const Configuration &rconfig(GetConfiguration());
43        int64_t housekeepingInterval = SecondsToBoxTime(rconfig.GetKeyValueInt("TimeBetweenHousekeeping"));
44
45        while(!StopRun())
46        {
47                RunHousekeepingIfNeeded();
48
49                // Stop early?
50                if(StopRun())
51                {
52                        break;
53                }
54
55                // Calculate how long should wait before doing the next
56                // housekeeping run
57                int64_t timeNow = GetCurrentBoxTime();
58                time_t secondsToGo = BoxTimeToSeconds(
59                        (mLastHousekeepingRun + housekeepingInterval) - 
60                        timeNow);
61                if(secondsToGo < 1) secondsToGo = 1;
62                if(secondsToGo > 60) secondsToGo = 60;
63                int32_t millisecondsToGo = ((int)secondsToGo) * 1000;
64       
65                // Check to see if there's any message pending
66                CheckForInterProcessMsg(0 /* no account */, millisecondsToGo);
67        }
68}
69
70void BackupStoreDaemon::RunHousekeepingIfNeeded()
71{
72        // Get the time between housekeeping runs
73        const Configuration &rconfig(GetConfiguration());
74        int64_t housekeepingInterval = SecondsToBoxTime(rconfig.GetKeyValueInt("TimeBetweenHousekeeping"));
75
76        // Time now
77        int64_t timeNow = GetCurrentBoxTime();
78
79        // Do housekeeping if the time interval has elapsed since the last check
80        if((timeNow - mLastHousekeepingRun) < housekeepingInterval)
81        {
82                return;
83        }
84
85        // Store the time
86        mLastHousekeepingRun = timeNow;
87        BOX_INFO("Starting housekeeping");
88
89        // Get the list of accounts
90        std::vector<int32_t> accounts;
91        if(mpAccountDatabase)
92        {
93                mpAccountDatabase->GetAllAccountIDs(accounts);
94        }
95                       
96        SetProcessTitle("housekeeping, active");
97                       
98        // Check them all
99        for(std::vector<int32_t>::const_iterator i = accounts.begin(); i != accounts.end(); ++i)
100        {
101                try
102                {
103                        // Tag log output to identify account
104                        std::ostringstream tag;
105                        tag << "hk/" << BOX_FORMAT_ACCOUNT(*i);
106                        Logging::Tagger tagWithClientID(tag.str());
107
108                        // Get the account root
109                        std::string rootDir;
110                        int discSet = 0;
111                        mpAccounts->GetAccountRoot(*i, rootDir, discSet);
112                       
113                        // Do housekeeping on this account
114                        HousekeepStoreAccount housekeeping(*i, rootDir,
115                                discSet, this);
116                        housekeeping.DoHousekeeping();
117                }
118                catch(BoxException &e)
119                {
120                        BOX_ERROR("Housekeeping on account " <<
121                                BOX_FORMAT_ACCOUNT(*i) << " threw exception, "
122                                "aborting run for this account: " <<
123                                e.what() << " (" <<
124                                e.GetType() << "/" << e.GetSubType() << ")");
125                }
126                catch(std::exception &e)
127                {
128                        BOX_ERROR("Housekeeping on account " <<
129                                BOX_FORMAT_ACCOUNT(*i) << " threw exception, "
130                                "aborting run for this account: " <<
131                                e.what());
132                }
133                catch(...)
134                {
135                        BOX_ERROR("Housekeeping on account " <<
136                                BOX_FORMAT_ACCOUNT(*i) << " threw exception, "
137                                "aborting run for this account: "
138                                "unknown exception");
139                }
140       
141                int64_t timeNow = GetCurrentBoxTime();
142                time_t secondsToGo = BoxTimeToSeconds(
143                        (mLastHousekeepingRun + housekeepingInterval) - 
144                        timeNow);
145                if(secondsToGo < 1) secondsToGo = 1;
146                if(secondsToGo > 60) secondsToGo = 60;
147                int32_t millisecondsToGo = ((int)secondsToGo) * 1000;
148
149                // Check to see if there's any message pending
150                CheckForInterProcessMsg(0 /* no account */, millisecondsToGo);
151
152                // Stop early?
153                if(StopRun())
154                {
155                        break;
156                }
157        }
158               
159        BOX_INFO("Finished housekeeping");
160
161        // Placed here for accuracy, if StopRun() is true, for example.
162        SetProcessTitle("housekeeping, idle");
163}
164
165void BackupStoreDaemon::OnIdle()
166{
167        if (!IsSingleProcess())
168        {
169                return;
170        }
171
172        if (!mHousekeepingInited)
173        {
174                HousekeepingInit();
175                mHousekeepingInited = true;
176        }
177
178        RunHousekeepingIfNeeded();
179}
180
181// --------------------------------------------------------------------------
182//
183// Function
184//              Name:    BackupStoreDaemon::CheckForInterProcessMsg(int, int)
185//              Purpose: Process a message, returning true if the housekeeping process
186//                               should abort for the specified account.
187//              Created: 11/12/03
188//
189// --------------------------------------------------------------------------
190bool BackupStoreDaemon::CheckForInterProcessMsg(int AccountNum, int MaximumWaitTime)
191{
192        if(!mInterProcessCommsSocket.IsOpened())
193        {
194                return false;
195        }
196
197        // First, check to see if it's EOF -- this means something has gone wrong, and the housekeeping should terminate.
198        if(mInterProcessComms.IsEOF())
199        {
200                SetTerminateWanted();
201                return true;
202        }
203
204        // Get a line, and process the message
205        std::string line;
206        if(mInterProcessComms.GetLine(line, false /* no pre-processing */, MaximumWaitTime))
207        {
208                BOX_TRACE("Housekeeping received command '" << line <<
209                        "' over interprocess comms");
210       
211                int account = 0;
212       
213                if(line == "h")
214                {
215                        // HUP signal received by main process
216                        SetReloadConfigWanted();
217                        return true;
218                }
219                else if(line == "t")
220                {
221                        // Terminate signal received by main process
222                        SetTerminateWanted();
223                        return true;
224                }
225                else if(sscanf(line.c_str(), "r%x", &account) == 1)
226                {
227                        // Main process is trying to lock an account -- are we processing it?
228                        if(account == AccountNum)
229                        {
230                                // Yes! -- need to stop now so when it retries to get the lock, it will succeed
231                                BOX_INFO("Housekeeping on account " <<
232                                        BOX_FORMAT_ACCOUNT(AccountNum) <<
233                                        "giving way to client connection");
234                                return true;
235                        }
236                }
237        }
238       
239        return false;
240}
241
242
Note: See TracBrowser for help on using the repository browser.