1 9 package org.ozoneDB.core.storage.wizardStore; 10 11 import java.io.Externalizable ; 12 import java.io.File ; 13 import java.io.FileInputStream ; 14 import java.io.FileOutputStream ; 15 import java.io.IOException ; 16 import java.io.InputStream ; 17 import java.io.ObjectInput ; 18 import java.io.ObjectOutput ; 19 import java.io.ObjectStreamException ; 20 import java.io.OutputStream ; 21 import org.ozoneDB.DxLib.DxArrayBag; 22 import org.ozoneDB.DxLib.DxCollection; 23 import org.ozoneDB.DxLib.DxHashMap; 24 import org.ozoneDB.DxLib.DxIterator; 25 import org.ozoneDB.DxLib.DxLong; 26 import org.ozoneDB.core.Lock; 27 import org.ozoneDB.core.MROWLock; 28 import org.ozoneDB.core.Permissions; 29 import org.ozoneDB.core.Transaction; 30 import org.ozoneDB.core.TransactionID; 31 import org.ozoneDB.core.storage.AbstractCluster; 32 import org.ozoneDB.core.storage.StorageObjectContainer; 33 import org.ozoneDB.core.storage.ClusterID; 34 import org.ozoneDB.util.LogWriter; 35 36 37 38 44 public class WizardCluster extends AbstractCluster implements Externalizable { 45 46 protected final static long serialVersionUID = 2L; 47 protected final static byte subSerialVersionUID = 1; 48 49 protected transient Lock lock; 50 51 protected transient long lastTouched; 52 53 protected transient int bytesPerContainer; 54 55 protected long modTime; 56 57 64 protected transient int pinCount; 65 66 67 70 public WizardCluster() { 71 this(null, null, null, 0); 72 } 73 74 75 public WizardCluster(ClusterID _clusterID, Permissions _permissions, Lock _lock, int _bpc) { 76 clusterID = _clusterID; 78 permissions = _permissions; 79 lock = _lock; 80 bytesPerContainer = _bpc; 81 containers = new DxHashMap(1024); 82 if (lock != null) { 83 ((MROWLock) lock).setDebugInfo("clusterID=" + clusterID); 84 } 85 } 86 87 88 94 95 public long modTime() { 96 return modTime; 97 } 98 99 100 105 public DxLong cachePriority() { 106 return new DxLong(lastTouched); 107 } 108 109 110 public synchronized void setCurrentSize(int byteSize) { 111 int containerCount = containers.count(); 112 bytesPerContainer = containerCount > 0 ? byteSize / containerCount : clusterStore.currentBytesPerContainer(); 113 } 114 115 116 public int size() { 117 return containers.count() * bytesPerContainer; 118 } 119 120 121 124 public boolean isInvoked() { 125 StorageObjectContainer container; 128 DxIterator it = containers.iterator(); 129 while ((container = (StorageObjectContainer) it.next()) != null) { 130 if (container.isInvoked()) { 131 return true; 132 } 133 } 134 return false; 135 } 136 137 138 public synchronized void touch() { 139 lastTouched = clusterStore.touchCount++; 140 } 141 142 143 public void registerContainer(StorageObjectContainer container) { 144 synchronized (container) { 145 container.setCluster(this); 146 if (containers.addForKey(container, container.id()) == false) { 147 throw new IllegalStateException ("Unable to add id " + container.id() + " to cluster " + clusterID()); 148 } 149 } 150 } 151 152 153 public void removeContainer(StorageObjectContainer container) { 154 if (containers.removeForKey(container.id()) == null) { 155 throw new IllegalStateException ("Unable to remove container from cluster."); 156 } 157 } 158 159 160 165 public void updateLockLevel(Transaction ta) throws IOException { 166 if (env.logWriter.hasTarget(LogWriter.DEBUG2)) { 167 env.logWriter.newEntry(this, "updateLockLevel(): " + clusterID, LogWriter.DEBUG2); 168 env.logWriter.newEntry(this, " lock: " + lock.level(ta), LogWriter.DEBUG2); 169 } 170 if (lock.level(ta) > Lock.LEVEL_UPGRADE) { 171 saveShadow(); 172 } 173 } 174 175 176 public void prepareCommit(Transaction ta) { 177 if (env.logWriter.hasTarget(LogWriter.DEBUG3)) { 178 env.logWriter.newEntry(this, "prepareCommit()" + clusterID, LogWriter.DEBUG3); 179 } 180 if (lock.level(ta) > Lock.LEVEL_UPGRADE) { 181 synchronized (this) { 182 modTime = System.currentTimeMillis(); 183 } 184 } 185 } 186 187 188 public void commit(Transaction ta) throws IOException { 189 if (env.logWriter.hasTarget(LogWriter.DEBUG3)) { 190 env.logWriter.newEntry(this, "commit()" + clusterID, LogWriter.DEBUG3); 191 } 192 193 if (true || lock != null) { 194 if (lock.level(ta) > Lock.LEVEL_UPGRADE) { 195 deleteShadow(); 196 } 197 lock.release(ta); 198 } else { 199 throw new NullPointerException (this + ".commit(" + ta + "): lock=" + lock + "."); 201 } 202 } 203 204 205 public void abort(Transaction ta) throws IOException { 206 if (env.logWriter.hasTarget(LogWriter.DEBUG3)) { 207 env.logWriter.newEntry(this, "abort()" + clusterID, LogWriter.DEBUG3); 208 } 209 210 if (true || lock != null) { 211 if (lock.level(ta) > Lock.LEVEL_UPGRADE) { 212 restoreShadow(); 213 deleteShadow(); 214 } 215 lock.release(ta); 216 } else { 217 throw new NullPointerException (this + ".abort(" + ta + "): lock=" + lock + "."); 218 } 219 } 220 221 222 230 231 public DxCollection allLockers() { 232 DxCollection lockerIDs = lock.lockerIDs(); 233 234 DxArrayBag result = new DxArrayBag(lockerIDs.count()); 235 DxIterator it = lockerIDs.iterator(); 236 while (it.next() != null) { 237 result.add(env.transactionManager.taForID((TransactionID) it.object())); 238 } 239 240 return result; 241 } 242 243 244 248 protected void saveShadow() throws IOException { 249 if (env != null) { 250 } 252 253 String basename = clusterStore.basename(clusterID); 254 File orig = new File (basename + ClusterStore.POSTFIX_CLUSTER); 255 File shadow = new File (basename + ClusterStore.POSTFIX_SHADOW); 256 257 262 264 267 InputStream in = null; 268 OutputStream out = null; 269 try { 270 in = new FileInputStream (orig); 271 out = new FileOutputStream (shadow); 272 273 final int chunkSize = 4096; 274 byte[] chunk = new byte[chunkSize]; 275 int c = 0; 276 while ((c = in.read(chunk)) != -1) { 277 out.write(chunk, 0, c); 278 } 279 } finally { 280 if (in != null) { 281 in.close(); 282 } 283 if (out != null) { 284 out.close(); 285 } 286 } 287 } 288 289 290 294 protected void restoreShadow() throws IOException { 295 if (env != null) { 296 } 298 299 String basename = clusterStore.basename(clusterID); 301 File orig = new File (basename + ClusterStore.POSTFIX_CLUSTER); 302 File shadow = new File (basename + ClusterStore.POSTFIX_SHADOW); 303 304 orig.delete(); 307 if (!shadow.renameTo(orig)) { 308 throw new IOException ("Unable to rename shadow file."); 309 } 310 } 311 312 313 protected void deleteShadow() throws IOException { 314 if (env.logWriter.hasTarget(LogWriter.DEBUG3)) { 315 env.logWriter.newEntry(this, "deleteShadow(): " + clusterID, LogWriter.DEBUG3); 316 } 317 318 String basename = clusterStore.basename(clusterID); 319 File shadow = new File (basename + ClusterStore.POSTFIX_SHADOW); 320 if (shadow.exists() && !shadow.delete()) { 321 throw new IOException ("Unable to delete shadow file."); 322 } 323 } 324 325 326 329 public void delete() throws Exception { 330 String basename = clusterStore.basename(clusterID); 331 new File (basename + ClusterStore.POSTFIX_CLUSTER).delete(); 332 new File (basename + ClusterStore.POSTFIX_SHADOW).delete(); 333 new File (basename + ClusterStore.POSTFIX_TEMP).delete(); 334 new File (basename + ClusterStore.POSTFIX_LOCK).delete(); 335 } 336 337 public String toString() { 338 return "WizardCluster[id=" + clusterID + "]"; 339 } 340 341 public Lock lock() { 342 return lock; 343 } 344 345 public void setLock(Lock to) { 346 if (to == null) { 348 if (env.logWriter.hasTarget(LogWriter.DEBUG)) { 349 env.logWriter.newEntry(this, this + ".setLock(" + to + ") (oldLock=" + this.lock + "), isPinned()=" + isPinned() + ".", LogWriter.DEBUG); 350 } 351 } 352 353 this.lock = to; 354 } 355 356 public void writeExternal(ObjectOutput out) throws IOException { 357 out.writeByte(subSerialVersionUID); 363 out.writeObject(clusterID); 364 out.writeObject(permissions); 365 out.writeLong(modTime); 366 368 out.writeInt(containers.count()); 369 DxIterator it = containers.iterator(); 370 StorageObjectContainer container; 371 while ((container = (StorageObjectContainer) it.next()) != null) { 372 container.writeExternal(out); 374 } 375 } 376 377 378 public void readExternal(ObjectInput in) throws IOException , ObjectStreamException , ClassNotFoundException { 379 byte streamUID = in.readByte(); 381 clusterID = (ClusterID) in.readObject(); 382 permissions = (Permissions) in.readObject(); 383 modTime = in.readLong(); 384 386 int count = in.readInt(); 387 for (int i = 0; i < count; i++) { 388 try { 389 StorageObjectContainer container = new WizardObjectContainer(); 391 container.readExternal(in); 392 container.setCluster(this); 393 containers.addForKey(container, container.id()); 395 } catch (ObjectStreamException e) { 396 if (env != null) { 397 env.logWriter.newEntry(this, "ObjectStreamException for cluster " + clusterID + " at container #" + i + ": ", e, LogWriter.ERROR); 398 } else { 399 System.out.println("ObjectStreamException for cluster " + clusterID + " at container #" + i + ": " + e); 400 } 401 throw e; 402 } 403 } 404 } 405 406 411 public synchronized void pin() { 412 int maxPinCount = (1 + containers.count()) * 1000; 413 if (++pinCount > maxPinCount) { 414 env.logWriter.newEntry(this, "pincount for " + this + " getting too large (" + pinCount + " for " + containers.count() + " containers)", LogWriter.ERROR); 415 } 416 } 417 418 422 public synchronized void unpin() { 423 if (--pinCount < 0) { 424 env.logWriter.newEntry(this, "pincount < 0 (" + pinCount + ") for " + this, LogWriter.WARN); 425 clearPinCount(); 426 } 430 431 } 432 433 436 public synchronized boolean isPinned() { 437 return pinCount != 0; 438 } 439 440 443 public synchronized int clearPinCount() { 444 int oldPinCount = pinCount; 445 446 pinCount = 0; 447 448 return oldPinCount; 449 } 450 451 454 public synchronized void addPinCount(int what) { 455 pinCount += what; 456 } 457 } 458 | Popular Tags |