001/* 002 * Copyright (c) 2006-2011 Nuxeo SA (http://nuxeo.com/) and others. 003 * 004 * All rights reserved. This program and the accompanying materials 005 * are made available under the terms of the Eclipse Public License v1.0 006 * which accompanies this distribution, and is available at 007 * http://www.eclipse.org/legal/epl-v10.html 008 * 009 * Contributors: 010 * Florent Guillaume 011 */ 012package org.nuxeo.ecm.core.storage.sql; 013 014import java.io.Serializable; 015import java.util.HashSet; 016import java.util.Set; 017 018/** 019 * A set of invalidations. 020 * <p> 021 * Records both modified and deleted fragments, as well as "parents modified" fragments. 022 */ 023public class Invalidations implements Serializable { 024 025 private static final long serialVersionUID = 1L; 026 027 /** Pseudo-table for children invalidation. */ 028 public static final String PARENT = "__PARENT__"; 029 030 /** Pseudo-table for series proxies invalidation. */ 031 public static final String SERIES_PROXIES = "__SERIES_PROXIES__"; 032 033 /** Pseudo-table for target proxies invalidation. */ 034 public static final String TARGET_PROXIES = "__TARGET_PROXIES__"; 035 036 public static final int MODIFIED = 1; 037 038 public static final int DELETED = 2; 039 040 /** 041 * Maximum number of invalidations kept, after which only {@link #all} is set. This avoids accumulating too many 042 * invalidations in memory, at the expense of more coarse-grained invalidations. 043 */ 044 public static final int MAX_SIZE = 10000; 045 046 /** 047 * Used locally when invalidating everything, or when too many invalidations have been received. 048 */ 049 public boolean all; 050 051 /** null when empty */ 052 public Set<RowId> modified; 053 054 /** null when empty */ 055 public Set<RowId> deleted; 056 057 public Invalidations() { 058 } 059 060 public Invalidations(boolean all) { 061 this.all = all; 062 } 063 064 public boolean isEmpty() { 065 return modified == null && deleted == null && !all; 066 } 067 068 public void clear() { 069 all = false; 070 modified = null; 071 deleted = null; 072 } 073 074 protected void setAll() { 075 all = true; 076 modified = null; 077 deleted = null; 078 } 079 080 protected void checkMaxSize() { 081 if (modified != null && modified.size() > MAX_SIZE // 082 || deleted != null && deleted.size() > MAX_SIZE) { 083 setAll(); 084 } 085 } 086 087 /** only call this if it's to add at least one element in the set */ 088 public Set<RowId> getKindSet(int kind) { 089 switch (kind) { 090 case MODIFIED: 091 if (modified == null) { 092 modified = new HashSet<RowId>(); 093 } 094 return modified; 095 case DELETED: 096 if (deleted == null) { 097 deleted = new HashSet<RowId>(); 098 } 099 return deleted; 100 } 101 throw new AssertionError(); 102 } 103 104 public void add(Invalidations other) { 105 if (other == null) { 106 return; 107 } 108 if (all) { 109 return; 110 } 111 if (other.all) { 112 setAll(); 113 return; 114 } 115 if (other.modified != null) { 116 if (modified == null) { 117 modified = new HashSet<RowId>(); 118 } 119 modified.addAll(other.modified); 120 } 121 if (other.deleted != null) { 122 if (deleted == null) { 123 deleted = new HashSet<RowId>(); 124 } 125 deleted.addAll(other.deleted); 126 } 127 checkMaxSize(); 128 } 129 130 public void addModified(RowId rowId) { 131 if (all) { 132 return; 133 } 134 if (modified == null) { 135 modified = new HashSet<RowId>(); 136 } 137 modified.add(rowId); 138 checkMaxSize(); 139 } 140 141 public void addDeleted(RowId rowId) { 142 if (all) { 143 return; 144 } 145 if (deleted == null) { 146 deleted = new HashSet<RowId>(); 147 } 148 deleted.add(rowId); 149 checkMaxSize(); 150 } 151 152 public void add(Serializable id, String[] tableNames, int kind) { 153 if (tableNames.length == 0) { 154 return; 155 } 156 Set<RowId> set = getKindSet(kind); 157 for (String tableName : tableNames) { 158 set.add(new RowId(tableName, id)); 159 } 160 checkMaxSize(); 161 } 162 163 @Override 164 public String toString() { 165 StringBuilder sb = new StringBuilder(this.getClass().getSimpleName() + '('); 166 if (all) { 167 sb.append("all=true"); 168 } 169 if (modified != null) { 170 sb.append("modified="); 171 sb.append(modified); 172 if (deleted != null) { 173 sb.append(','); 174 } 175 } 176 if (deleted != null) { 177 sb.append("deleted="); 178 sb.append(deleted); 179 } 180 sb.append(')'); 181 return sb.toString(); 182 } 183 184}