001: /*
002: * Copyright (c) 1998 - 2005 Versant Corporation
003: * All rights reserved. This program and the accompanying materials
004: * are made available under the terms of the Eclipse Public License v1.0
005: * which accompanies this distribution, and is available at
006: * http://www.eclipse.org/legal/epl-v10.html
007: *
008: * Contributors:
009: * Versant Corporation - initial API and implementation
010: */
011: package com.versant.core.storagemanager;
012:
013: import com.versant.core.common.State;
014: import com.versant.core.server.CompiledQuery;
015: import com.versant.core.jdo.QueryDetails;
016: import com.versant.core.jdo.VersantQueryPlan;
017: import com.versant.core.metadata.ClassMetaData;
018: import com.versant.core.metadata.FetchGroup;
019: import com.versant.core.metadata.FieldMetaData;
020: import com.versant.core.common.OID;
021: import com.versant.core.common.OIDArray;
022: import com.versant.core.common.*;
023:
024: import java.util.Map;
025:
026: /**
027: * This keeps track of server side transaction and other information for a
028: * application level session (e.g. a PersistenceManager for JDO) and provides
029: * persistence services for {@link State} instances.
030: *
031: * These methods are designed to be used from an application API layer
032: * (e.g. JDO PersistenceManager) that may be in a different tier.
033: *
034: * All calls from the application API layer go through this interface. For
035: * example there are methods to return results from queries that could have
036: * been implemented via a separate "server side query result" interface.
037: *
038: * The query related methods need a lot more refactoring but one thing at
039: * a time ...
040: */
041: public interface StorageManager {
042:
043: /** Release the datastore connection as quickly as possible. */
044: public static final int CON_POLICY_RELEASE = 1;
045: /** Pin the datastore connection for the duration of the tx. */
046: public static final int CON_POLICY_PIN_FOR_TX = 2;
047: /** Pin the datastore connection indefinitely (even between tx's). */
048: public static final int CON_POLICY_PIN = 3;
049:
050: /** Do not lock any objects in datastore tx. */
051: public static final int LOCK_POLICY_NONE = 1;
052: /** Lock only the first object navigated or fetched in datastore tx. */
053: public static final int LOCK_POLICY_FIRST = 2;
054: /** Lock all objects in datastore tx. */
055: public static final int LOCK_POLICY_ALL = 3;
056:
057: /** Send changes to the datastore and do not commit. */
058: public static final int STORE_OPTION_FLUSH = 1;
059: /** Call prepareForCommit after store. */
060: public static final int STORE_OPTION_PREPARE = 2;
061: /** Call commit after store. */
062: public static final int STORE_OPTION_COMMIT = 3;
063:
064: public static final int EVENT_ERRORS = 1;
065: public static final int EVENT_NORMAL = 2;
066: public static final int EVENT_VERBOSE = 3;
067: public static final int EVENT_ALL = 4;
068:
069: /**
070: * Begin a tx using the optimistic or datastore transation model.
071: */
072: public void begin(boolean optimistic);
073:
074: /**
075: * Commit the tx. Note that non-XA transactions can call {@link #store}
076: * with {@link #STORE_OPTION_COMMIT} to commit instead of having to
077: * also call this method. XA transactions should use the
078: * {@link #STORE_OPTION_PREPARE} and call this method later. Normal
079: * transactions might still call this method if they have no changes or
080: * have already used {@link #STORE_OPTION_FLUSH} to flush changes.
081: */
082: public void commit();
083:
084: /**
085: * Rollback a tx.
086: */
087: public void rollback();
088:
089: /**
090: * Control pinning of datastore connections. Note that the datastore
091: * may ignore these options.
092: *
093: * @see #CON_POLICY_RELEASE
094: * @see #CON_POLICY_PIN_FOR_TX
095: * @see #CON_POLICY_PIN
096: */
097: public void setConnectionPolicy(int policy);
098:
099: /**
100: * Control locking of objects in datastore transactions. Note that the
101: * datastore may ignore this options.
102: *
103: * @see #LOCK_POLICY_NONE
104: * @see #LOCK_POLICY_FIRST
105: * @see #LOCK_POLICY_ALL
106: */
107: public void setLockingPolicy(int policy);
108:
109: /**
110: * Get the locking policy.
111: */
112: public int getLockingPolicy();
113:
114: /**
115: * Get the State for an OID.
116: *
117: * @param triggerField The field that triggered the fetch or null if
118: */
119: public StatesReturned fetch(ApplicationContext context, OID oid,
120: State current, FetchGroup fetchGroup,
121: FieldMetaData triggerField);
122:
123: /**
124: * Get the States for a batch of OIDs. The default fetch group is fetched
125: * for each OID.
126: *
127: * @param triggerField The field that triggered the fetch or null if
128: */
129: public StatesReturned fetch(ApplicationContext context,
130: OIDArray oids, FieldMetaData triggerField);
131:
132: /**
133: * Persist a graph of State's (insert, update and delete). For some states
134: * persisting them will change some of their fields (e.g. autoset fields)
135: * and the new values of these fields must be returned if
136: * returnFieldsUpdatedBySM is true.
137: *
138: * @param returnFieldsUpdatedBySM Return States containing any fields
139: * updated by us (i.e. instead of using the value in the incoming
140: * State, if any) in returned.
141: * @param storeOption Option to prepare or commit the tx after the store
142: * operation ({@link #STORE_OPTION_PREPARE},
143: * {@link #STORE_OPTION_COMMIT}, {@link #STORE_OPTION_FLUSH}).
144: * @param evictClasses If this is true then classes with instances
145: * modified in the transaction are evicted instead of the instances
146: */
147: public StatesReturned store(StatesToStore toStore,
148: DeletePacket toDelete, boolean returnFieldsUpdatedBySM,
149: int storeOption, boolean evictClasses);
150:
151: /**
152: * Create a real OID for a new instance. This is called prior to commit
153: * when the real OID is required. If it is not possible to create the
154: * OID (e.g. an IDENTITY column in JDBC) then an exception must be
155: * thrown. For these classes a flush must be done instead.
156: */
157: public OID createOID(ClassMetaData cmd);
158:
159: /**
160: * Compile a query into a form for the datastore (e.g. generate the SQL
161: * for JDBC).
162: */
163: public CompiledQuery compileQuery(QueryDetails query);
164:
165: /**
166: * Execute a query. If compiledQuery is not null then query is ignored
167: * and may be null. If compiledQuery is null then query is used to compile
168: * the query. The compiledQuery is accessable through the returned
169: * ExecuteQueryReturn instance for reuse in future calls.
170: */
171: public ExecuteQueryReturn executeQuery(ApplicationContext context,
172: QueryDetails query, CompiledQuery compiledQuery,
173: Object[] params);
174:
175: /**
176: * Prepare and execute the query, returning all results in the supplied
177: * container.
178: */
179: public QueryResultContainer executeQueryAll(
180: ApplicationContext context, QueryDetails query,
181: CompiledQuery compiledQuery, Object[] params);
182:
183: /**
184: * Prepare and execute the query and return the number of results
185: * using count(*) or something similar.
186: */
187: public int executeQueryCount(QueryDetails query,
188: CompiledQuery compiledQuery, Object[] params);
189:
190: /**
191: * Get the datastore specific query plan for the query (e.g. the SQL
192: * and database plan for JDBC).
193: */
194: public VersantQueryPlan getQueryPlan(QueryDetails query,
195: CompiledQuery compiledQuery, Object[] params);
196:
197: /**
198: * Return the next batch of results for the query.
199: */
200: public QueryResultContainer fetchNextQueryResult(
201: ApplicationContext context, RunningQuery runningQuery,
202: int skipAmount);
203:
204: /**
205: * This is used by random access queries to return absolute results.
206: */
207: public QueryResultContainer fetchRandomAccessQueryResult(
208: ApplicationContext context, RunningQuery runningQuery,
209: int index, int fetchAmount);
210:
211: /**
212: * This is used by random access queries to return the number of results.
213: */
214: public int getRandomAccessQueryCount(ApplicationContext context,
215: RunningQuery runningQuery);
216:
217: /**
218: * Close the query.
219: */
220: public void closeQuery(RunningQuery runningQuery);
221:
222: /**
223: * Get the underlying datastore connection. If no connection is associated
224: * with this StorageManager then one is allocated and pinned. The returned
225: * object must be a proxy for the real connection that is returned when
226: * its "close" method is called.
227: */
228: public Object getDatastoreConnection();
229:
230: /**
231: * Does the datastore require notification before an object becomes dirty
232: * or deleted for the first time in the tx?
233: *
234: * @see #notifyDirty(com.versant.core.common.OID)
235: */
236: public boolean isNotifyDirty();
237:
238: /**
239: * The object for the oid is about to become dirty or deleted.
240: *
241: * @see #isNotifyDirty()
242: */
243: public void notifyDirty(OID oid);
244:
245: /**
246: * Restore to an initial inactive state.
247: */
248: public void reset();
249:
250: /**
251: * Destroy cleaning up all resources. No methods should be invoked on a
252: * destroyed StorageManager but the StorageManager is not required to
253: * enforce this.
254: */
255: public void destroy();
256:
257: /**
258: * Log an event to our event log.
259: */
260: public void logEvent(int level, String description, int ms);
261:
262: /**
263: * If we are decorating another SM then return it. Otherwise return null.
264: */
265: public StorageManager getInnerStorageManager();
266:
267: /**
268: * Are we holding a datastore connection?
269: */
270: public boolean hasDatastoreConnection();
271:
272: /**
273: * Get internal status information in the form of property -> value pairs.
274: */
275: public Map getStatus();
276:
277: /**
278: * Set a userObject on this SM.
279: */
280: public void setUserObject(Object o);
281: }
|