@@ -702,8 +702,7 @@ class Cell(s_nexus.Pusher, s_telepath.Aware):
702
702
}
703
703
}
704
704
705
- BACKUP_SPAWN_TIMEOUT = 30.0
706
- BACKUP_ACQUIRE_TIMEOUT = 0.5
705
+ BACKUP_SPAWN_TIMEOUT = 60.0
707
706
708
707
async def __anit__ (self , dirn , conf = None , readonly = False ):
709
708
@@ -1202,75 +1201,69 @@ async def _execBackupTask(self, dirn):
1202
1201
mypipe , child_pipe = ctx .Pipe ()
1203
1202
paths = [str (slab .path ) for slab in slabs ]
1204
1203
loglevel = logger .getEffectiveLevel ()
1204
+ proc = None
1205
1205
1206
- def spawnproc ():
1207
- logger .debug ('Starting multiprocessing target' )
1208
- proc = ctx .Process (target = self ._backupProc , args = (child_pipe , self .dirn , dirn , paths , loglevel ))
1209
- proc .start ()
1210
- hasdata = mypipe .poll (timeout = self .BACKUP_SPAWN_TIMEOUT )
1211
- if not hasdata :
1212
- raise s_exc .SynErr (mesg = 'backup subprocess stuck starting' )
1213
- data = mypipe .recv ()
1214
- assert data == 'ready'
1215
- return proc
1206
+ try :
1216
1207
1217
- proc = await s_coro . executor ( spawnproc )
1208
+ async with self . nexsroot . applylock :
1218
1209
1219
- logger .debug ('Syncing LMDB Slabs' )
1220
- while True :
1221
- await s_lmdbslab .Slab .syncLoopOnce ()
1222
- if not any (slab .dirty for slab in slabs ):
1223
- break
1210
+ logger .debug ('Syncing LMDB Slabs' )
1224
1211
1225
- try :
1212
+ while True :
1213
+ await s_lmdbslab .Slab .syncLoopOnce ()
1214
+ if not any (slab .dirty for slab in slabs ):
1215
+ break
1226
1216
1227
- logger .debug ('Acquiring LMDB txns' )
1228
- mypipe .send ('proceed' )
1217
+ logger .debug ('Starting backup process' )
1229
1218
1230
- # This is technically pending the ioloop waiting for the backup process to acquire a bunch of
1231
- # transactions. We're effectively locking out new write requests the brute force way.
1232
- hasdata = mypipe .poll (timeout = self .BACKUP_ACQUIRE_TIMEOUT )
1233
- if not hasdata :
1234
- raise s_exc .SynErr (mesg = 'backup subprocess stuck acquiring LMDB txns' )
1219
+ args = (child_pipe , self .dirn , dirn , paths , loglevel )
1235
1220
1236
- data = mypipe .recv ()
1237
- assert data == 'captured'
1221
+ def waitforproc1 ():
1222
+ nonlocal proc
1223
+ proc = ctx .Process (target = self ._backupProc , args = args )
1224
+ proc .start ()
1225
+ hasdata = mypipe .poll (timeout = self .BACKUP_SPAWN_TIMEOUT )
1226
+ if not hasdata :
1227
+ raise s_exc .SynErr (mesg = 'backup subprocess start timed out' )
1228
+ data = mypipe .recv ()
1229
+ assert data == 'captured'
1238
1230
1239
- logger . debug ( 'Acquired LMDB txns' )
1231
+ await s_coro . executor ( waitforproc1 )
1240
1232
1241
- def waitforproc ():
1233
+ def waitforproc2 ():
1242
1234
proc .join ()
1243
1235
if proc .exitcode :
1244
1236
raise s_exc .SpawnExit (code = proc .exitcode )
1245
1237
1246
- retn = await s_coro .executor (waitforproc )
1238
+ await s_coro .executor (waitforproc2 )
1239
+ proc = None
1240
+
1241
+ logger .info (f'Backup completed to [{ dirn } ]' )
1242
+ return
1247
1243
1248
1244
except (asyncio .CancelledError , Exception ):
1249
1245
logger .exception (f'Error performing backup to [{ dirn } ]' )
1250
- proc .terminate ()
1251
1246
raise
1252
1247
1253
- else :
1254
- logger . info ( f'Backup completed to [ { dirn } ]' )
1255
- return retn
1248
+ finally :
1249
+ if proc :
1250
+ proc . terminate ()
1256
1251
1257
1252
@staticmethod
1258
1253
def _backupProc (pipe , srcdir , dstdir , lmdbpaths , loglevel ):
1259
1254
'''
1260
1255
(In a separate process) Actually do the backup
1261
1256
'''
1262
- # This logging call is okay to run since we're executing in
1263
- # our own process space and no logging has been configured.
1257
+ # This is a new process: configure logging
1264
1258
s_common .setlogging (logger , loglevel )
1265
- pipe .send ('ready' )
1266
- data = pipe .recv ()
1267
- assert data == 'proceed'
1259
+
1268
1260
with s_t_backup .capturelmdbs (srcdir , onlydirs = lmdbpaths ) as lmdbinfo :
1269
- # Let parent know we have the transactions so he can resume the ioloop
1270
1261
pipe .send ('captured' )
1271
-
1262
+ logger . debug ( 'Acquired LMDB transactions' )
1272
1263
s_t_backup .txnbackup (lmdbinfo , srcdir , dstdir )
1273
1264
1265
+ logger .debug ('Backup process completed' )
1266
+
1274
1267
def _reqBackConf (self ):
1275
1268
if self .backdirn is None :
1276
1269
mesg = 'Backup APIs require the backup:dir config option is set'
0 commit comments