Author: michiel Date: 2009-09-23 17:49:04 +0200 (Wed, 23 Sep 2009) New Revision: 38812
Modified: mmbase/trunk/core/src/main/java/org/mmbase/storage/implementation/database/DatabaseStorageManager.java Log: added a bit of checks and synchronization, which in some multithreaded situations seem to help quite a bit Modified: mmbase/trunk/core/src/main/java/org/mmbase/storage/implementation/database/DatabaseStorageManager.java =================================================================== --- mmbase/trunk/core/src/main/java/org/mmbase/storage/implementation/database/DatabaseStorageManager.java 2009-09-23 14:02:12 UTC (rev 38811) +++ mmbase/trunk/core/src/main/java/org/mmbase/storage/implementation/database/DatabaseStorageManager.java 2009-09-23 15:49:04 UTC (rev 38812) @@ -962,7 +962,7 @@ } - private int createWithoutEvent(MMObjectNode node) throws StorageException { + private int createWithoutEvent(final MMObjectNode node) throws StorageException { // assign a new number if the node has not yet been assigned one int nodeNumber = node.getNumber(); if (nodeNumber == -1) { @@ -1059,7 +1059,10 @@ String query = scheme.format(this, tablename, fieldNames.toString(), fieldValues.toString()); try { getActiveConnection(); - executeUpdateCheckConnection(query, node, fields); + int result = executeUpdateCheckConnection(query, node, fields); + if (result != 1) { + throw new StorageException("Insert node " + node + " in " + tablename + " " + query + ": " + result); + } } catch (SQLException se) { throw new StorageException(se.getMessage() + " during creation of " + UNICODE_ESCAPER.transform(node.toString()) + " using query " + query, se); } finally { @@ -1088,9 +1091,9 @@ * @throws SQLException If something wrong with the query, or the database is down or could not be contacted. * @since MMBase-1.7.1 */ - protected void executeUpdateCheckConnection(String query, MMObjectNode node, List<CoreField> fields) throws SQLException { + protected int executeUpdateCheckConnection(String query, MMObjectNode node, List<CoreField> fields) throws SQLException { try { - executeUpdate(query, node, fields); + return executeUpdate(query, node, fields); } catch (SQLException sqe) { while (true) { Statement s = null; @@ -1118,7 +1121,7 @@ } break; } - executeUpdate(query, node, fields); + return executeUpdate(query, node, fields); } } @@ -1133,7 +1136,7 @@ * * @since MMBase-1.7.1 */ - protected void executeUpdate(String query, MMObjectNode node, List<CoreField> fields) throws SQLException { + protected int executeUpdate(String query, MMObjectNode node, List<CoreField> fields) throws SQLException { PreparedStatement ps = activeConnection.prepareStatement(query); for (int fieldNumber = 0; fieldNumber < fields.size(); fieldNumber++) { CoreField field = fields.get(fieldNumber); @@ -1146,7 +1149,7 @@ } } long startTime = getLogStartTime(); - ps.executeUpdate(); + int result = ps.executeUpdate(); ps.close(); boolean logged = logQuery(query, startTime); if (logged) { @@ -1157,43 +1160,56 @@ } valuesLogger.info(values); } + return result; } // javadoc is inherited - public void change(MMObjectNode node) throws StorageException { - // resolve aliases, if any. - MMObjectBuilder builder = node.getBuilder(); - for (CoreField field: builder.getFields()) { - if (field.getName().equals(MMObjectBuilder.FIELD_NUMBER)) continue; - if (field.getName().equals(MMObjectBuilder.FIELD_OBJECT_TYPE)) continue; - if (field.getType() == Field.TYPE_NODE) { - Object value = node.getValue(field.getName()); - if (value instanceof String) { - node.setValue(field.getName(), builder.getNode((String)value)); + public void change(final MMObjectNode node) throws StorageException { + synchronized(node) { + // resolve aliases, if any. + MMObjectBuilder builder = node.getBuilder(); + for (CoreField field: builder.getFields()) { + if (field.getName().equals(MMObjectBuilder.FIELD_NUMBER)) continue; + if (field.getName().equals(MMObjectBuilder.FIELD_OBJECT_TYPE)) continue; + if (field.getType() == Field.TYPE_NODE) { + Object value = node.getValue(field.getName()); + if (value instanceof String) { + node.setValue(field.getName(), builder.getNode((String)value)); + } } } - } - // precommit call, needed to convert or add things before a save - // Should be done in MMObjectBuilder - builder.preCommit(node); - change(node, builder); - commitChange(node, "c"); - unloadShortedFields(node, builder); - // the node instance can be wrapped by other objects (org.mmbase.bridge.implementation.BasicNode) or otherwise still in use. - // this make sure that the values are realistic reflections of the database: - // This can change after a commit e.g. if the database enforces a maximum length for certain - // fields. - try { - refresh(node); - } catch (org.mmbase.storage.StorageNotFoundException se) { - log.warn("node " + node + " : " + se.getMessage(), se); - log.debug("Changed node " + node + " probably does not exist any more, but since we had to change it, we'll have to recreate it."); - log.service("Recreating node " + node.getNumber()); - if(node.getNumber() > 0) { - create(node, builder); - } else { - log.warn("Cannot recreate node without number"); + // precommit call, needed to convert or add things before a save + // Should be done in MMObjectBuilder + builder.preCommit(node); + change(node, builder); + commitChange(node, "c"); + unloadShortedFields(node, builder); + // the node instance can be wrapped by other objects (org.mmbase.bridge.implementation.BasicNode) or otherwise still in use. + // this make sure that the values are realistic reflections of the database: + // This can change after a commit e.g. if the database enforces a maximum length for certain + // fields. + if(node.getNumber() < 0) { + throw new RuntimeException(" " + node); } + try { + refresh(node); + } catch (StorageNotFoundException se) { + if(node.getNumber() > 0) { + // Check whether node realy, realy doesn't exist + MMObjectBuilder buil = node.getBuilder().getMMBase().getBuilder("object"); + try { + MMObjectNode o = getNode(buil, node.getNumber()); + log.warn("Node _does_ exist (but" + se + ")"); + } catch (StorageNotFoundException se2) { + log.debug("Changed node " + node + " probably does not exist any more, but since we had to change it, we'll have to recreate it."); + log.service("Recreating node " + node.getNumber()); + + create(node, builder); + } + } else { + log.warn("Cannot recreate node without number"); + } + } } } @@ -1708,63 +1724,71 @@ } - protected void setNodeTypeLeaveRelations(MMObjectNode node, MMObjectBuilder buil) throws StorageException { + protected void setNodeTypeLeaveRelations(final MMObjectNode node, final MMObjectBuilder buil) throws StorageException { - assert node.getIntValue("otype") > 0; - assert node.getNumber() > 0; + synchronized(node) { + assert node.getIntValue("otype") > 0; + assert node.getNumber() > 0; - MMObjectBuilder oldBuilder = node.getOldBuilder(); - // delete from database but do not delete blobs on disk - /* + MMObjectBuilder oldBuilder = node.getOldBuilder(); + if (oldBuilder != null) { + // delete from database but do not delete blobs on disk + /* - String tablename = (String) factory.getStorageIdentifier(oldBuilder); - delete(node, oldBuilder, new ArrayList<CoreField>(), tablename); - */ - delete(node, oldBuilder); + String tablename = (String) factory.getStorageIdentifier(oldBuilder); + delete(node, oldBuilder, new ArrayList<CoreField>(), tablename); + */ + delete(node, oldBuilder); - assert node.getIntValue("otype") > 0; + assert node.getIntValue("otype") > 0; - typeCache.remove(node.getNumber()); + typeCache.remove(node.getNumber()); - log.service("Recreating " + node + " " + (oldBuilder == null ? "NULL" : oldBuilder.getTableName()) + " -> " + buil.getTableName()); - createWithoutEvent(node); + log.service("Recreating " + node + " " + (oldBuilder == null ? "NULL" : oldBuilder.getTableName()) + " -> " + buil.getTableName()); + createWithoutEvent(node); + } else { + log.service("Called setNodeType for nothing (done by other thread?)"); + } + } } - public int setNodeType(MMObjectNode node, MMObjectBuilder bul) throws StorageException { + public int setNodeType(final MMObjectNode node, MMObjectBuilder bul) throws StorageException { + synchronized(node) { - boolean wasinTransaction = inTransaction; - try { + boolean wasinTransaction = inTransaction; + try { - getActiveConnection(); - if (! inTransaction) { - beginTransaction(); - } + getActiveConnection(); + if (! inTransaction) { + beginTransaction(); + } - setNodeTypeLeaveRelations(node, bul); - commitChange(node, "dn"); + setNodeTypeLeaveRelations(node, bul); + commitChange(node, "dn"); - Enumeration<MMObjectNode> en = node.getRelations(); - if (en != null) { - for (MMObjectNode r : Collections.list(en)) { - commitChange(r, "dn"); + Enumeration<MMObjectNode> en = node.getRelations(); + if (en != null) { + for (MMObjectNode r : Collections.list(en)) { + commitChange(r, "dn"); + } } + if (! wasinTransaction) { + commit(); + } + // nothing wrong. + return bul.getNumber(); + } catch (SQLException sqe) { + log.warn(sqe); + if (! wasinTransaction) { + rollback(); + } + throw new StorageException(sqe); + } finally { + releaseActiveConnection(); } - if (! wasinTransaction) { - commit(); - } - // nothing wrong. - return bul.getNumber(); - } catch (SQLException sqe) { - log.warn(sqe); - if (! wasinTransaction) { - rollback(); - } - throw new StorageException(sqe); - } finally { - releaseActiveConnection(); } } @@ -1807,9 +1831,11 @@ PreparedStatement s = null; try { s = activeConnection.prepareStatement(query); - s.executeUpdate(); - } - finally { + int result = s.executeUpdate(); + if (result != 1) { + throw new StorageException("Deleting of " + node + " from " + tablename + " " + query + ":" + result); + } + } finally { if (s != null) { s.close(); } @@ -2250,9 +2276,11 @@ PreparedStatement s = null; try { s = activeConnection.prepareStatement(query); - s.executeUpdate(); - } - finally { + int result = s.executeUpdate(); + if (result != 1) { + throw new StorageException("" + query + " result: " + result); + } + } finally { if (s != null) { s.close(); } @@ -2457,7 +2485,7 @@ } } } catch (Exception e) { - throw new StorageException(e.getMessage()); + throw new StorageException(e.getMessage(), e); } finally { releaseActiveConnection(); } _______________________________________________ Cvs mailing list Cvs@lists.mmbase.org http://lists.mmbase.org/mailman/listinfo/cvs