/*
* Copyright 2009-2016 Tilmann Zaeschke. All rights reserved.
*
* This file is part of ZooDB.
*
* ZooDB is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* ZooDB is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with ZooDB. If not, see <http://www.gnu.org/licenses/>.
*
* See the README and COPYING files for further information.
*/
package org.zoodb.internal.model1p;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import org.zoodb.api.impl.ZooPC;
import org.zoodb.internal.DataDeleteSink;
import org.zoodb.internal.DataSink;
import org.zoodb.internal.GenericObject;
import org.zoodb.internal.Node;
import org.zoodb.internal.OidBuffer;
import org.zoodb.internal.Session;
import org.zoodb.internal.ZooClassDef;
import org.zoodb.internal.ZooClassProxy;
import org.zoodb.internal.ZooFieldDef;
import org.zoodb.internal.ZooHandleImpl;
import org.zoodb.internal.client.SchemaManager;
import org.zoodb.internal.client.session.ClientSessionCache;
import org.zoodb.internal.server.DiskAccess;
import org.zoodb.internal.server.OptimisticTransactionResult;
import org.zoodb.internal.server.ServerResponse;
import org.zoodb.internal.server.SessionFactory;
import org.zoodb.internal.server.TxObjInfo;
import org.zoodb.internal.server.index.PagedOidIndex;
import org.zoodb.internal.server.index.SchemaIndex.SchemaIndexEntry;
import org.zoodb.internal.util.CloseableIterator;
import org.zoodb.internal.util.DBLogger;
import org.zoodb.internal.util.Util;
import org.zoodb.tools.DBStatistics.STATS;
/**
* 1P (1-process) implementation of the Node interface. 1P means that client and server run
* in the same process, therefore no inter-process communication is required and the Node1P
* implementation can implement direct communication between client (JDO) and database.
*
* @author Tilmann Zaeschke
*/
public class Node1P extends Node {
private final OidBuffer oidBuffer;
private DiskAccess disk;
private final Session session;
public Node1P(String dbPath, Session session) {
super(dbPath);
this.oidBuffer = new OidBuffer1P(this);
this.session = session;
}
@Override
public void connect() {
ClientSessionCache commonCache = session.internalGetCache();
disk = SessionFactory.getSession(this, commonCache);
//load all schema data
Collection<ZooClassDef> defs = disk.readSchemaAll();
for (ZooClassDef def: defs) {
def.associateJavaTypes();
if (def.getJavaClass() == ZooClassDef.class) {
def.initProvidedContext(commonCache.getSession(), this);
commonCache.setRootSchema(def);
}
}
//more bootstrapping for brand new databases: enforce writing of root schemata
if (defs.size()==2) {
for (ZooClassDef def: defs) {
commonCache.addSchema(def, false, this);
}
} else {
for (ZooClassDef def: defs) {
commonCache.addSchema(def, true, this);
}
}
//To drop all locks
disk.rollbackTransaction();
}
@Override
public OidBuffer getOidBuffer() {
return oidBuffer;
}
/**
* Only used by OidBuffer.
* @return DiskAccess instance.
*/
DiskAccess getDiskAccess() {
return disk;
}
@Override
public long beginTransaction() {
return disk.beginTransaction();
}
@Override
public OptimisticTransactionResult rollbackTransaction() {
return disk.rollbackTransaction();
}
@Override
public void commit() {
disk.commit();
}
@Override
public OptimisticTransactionResult checkTxConsistency(ArrayList<TxObjInfo> updates) {
return disk.checkTxConsistency(updates);
}
@Override
public void revert() {
disk.revert();
}
@Override
public CloseableIterator<ZooPC> loadAllInstances(ZooClassProxy def,
boolean loadFromCache) {
return disk.readAllObjects(def.getSchemaId(), loadFromCache);
}
@Override
public CloseableIterator<ZooHandleImpl> oidIterator(ZooClassProxy px, boolean subClasses) {
return disk.oidIterator(px, subClasses);
}
@Override
public ZooPC loadInstanceById(long oid) {
ZooPC pc = disk.readObject(oid);
//put into local cache (?) -> is currently done in deserializer
return pc;
}
@Override
public void refreshObject(ZooPC pc) {
if (pc.jdoZooIsNew() || (!pc.jdoZooIsStateHollow() && !pc.jdoZooIsTransactional())) {
//ignore non-persistent objects
return;
}
if (pc.jdoZooIsDeleted()) {
//deleted objects remain unchanged (!) --> see spec.
return;
}
ServerResponse r = disk.readObject(pc);
if (r.result() == ServerResponse.RESULT.OBJECT_NOT_FOUND) {
//must have been deleted
//We mark it as deleted/transient to allow follow-up commits() to go through.
//'Transient' is the JDO-spec state of a deleted object after commit()
//if (!pc.jdoZooIsDeleted() || pc.jdoZooIsPersistent()) {
pc.jdoZooMarkClean();
pc.jdoZooEvict();
session.makeTransient(pc);
//}
throw DBLogger.newObjectNotFoundException(
"Object not found: " + Util.getOidAsString(pc), null, pc);
}
}
@Override
public void refreshSchema(ZooClassDef def) {
disk.refreshSchema(def);
}
@Override
public final void makePersistent(ZooPC obj) {
ClientSessionCache commonCache = session.internalGetCache();
ZooClassDef cs;
if (obj.getClass() != GenericObject.class) {
cs = commonCache.getSchema(obj.getClass(), this);
if (cs == null || cs.jdoZooIsDeleted()) {
SchemaManager sm = session.getSchemaManager();
if (sm.getAutoCreateSchema()) {
cs = sm.createSchema(this, obj.getClass()).getSchemaDef();
} else {
throw DBLogger.newUser("No schema found for object: " + obj.getClass().getName());
}
}
} else {
cs = ((GenericObject)obj).jdoZooGetClassDef();
}
//allocate OID
long oid = getOidBuffer().allocateOid();
//add to cache
commonCache.markPersistent(obj, oid, this, cs);
}
@Override
public void closeConnection() {
disk.close();
}
@Override
public void defineIndex(ZooClassDef def, ZooFieldDef field, boolean isUnique) {
disk.defineIndex(def, field, isUnique);
}
@Override
public boolean removeIndex(ZooClassDef def, ZooFieldDef field) {
return disk.removeIndex(def, field);
}
@Override
public Iterator<ZooPC> readObjectFromIndex( ZooFieldDef field,
long minValue, long maxValue, boolean loadFromCache) {
return disk.readObjectFromIndex(field, minValue, maxValue, loadFromCache);
}
@Override
public long getStats(STATS stats) {
return disk.getStats(stats);
}
@Override
public String checkDb() {
return disk.checkDb();
}
@Override
public void dropInstances(ZooClassProxy def) {
disk.dropInstances(def);
}
@Override
public void defineSchema(ZooClassDef def) {
disk.defineSchema(def);
}
@Override
public void newSchemaVersion(ZooClassDef defNew) {
disk.newSchemaVersion(defNew);
}
@Override
public void renameSchema(ZooClassDef def, String newName) {
disk.renameSchema(def, newName);
}
@Override
public void undefineSchema(ZooClassProxy def) {
disk.undefineSchema(def);
}
@Override
public long getSchemaForObject(long oid) {
return disk.getObjectClass(oid);
}
public SchemaIndexEntry getSchemaIE(ZooClassDef def) {
return disk.getSchemaIE(def);
}
@Override
public DataSink createDataSink(ZooClassDef clsDef) {
return new DataSink1P(this, session.internalGetCache(), clsDef, disk.getWriter(clsDef));
}
@Override
public DataDeleteSink createDataDeleteSink(ZooClassDef clsDef) {
PagedOidIndex oidIndex = disk.getOidIndex();
return new DataDeleteSink1P(this, clsDef, oidIndex);
}
@Override
public Session getSession() {
return session;
}
@Override
public long countInstances(ZooClassProxy clsDef, boolean subClasses) {
return disk.countInstances(clsDef, subClasses);
}
@Override
public GenericObject readGenericObject(ZooClassDef def, long oid) {
return disk.readGenericObject(def, oid);
}
@Override
public boolean checkIfObjectExists(long oid) {
return disk.checkIfObjectExists(oid);
}
@Override
public OptimisticTransactionResult beginCommit(ArrayList<TxObjInfo> updates) {
return disk.beginCommit(updates);
}
}