Dépôt officiel du code source de l'ERP OpenConcerto
Blame | Last modification | View Log | RSS feed
/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
*
* Copyright 2011-2019 OpenConcerto, by ILM Informatique. All rights reserved.
*
* The contents of this file are subject to the terms of the GNU General Public License Version 3
* only ("GPL"). You may not use this file except in compliance with the License. You can obtain a
* copy of the License at http://www.gnu.org/licenses/gpl-3.0.html See the License for the specific
* language governing permissions and limitations under the License.
*
* When distributing the software, include this License Header Notice in each file.
*/
package org.openconcerto.sql.view;
import org.openconcerto.sql.Log;
import org.openconcerto.sql.model.RowRef;
import org.openconcerto.sql.model.SQLField;
import org.openconcerto.sql.model.SQLRowAccessor;
import org.openconcerto.sql.model.SQLRowListRSH;
import org.openconcerto.sql.model.SQLSelect;
import org.openconcerto.sql.model.SQLTable;
import org.openconcerto.sql.model.Where;
import org.openconcerto.sql.request.SQLCache;
import org.openconcerto.utils.RTInterruptedException;
import org.openconcerto.utils.ThreadFactory;
import org.openconcerto.utils.cache.CacheResult;
import java.util.Collections;
import java.util.Date;
import java.util.Set;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.logging.Level;
public final class RowMetadataCache {
private static RowMetadata createMD(final SQLRowAccessor r, final SQLField creation, final SQLField userCreate, final SQLField modification, final SQLField userModify) {
return new RowMetadata(getDateMD(r, creation), getForeignIntegerMD(r, userCreate), getDateMD(r, modification), getForeignIntegerMD(r, userModify));
}
private static Date getDateMD(final SQLRowAccessor row, final SQLField f) {
return f == null ? null : row.getObjectAs(f.getName(), Date.class);
}
private static Integer getForeignIntegerMD(final SQLRowAccessor row, final SQLField f) {
if (f == null)
return null;
final Number n = row.getNonEmptyForeignIDNumber(f.getName());
return n == null ? null : n.intValue();
}
private final SQLCache<RowRef, RowMetadata> cache;
private final ExecutorService exec;
public RowMetadataCache(final int timeoutInSeconds, final int maxCount, final String name) {
this.cache = new SQLCache<>(timeoutInSeconds, maxCount, "Cache of metadata for " + name);
this.exec = Executors.newSingleThreadExecutor(new ThreadFactory("Metadata cache thread for " + name, true));
}
public final RowMetadata get(final RowRef ref) {
final CacheResult<RowMetadata> cacheRes = this.cache.get(ref);
if (cacheRes.getState() == CacheResult.State.INTERRUPTED) {
// shouldn't happen since we don't use check()/removeRunning()
throw new RTInterruptedException("interrupted while waiting for the cache");
} else if (cacheRes.getState() == CacheResult.State.VALID) {
final RowMetadata res = cacheRes.getRes();
assert res != null : "Null ambiguity";
return res;
} else {
return null;
}
}
public final void fetch(final RowRef ref, final Set<Number> withAdditionalIDs) {
this.exec.submit(() -> {
final CacheResult<RowMetadata> cacheResult = this.cache.get(ref);
if (cacheResult.getState() == CacheResult.State.VALID)
return;
final SQLTable table = ref.getTable();
final SQLField creationDateField = table.getCreationDateField();
final SQLField creationUserField = table.getCreationUserField();
final SQLField modifDateField = table.getModifDateField();
final SQLField modifUserField = table.getModifUserField();
final SQLSelect sel = new SQLSelect();
sel.addAllSelect(table.getPrimaryKeyFields());
sel.addAllSelect(creationDateField, creationUserField, modifDateField, modifUserField);
sel.setWhere(Where.inValues(table.getKey(), withAdditionalIDs));
final Set<SQLTable> data = Collections.singleton(table);
// wait :
// 1. check errors
// 2. avoid fetching the same IDs more than once
try {
for (final SQLRowAccessor v : SQLRowListRSH.execute(sel)) {
this.cache.put(v.getRowRef(), createMD(v, creationDateField, creationUserField, modifDateField, modifUserField), data);
}
} catch (Exception exn) {
Log.get().log(Level.WARNING, "Couldn't fetch metadata for " + ref, exn);
}
});
}
}