Project

General

Profile

1
package eu.dnetlib.data.mdstore.modular.mongodb;
2

    
3
import java.util.Collections;
4
import java.util.Date;
5
import java.util.List;
6

    
7
import com.google.common.collect.Lists;
8
import com.mongodb.BasicDBList;
9
import com.mongodb.BasicDBObject;
10
import com.mongodb.DBObject;
11
import com.mongodb.WriteConcern;
12
import com.mongodb.client.FindIterable;
13
import com.mongodb.client.MongoCollection;
14
import com.mongodb.client.MongoDatabase;
15
import com.mongodb.client.MongoIterable;
16
import com.mongodb.client.model.Filters;
17
import com.mongodb.client.model.UpdateOptions;
18
import eu.dnetlib.data.mdstore.MDStoreServiceException;
19
import eu.dnetlib.data.mdstore.modular.connector.*;
20
import eu.dnetlib.data.mdstore.modular.mongodb.utils.MDStoreUtils;
21
import org.apache.commons.lang.StringUtils;
22
import org.apache.commons.logging.Log;
23
import org.apache.commons.logging.LogFactory;
24
import org.bson.conversions.Bson;
25
import org.joda.time.DateTime;
26
import org.joda.time.Days;
27
import org.springframework.beans.factory.annotation.Required;
28

    
29
/**
30
 * The Class MDStoreTransactionManager.
31
 */
32
public class MDStoreTransactionManagerImpl implements MDStoreTransactionManager {
33

    
34
	/** The Constant log. */
35
	private static final Log log = LogFactory.getLog(MDStoreTransactionManagerImpl.class);
36

    
37
	/**
38
	 * The table name.
39
	 */
40
	private static String TABLE_NAME = "metadataManager";
41

    
42
	/** The max number of concurrent transactions per mdstore. */
43
	private int maxTransactions = 1;
44

    
45
	/**
46
	 * The db.
47
	 */
48
	private MongoDatabase db;
49

    
50
	/**
51
	 * The manager table.
52
	 */
53
	private MongoCollection<DBObject> managerTable;
54

    
55
	/** The expired days. */
56
	private int expiredDays;
57

    
58
	/**
59
	 * Bootstrap manager.
60
	 */
61
	private void bootstrapManager() {
62
		log.debug("Bootstrap Manager start");
63
		final MongoCollection<DBObject> metadataColl = db.getCollection("metadata", DBObject.class);
64
		final FindIterable<DBObject> values = metadataColl.find();
65
		this.setManagerTable(db.getCollection(TABLE_NAME, DBObject.class));
66
		for (DBObject object : values) {
67
			final String id = (String) object.get("mdId");
68
			String newId = id;
69
			if (id.contains("_")) {
70
				newId = StringUtils.substringBefore(id, "_");
71
			}
72
			final BasicDBObject input = new BasicDBObject();
73
			input.put("mdId", id);
74
			input.put("currentId", newId);
75
			input.put("expiring", new String[] {});
76
			input.put("transactions", new String[] {});
77
			getManagerTable().insertOne(input);
78
			log.debug(String.format("Added %s to Metadata Manager data structure", id));
79

    
80
		}
81
		final BasicDBObject ensureIndex = new BasicDBObject();
82
		ensureIndex.put("mdId", 1);
83
		log.debug("Create index in MetadaManager ");
84
		this.getManagerTable().createIndex(ensureIndex);
85
	}
86

    
87
	/**
88
	 * Gets the DBObject describing an mdstore. null if there is no mdstore with the given id.
89
	 *
90
	 * @param mdstoreID
91
	 * @return DBObject or null
92
	 */
93
	private DBObject getMDStoreAsDBObject(String mdstoreID) throws MDStoreServiceException {
94
		final BasicDBObject query = new BasicDBObject();
95
		query.put("mdId", mdstoreID);
96
		final FindIterable<DBObject> it = this.getManagerTable().find(query);
97
		DBObject mdstoreInfo = it.first();
98
		return mdstoreInfo;
99
	}
100

    
101
	/**
102
	 * Verify consistency.
103
	 *
104
	 * @throws MDStoreServiceException
105
	 *             the MD store service exception
106
	 */
107
	@Override
108
	public void verifyConsistency() throws MDStoreServiceException {
109
		if (this.getManagerTable() == null) {
110
			if (!Lists.newArrayList(db.listCollectionNames()).contains(TABLE_NAME))
111
				bootstrapManager();
112
			else {
113
				this.setManagerTable(db.getCollection(TABLE_NAME, DBObject.class));
114
			}
115
		}
116
		if (this.getManagerTable() == null) throw new MDStoreServiceException("Something bad happen, unable to create managerTable");
117
	}
118

    
119
	/**
120
	 * {@inheritDoc}
121
	 *
122
	 * @see eu.dnetlib.data.mdstore.modular.connector.MDStoreTransactionManager#createMDStore(java.lang.String)
123
	 */
124
	@Override
125
	public void createMDStore(final String mdId) throws MDStoreServiceException {
126
		log.debug("Creating new mdstore");
127
		verifyConsistency();
128
		String newId = mdId;
129
		if (mdId.contains("_")) {
130
			newId = StringUtils.substringBefore(mdId, "_");
131
		}
132
		final BasicDBObject instance = new BasicDBObject();
133
		instance.put("mdId", mdId);
134
		instance.put("currentId", newId);
135
		instance.put("expiring", new String[] {});
136
		getManagerTable().insertOne(instance);
137
	}
138

    
139
	/**
140
	 * {@inheritDoc}
141
	 *
142
	 * @see eu.dnetlib.data.mdstore.modular.connector.MDStoreTransactionManager#dropMDStore(java.lang.String)
143
	 */
144
	@Override
145
	public void dropMDStore(final String mdId) throws MDStoreServiceException {
146
		verifyConsistency();
147
		log.debug("Droping MDStore: " + mdId);
148
		final BasicDBObject query = new BasicDBObject();
149
		query.put("mdId", mdId);
150
		final DBObject dropped = this.getManagerTable().findOneAndDelete(query);
151
		garbage();
152
		final String collectionName = (String) dropped.get("currentId");
153
		this.db.getCollection(collectionName).drop();
154
		this.db.getCollection("discarded-" + collectionName).drop();
155
	}
156

    
157
	/**
158
	 * {@inheritDoc}
159
	 *
160
	 * @see eu.dnetlib.data.mdstore.modular.connector.MDStoreTransactionManager#getMDStoreCollection(java.lang.String)
161
	 */
162
	@Override
163
	public String getMDStoreCollection(final String mdId) throws MDStoreServiceException {
164
		verifyConsistency();
165
		DBObject mdstoreInfo = getMDStoreAsDBObject(mdId);
166
		if (mdstoreInfo != null)
167
			return (String) mdstoreInfo.get("currentId");
168
		else return null;
169
	}
170

    
171
	/**
172
	 * {@inheritDoc}
173
	 *
174
	 * @see eu.dnetlib.data.mdstore.modular.connector.MDStoreTransactionManager#startTransaction(java.lang.String, boolean)
175
	 */
176
	@Override
177
	public String startTransaction(final String mdId, final boolean refresh) throws MDStoreServiceException {
178
		verifyConsistency();
179
		log.info("Start transaction for metadata store " + mdId);
180
		final DBObject mdstoreInfo = getMDStoreAsDBObject(mdId);
181
		if (mdstoreInfo == null) throw new MDStoreServiceException("Error, unable to find Mdstore with Id " + mdId);
182
		String idCreation = StringUtils.substringBefore(mdId, "_");
183
		idCreation = idCreation + "::" + System.currentTimeMillis();
184

    
185
		BasicDBList values;
186
		if (mdstoreInfo.containsField("transactions")) {
187
			values = (BasicDBList) mdstoreInfo.get("transactions");
188
			if (values.size() > getMaxTransactions())
189
				throw new MDStoreServiceException("Cannot create more than " + getMaxTransactions() + " transactions, found: " + values.size() + ", mdId:"
190
						+ mdId);
191
		} else {
192
			values = new BasicDBList();
193
		}
194
		final BasicDBObject transactionMetadata = new BasicDBObject();
195
		transactionMetadata.put("id", idCreation.toString());
196
		transactionMetadata.put("refresh", refresh);
197
		transactionMetadata.put("date", new Date());
198
		values.add(transactionMetadata);
199
		mdstoreInfo.put("transactions", values);
200
		this.getManagerTable().findOneAndReplace(new BasicDBObject("_id", mdstoreInfo.get("_id")), mdstoreInfo);
201
		return idCreation.toString();
202
	}
203

    
204
	/**
205
	 * {@inheritDoc}
206
	 *
207
	 * @see eu.dnetlib.data.mdstore.modular.connector.MDStoreTransactionManager#commit(java.lang.String, java.lang.String,
208
	 *      eu.dnetlib.data.mdstore.modular.connector.MDStore)
209
	 */
210
	@Override
211
	public boolean commit(final String transactionId, final String mdstoreId, final MDStore current) throws MDStoreServiceException {
212
		verifyConsistency();
213
		final DBObject mdstoreInfo = getMDStoreAsDBObject(mdstoreId);
214
		if (mdstoreInfo == null) throw new MDStoreServiceException("Error, unable to find Mdstore with Id " + mdstoreId);
215
		final BasicDBList transactions = (BasicDBList) mdstoreInfo.get("transactions");
216
		final DBObject transaction = findTransaction(transactions, transactionId);
217
		if (transaction == null) throw new MDStoreServiceException("Error, unable to find transaction with Id " + transactionId);
218
		final boolean refresh = (Boolean) transaction.get("refresh");
219
		transactions.remove(transaction);
220
		final String oldId = (String) mdstoreInfo.get("currentId");
221
		if (refresh) {
222
			mdstoreInfo.put("currentId", transactionId);
223
			final BasicDBList stillUsed = (BasicDBList) mdstoreInfo.get("expiring");
224
			if (stillUsed.size() == 0) {
225
				db.getCollection(oldId).drop();
226
				db.getCollection("discarded-" + oldId).drop();
227
			}
228
			log.debug("Replaced collection ");
229
		} else {
230
			log.debug("commit incremental ");
231
			updateIncremental(transactionId, oldId);
232
			db.getCollection(transactionId).drop();
233
			db.getCollection("discarded-" + transactionId).drop();
234
		}
235
		this.getManagerTable().findOneAndReplace(new BasicDBObject("_id", mdstoreInfo.get("_id")), mdstoreInfo);
236

    
237
		log.info("Committed transaction for metadata store " + mdstoreId);
238
		return true;
239
	}
240

    
241
	/**
242
	 * Find transaction.
243
	 *
244
	 * @param transactions
245
	 *            the transactions
246
	 * @param transactionId
247
	 *            the transaction id
248
	 * @return the DB object
249
	 */
250
	private DBObject findTransaction(final BasicDBList transactions, final String transactionId) {
251
		if (transactions.size() == 0) return null;
252
		for (int i = 0; i < transactions.size(); i++) {
253
			final BasicDBObject transaction = (BasicDBObject) transactions.get(i);
254
			final String id = (String) transaction.get("id");
255
			if (transactionId.equals(id)) return transaction;
256
		}
257
		return null;
258

    
259
	}
260

    
261
	/**
262
	 * Gets the db.
263
	 *
264
	 * @return the db
265
	 */
266
	public MongoDatabase getDb() {
267
		return db;
268
	}
269

    
270
	/**
271
	 * Sets the db.
272
	 *
273
	 * @param db
274
	 *            the db to set
275
	 */
276
	@Required
277
	public void setDb(final MongoDatabase db) {
278
		this.db = db;
279
	}
280

    
281
	/**
282
	 * {@inheritDoc}
283
	 *
284
	 * @see eu.dnetlib.data.mdstore.modular.connector.MDStoreTransactionManager#readMdStore(java.lang.String)
285
	 */
286
	@Override
287
	public String readMdStore(final String mdStoreId) throws MDStoreServiceException {
288
		verifyConsistency();
289
		final DBObject mdstoreInfo = getMDStoreAsDBObject(mdStoreId);
290
		if (mdstoreInfo == null) throw new MDStoreServiceException("Error, unable to find Mdstore with Id " + mdStoreId);
291
		final String currentId = (String) mdstoreInfo.get("currentId");
292
		final BasicDBList values = (BasicDBList) mdstoreInfo.get("expiring");
293
		updateMdstoreUsed(values, currentId);
294
		this.getManagerTable().findOneAndReplace(new BasicDBObject("_id", mdstoreInfo.get("_id")), mdstoreInfo);
295
		return currentId;
296

    
297
	}
298

    
299

    
300
	/**
301
	 * Update mdstore used.
302
	 *
303
	 * @param values
304
	 *            the values
305
	 * @param mdId
306
	 *            the md id
307
	 */
308
	private void updateMdstoreUsed(final BasicDBList values, final String mdId) {
309
		if (values.size() > 0) {
310
			for (int i = 0; i < values.size(); i++) {
311
				final DBObject obj = (DBObject) values.get(i);
312
				final String id = (String) obj.get("id");
313
				if (mdId.equals(id)) {
314
					obj.put("lastRead", new Date());
315
					return;
316
				}
317
			}
318
		}
319
		final BasicDBObject readStore = new BasicDBObject();
320
		readStore.put("id", mdId);
321
		readStore.put("lastRead", new Date());
322
		values.add(readStore);
323
	}
324

    
325
	/**
326
	 * Gets the manager table.
327
	 *
328
	 * @return the managerTable
329
	 */
330
	public MongoCollection<DBObject> getManagerTable() {
331
		return managerTable;
332
	}
333

    
334
	/**
335
	 * Sets the manager table.
336
	 *
337
	 * @param managerTable
338
	 *            the managerTable to set
339
	 */
340
	public void setManagerTable(final MongoCollection<DBObject> managerTable) {
341
		this.managerTable = managerTable;
342
	}
343

    
344
	/*
345
	 * (non-Javadoc)
346
	 *
347
	 * @see eu.dnetlib.data.mdstore.modular.connector.MDStoreTransactionManager#getInfoForCurrentMdStore(java.lang.String)
348
	 */
349
	@Override
350
	public MDStoreManagerInfo getInfoForCurrentMdStore(final String mdStoreId) throws MDStoreServiceException {
351
		verifyConsistency();
352
		final DBObject mdstoreInfo = getMDStoreAsDBObject(mdStoreId);
353
		if (mdstoreInfo == null) throw new MDStoreServiceException("Error, unable to find Mdstore with Id " + mdStoreId);
354
		final MDStoreManagerInfo result = new MDStoreManagerInfo();
355
		result.setCurrentId((String) mdstoreInfo.get("currentId"));
356
		result.setMdId((String) mdstoreInfo.get("mdId"));
357
		final BasicDBList values = (BasicDBList) mdstoreInfo.get("expiring");
358
		for (int i = 0; i < values.size(); i++) {
359
			final MDStoreExpiredInfo stillused = new MDStoreExpiredInfo();
360
			final DBObject value = (DBObject) values.get(i);
361
			stillused.setId((String) value.get("id"));
362
			stillused.setLastRead((Date) value.get("lastRead"));
363
			result.addExpiredItem(stillused);
364
		}
365
		final BasicDBList transactions = (BasicDBList) mdstoreInfo.get("transactions");
366
		if (transactions != null) {
367
			for (int i = 0; i < transactions.size(); i++) {
368
				final MDStoreTransactionInfo transaction = new MDStoreTransactionInfo();
369
				final DBObject value = (DBObject) transactions.get(i);
370
				final String transactionId = (String) value.get("id");
371
				transaction.setId(transactionId);
372
				transaction.setDate((Date) value.get("date"));
373
				transaction.setRefresh((Boolean) value.get("refresh"));
374
				transaction.setSize(db.getCollection(transactionId).count());
375
				result.addTransactionInfo(transaction);
376
			}
377
		}
378
		return result;
379
	}
380

    
381
	/*
382
	 * (non-Javadoc)
383
	 *
384
	 * @see eu.dnetlib.data.mdstore.modular.connector.MDStoreTransactionManager#dropUsed(java.lang.String, java.lang.String)
385
	 */
386
	@Override
387
	public Boolean dropUsed(final String mdId, final String idToDrop) throws MDStoreServiceException {
388
		verifyConsistency();
389
		final DBObject mdstoreInfo = getMDStoreAsDBObject(mdId);
390
		if (mdstoreInfo == null) throw new MDStoreServiceException("Error, unable to find Mdstore with Id " + mdId);
391
		return dropStore(mdstoreInfo, idToDrop, "expiring");
392
	}
393

    
394
	private boolean dropStore(DBObject mdstoreInfo, final String idToDrop, String transactionListName) throws MDStoreServiceException {
395
		final BasicDBList transactionList = (BasicDBList) mdstoreInfo.get(transactionListName);
396
		for (int i = 0; i < transactionList.size(); i++) {
397
			final DBObject value = (DBObject) transactionList.get(i);
398
			final String currentUsedId = (String) value.get("id");
399
			if (currentUsedId.equals(idToDrop)) {
400
				db.getCollection(idToDrop).drop();
401
				db.getCollection("discarded-" + idToDrop).drop();
402
				transactionList.remove(value);
403
				mdstoreInfo.put(transactionListName, transactionList);
404
				this.getManagerTable().findOneAndReplace(new BasicDBObject("_id", mdstoreInfo.get("_id")), mdstoreInfo);
405
				return true;
406
			}
407
		}
408
		throw new MDStoreServiceException("Error, unable to drop collection " + idToDrop);
409
	}
410

    
411
	/*
412
	 * (non-Javadoc)
413
	 *
414
	 * @see eu.dnetlib.data.mdstore.modular.connector.MDStoreTransactionManager#garbage()
415
	 */
416
	@Override
417
	public void garbage() throws MDStoreServiceException {
418
		verifyConsistency();
419
		log.info("Start garbage collection of MdStore");
420
		final FindIterable<DBObject> it = this.managerTable.find();
421
		int totalDeleted = 0;
422
		for (DBObject currentObject :  it){
423
			if (log.isDebugEnabled()) {
424
				log.debug("start to check id: " + currentObject.get("currentId"));
425
			}
426
			garbageExpiring(currentObject, (String) currentObject.get("currentId"));
427
			garbageTransactions(currentObject, (String) currentObject.get("currentId"));
428
			this.getManagerTable().findOneAndReplace(new BasicDBObject("_id", currentObject.get("_id")), currentObject);
429
		}
430

    
431
		// DELETING Collection that are not in the metadataManager table
432
		MongoIterable<String> collections = this.db.listCollectionNames();
433
		for (String collection : collections) {
434
			if ((collection.length() > 30) && (collection.contains("discarded-") == false)) {
435
				final DBObject item = getMetadataObjectForCollections(collection);
436

    
437
				if (shouldDelete(collection, item)) {
438
					if (log.isDebugEnabled()) {
439
						log.debug("delete collection: " + collection + " from mongo");
440
					}
441
					db.getCollection(collection).drop();
442
					db.getCollection("discarded-" + collection).drop();
443
					if (log.isDebugEnabled()) {
444
						log.debug("delete collection: discarded-" + collection + " from mongo");
445
					}
446
				}
447
			}
448
		}
449

    
450
		log.info("Complete garbage collection of MdStore, total store deleted: " + totalDeleted);
451
	}
452

    
453
	private DBObject getMetadataObjectForCollections(final String collectionName) {
454
		if (collectionName == null) return null;
455
		final String postfix = "_TURTdG9yZURTUmVzb3VyY2VzL01EU3RvcmVEU1Jlc291cmNlVHlwZQ==";
456
		final String tmp = collectionName.contains("discarded-") == true ? StringUtils.substringAfter(collectionName, "discarded-") : collectionName;
457
		final String collectionNameCleaned = StringUtils.substringBefore(tmp, "::") + postfix;
458

    
459
		//DBObject query = QueryBuilder.start("mdId").is(collectionNameCleaned).get();
460
		Bson query = Filters.eq("mdId", collectionNameCleaned);
461
		return this.managerTable.find(query).first();
462

    
463
	}
464

    
465
	private boolean shouldDelete(final String collectionName, final DBObject metadataManagerInstance) {
466
		log.debug("should delete instance "+metadataManagerInstance);
467
		if((metadataManagerInstance== null) || (metadataManagerInstance.get("currentId")== null)){
468
			log.debug("the instance has not currentID");
469
			return true;
470
		}
471
		String currentId = (String) metadataManagerInstance.get("currentId");
472
		if (collectionName.equals(currentId)) return false;
473
		BasicDBList expiringList = (BasicDBList) metadataManagerInstance.get("expiring");
474
		if (findInList(expiringList, collectionName, "id") == true) return false;
475
		BasicDBList transactionsList = (BasicDBList) metadataManagerInstance.get("transactions");
476
		return findInList(transactionsList, collectionName, "id") != true;
477
	}
478

    
479
	private boolean findInList(final BasicDBList list, final String object, final String tagname) {
480
		if (list == null) return false;
481
		for (int i = 0; i < list.size(); i++) {
482
			DBObject currentObject = (DBObject) list.get(i);
483
			final String id = (String) currentObject.get(tagname);
484
			if (id.equals(object)) return true;
485
		}
486
		return false;
487
	}
488

    
489
	/**
490
	 * Delete.
491
	 *
492
	 * @param list
493
	 *            the list
494
	 * @param toRemove
495
	 *            the to remove
496
	 */
497
	private void delete(final BasicDBList list, final List<DBObject> toRemove) {
498

    
499
		for (final DBObject obj : toRemove) {
500
			if (log.isDebugEnabled()) {
501
				log.debug("deleting " + obj);
502
			}
503
			list.remove(obj);
504
		}
505
	}
506

    
507
	/**
508
	 * Garbage transactions.
509
	 *
510
	 * @param currentObject
511
	 *            the current object
512
	 * @param currentId
513
	 *            the current id
514
	 */
515
	private void garbageTransactions(final DBObject currentObject, final String currentId) {
516
		if (log.isDebugEnabled()) {
517
			log.debug("Start garbage transactions ");
518
		}
519

    
520
		final BasicDBList expiring = (BasicDBList) currentObject.get("transactions");
521
		if ((expiring == null) || (expiring.size() <= getMaxTransactions())) return;
522

    
523
		List<DBObject> expiringList = Lists.newArrayList();
524

    
525
		for (int i = 0; i < expiring.size(); i++) {
526
			final DBObject cobj = (DBObject) expiring.get(i);
527
			if (cobj != null) {
528
				expiringList.add((DBObject) expiring.get(i));
529
			}
530

    
531
		}
532

    
533
		Collections.sort(expiringList, MDStoreUtils.getComparatorOnDate());
534

    
535
		List<DBObject> toRemove = Lists.newArrayList();
536
		int i = 0;
537

    
538
		// We should remove the k item less recent
539
		// where k = numberOftotalTransaction - maxNumberOfTransaction
540
		// k = numberOfItemToRemove
541

    
542
		while (((expiringList.size() - toRemove.size()) > getMaxTransactions()) || (i < expiringList.size())) {
543
			DBObject currentObj = expiringList.get(i++);
544
			String objectId = (String) currentObj.get("id");
545
			if (!objectId.equals(currentId)) {
546
				if (log.isDebugEnabled()) {
547
					log.debug("delete collection: " + objectId + " from mongo");
548
				}
549
				db.getCollection(objectId).drop();
550
				db.getCollection("discarded-" + objectId).drop();
551
				if (log.isDebugEnabled()) {
552
					log.debug("delete collection: discarded-" + objectId + " from mongo");
553
				}
554
				toRemove.add(currentObj);
555
			} else {
556
				if (log.isDebugEnabled()) {
557
					log.debug("Cannot remove transaction " + objectId + " because is the currentId: " + currentId);
558
				}
559
			}
560
		}
561

    
562
		delete(expiring, toRemove);
563
		log.info("Deleted " + toRemove.size() + " transactions, mdStore Id:" + currentObject.get("mdId"));
564
	}
565

    
566
	/**
567
	 * Garbage expiring.
568
	 *
569
	 * @param currentObject
570
	 *            the current object
571
	 * @param currentId
572
	 *            the current id
573
	 */
574
	private void garbageExpiring(final DBObject currentObject, final String currentId) {
575
		if (log.isDebugEnabled()) {
576
			log.debug("Start to search expiring mdstores for id: " + currentObject.get("mdId"));
577
		}
578
		final BasicDBList expiring = (BasicDBList) currentObject.get("expiring");
579
		final List<DBObject> toRemove = Lists.newArrayList();
580
		if (log.isDebugEnabled()) {
581
			if (expiring == null) {
582
				log.debug("expiring list is null");
583
			} else {
584
				log.debug("expiring list size is :" + expiring.size());
585
			}
586
		}
587
		if ((expiring == null) || (expiring.size() == 0)) {
588
			log.debug("Deleted  0  expired  collections, mdStore Id:" + currentObject.get("mdId"));
589
			return;
590
		}
591
		for (int i = 0; i < expiring.size(); i++) {
592
			final DBObject currentExpiredStore = (DBObject) expiring.get(i);
593
			final String currentUsedId = (String) currentExpiredStore.get("id");
594
			final Days d = getExpiringDays(currentExpiredStore, "lastRead");
595
			if (log.isDebugEnabled()) {
596
				log.debug("the store :" + currentId + " expired since " + d.getDays() + "days ");
597
			}
598
			// DELETE the collection where the last time they was read
599
			// is more than 3 days ago
600
			if (d.getDays() > getExpiredDays()) {
601
				if (currentUsedId.equals(currentId) == false) {
602
					db.getCollection(currentUsedId).drop();
603
					db.getCollection("discarded-" + currentUsedId).drop();
604
					log.debug("deleted collection " + currentUsedId);
605
				}
606
				toRemove.add(currentExpiredStore);
607
			}
608
		}
609
		delete(expiring, toRemove);
610
		log.debug("Deleted expired " + toRemove.size() + "collections, mdStore Id:" + currentObject.get("mdId"));
611
	}
612

    
613
	/**
614
	 * Gets the expiring days.
615
	 *
616
	 * @param value
617
	 *            the value
618
	 * @param paramName
619
	 *            the param name
620
	 * @return the expiring days
621
	 */
622
	private Days getExpiringDays(final DBObject value, final String paramName) {
623
		final Date lastRead = (Date) value.get(paramName);
624
		final DateTime last = new DateTime(lastRead);
625
		final DateTime today = new DateTime();
626
		final Days d = Days.daysBetween(last, today);
627
		return d;
628
	}
629

    
630
	/**
631
	 * Gets the expired days.
632
	 *
633
	 * @return the expiredDays
634
	 */
635
	public int getExpiredDays() {
636
		if (this.expiredDays == 0) return 3;
637
		return expiredDays;
638
	}
639

    
640
	/**
641
	 * Sets the expired days.
642
	 *
643
	 * @param expiredDays
644
	 *            the expiredDays to set
645
	 */
646
	public void setExpiredDays(final int expiredDays) {
647
		this.expiredDays = expiredDays;
648
	}
649

    
650
	/**
651
	 * Update incremental.
652
	 *
653
	 * @param transactionId
654
	 *            the transaction id
655
	 * @param currentId
656
	 *            the current id
657
	 */
658
	private void updateIncremental(final String transactionId, final String currentId) {
659
		final MongoCollection<DBObject> transaction = db.getCollection(transactionId, DBObject.class);
660
		final MongoCollection<DBObject> mdstore = db.getCollection(currentId, DBObject.class);
661
		final FindIterable<DBObject> it = transaction.find();
662
		for (DBObject currentObj : it){
663

    
664
			BasicDBObject newObj = new BasicDBObject();
665

    
666
			final String id = (String) currentObj.get("id");
667
			final String body = (String) currentObj.get("body");
668
			newObj.put("id", id);
669
			newObj.put("body", body);
670
			if (StringUtils.isNotBlank(id)) {
671
				final MongoCollection<DBObject> mdstoreWrite = mdstore.withWriteConcern(WriteConcern.ACKNOWLEDGED);
672
				mdstoreWrite.replaceOne(new BasicDBObject("id", id), newObj, new UpdateOptions().upsert(true));
673

    
674
			}
675
		}
676
		getDb().runCommand(new BasicDBObject("fsync",1));
677
	}
678

    
679
	/*
680
	 * (non-Javadoc)
681
	 *
682
	 * @see eu.dnetlib.data.mdstore.modular.connector.MDStoreTransactionManager#dropTransaction(java.lang.String, java.lang.String)
683
	 */
684
	@Override
685
	public Boolean dropTransaction(final String mdId, final String idToDrop) throws MDStoreServiceException {
686
		verifyConsistency();
687
		final DBObject mdstoreInfo = getMDStoreAsDBObject(mdId);
688
		if (mdstoreInfo == null) throw new MDStoreServiceException("Error, unable to find Mdstore with Id " + mdId);
689
		return dropStore(mdstoreInfo, idToDrop, "transactions");
690
	}
691

    
692
	public void garbageTransactionsOnStart() throws MDStoreServiceException {
693
		verifyConsistency();
694
		FindIterable<DBObject> it = this.managerTable.find();
695
		for (DBObject currentObject : it){
696
			final BasicDBList transactions = (BasicDBList) currentObject.get("transactions");
697
			if ((transactions != null) && (transactions.size() > 0)) {
698
				for (int i = 0; i < transactions.size(); i++) {
699
					final DBObject currentTransactions = (DBObject) transactions.get(i);
700
					final String id = (String) currentTransactions.get("id");
701
					db.getCollection(id).drop();
702
					db.getCollection("discarded-" + id).drop();
703
					log.debug("deleted collection " + id);
704
				}
705
				currentObject.put("transactions", new BasicDBList());
706
				this.getManagerTable().findOneAndReplace(new BasicDBObject("_id", currentObject.get("_id")), currentObject);
707
			}
708
		}
709
	}
710

    
711
	/**
712
	 * Gets the max transactions.
713
	 *
714
	 * @return the maxTransactions
715
	 */
716
	public int getMaxTransactions() {
717
		return maxTransactions;
718
	}
719

    
720
	/**
721
	 * Sets the max transactions.
722
	 *
723
	 * @param maxTransactions
724
	 *            the maxTransactions to set
725
	 */
726
	public void setMaxTransactions(final int maxTransactions) {
727
		this.maxTransactions = maxTransactions;
728
	}
729
}
(2-2/5)