1 7 package org.jboss.cache; 8 9 import org.apache.commons.logging.Log; 10 import org.apache.commons.logging.LogFactory; 11 import org.jboss.cache.lock.IdentityLock; 12 import org.jboss.cache.marshall.MethodCall; 13 import org.jboss.cache.marshall.MethodCallFactory; 14 import org.jboss.cache.marshall.MethodDeclarations; 15 import org.jboss.cache.optimistic.DataVersion; 16 import org.jboss.cache.util.MapCopy; 17 18 import java.io.Serializable ; 19 import java.util.AbstractSet ; 20 import java.util.Collections ; 21 import java.util.HashMap ; 22 import java.util.HashSet ; 23 import java.util.Iterator ; 24 import java.util.Map ; 25 import java.util.Set ; 26 import java.util.concurrent.ConcurrentHashMap ; 27 28 31 public class UnversionedNode extends AbstractNode implements NodeSPI 32 { 33 34 37 private static final int INDENT = 4; 38 39 42 private static Log log = LogFactory.getLog(UnversionedNode.class); 43 44 47 private boolean childrenLoaded = false; 48 49 52 private boolean dataLoaded = false; 53 54 58 private transient IdentityLock lock_ = null; 59 60 63 private transient CacheImpl cache; 64 65 68 private final Map data = new HashMap (); 69 70 73 public UnversionedNode() 74 { 75 this(Fqn.ROOT); 76 } 77 78 81 public UnversionedNode(Fqn fqn) 82 { 83 this.fqn = fqn; 84 } 85 86 89 public UnversionedNode(Object child_name, Fqn fqn, Map data, CacheSPI cache) 90 { 91 init(child_name, fqn, cache); 92 if (data != null) 93 { 94 this.data.putAll(data); 95 } 96 } 97 98 105 public UnversionedNode(Object child_name, Fqn fqn, Map data, boolean mapSafe, CacheSPI cache) 106 { 107 init(child_name, fqn, cache); 108 if (data != null) 109 { 110 this.data.putAll(data); } 112 } 113 114 117 private void init(Object child_name, Fqn fqn, CacheSPI cache) 118 { 119 if (cache == null) 120 { 121 throw new IllegalArgumentException ("no cache init for " + fqn); 122 } 123 this.cache = (CacheImpl) cache; 124 this.fqn = fqn; 125 if (!fqn.isRoot() && !child_name.equals(fqn.getLastElement())) 126 { 127 throw new IllegalArgumentException ("Child " + child_name + " must be last part of " + fqn); 128 } 129 } 130 131 134 public NodeSPI getParent() 135 { 136 if (fqn.isRoot()) 137 { 138 return null; 139 } 140 return cache.peek(fqn.getParent()); 141 } 142 143 private synchronized void initLock() 144 { 145 if (lock_ == null) 146 { 147 lock_ = new IdentityLock(cache.getConfiguration().getIsolationLevel(), this); 148 } 149 } 150 151 private synchronized Map <Object , Node> children() 152 { 153 if (children == null) 154 { 155 if (getFqn().isRoot()) 156 { 157 children = new ConcurrentHashMap <Object , Node>(64, .5f, 16); 158 } 159 else 160 { 161 children = new ConcurrentHashMap <Object , Node>(4, .75f, 4); 163 } 164 } 165 return children; 166 } 167 168 public void setCache(CacheSPI cache) 169 { 170 this.cache = (CacheImpl) cache; 171 this.lock_ = null; 172 if (children != null) 173 { 174 for (Node n : children.values()) 175 { 176 ((UnversionedNode) n).setCache(cache); 177 } 178 } 179 } 180 181 public CacheSPI getCache() 182 { 183 return cache; 184 } 185 186 public boolean getChildrenLoaded() 187 { 188 return childrenLoaded; 189 } 190 191 public void setChildrenLoaded(boolean flag) 192 { 193 childrenLoaded = flag; 194 } 195 196 public Object get(Object key) 197 { 198 return cache.get(getFqn(), key); 199 } 200 201 public synchronized Object getDirect(Object key) 202 { 203 return data == null ? null : data.get(key); 204 } 205 206 207 private boolean isReadLocked() 208 { 209 return lock_ != null && lock_.isReadLocked(); 210 } 211 212 private boolean isWriteLocked() 213 { 214 return lock_ != null && lock_.isWriteLocked(); 215 } 216 217 public IdentityLock getLock() 218 { 219 initLock(); 220 return lock_; 221 } 222 223 public Map <Object , Object > getData() 224 { 225 if (cache == null) return Collections.emptyMap(); 226 Map <Object , Object > dMap = new HashMap <Object , Object >(); 227 for (Object k : cache.getKeys(getFqn())) 228 { 229 dMap.put(k, cache.get(fqn, k)); 230 } 231 return Collections.unmodifiableMap(dMap); 232 } 233 234 public synchronized Map <Object , Object > getDataDirect() 235 { 236 return new MapCopy(data); 237 } 238 239 240 public Object put(Object key, Object value) 241 { 242 return cache.put(getFqn(), key, value); 243 } 244 245 public synchronized Object putDirect(Object key, Object value) 246 { 247 return data.put(key, value); 248 } 249 250 public NodeSPI getOrCreateChild(Object child_name, GlobalTransaction gtx) 251 { 252 return getOrCreateChild(child_name, gtx, true); 253 } 254 255 private synchronized NodeSPI getOrCreateChild(Object child_name, GlobalTransaction gtx, boolean createIfNotExists) 256 { 257 258 NodeSPI child; 259 if (child_name == null) 260 { 261 throw new IllegalArgumentException ("null child name"); 262 } 263 264 child = (NodeSPI) children().get(child_name); 265 if (createIfNotExists && child == null) 266 { 267 Fqn child_fqn = new Fqn(this.fqn, child_name); 270 NodeSPI newChild = (NodeSPI) cache.getConfiguration().getRuntimeConfig().getNodeFactory().createNode(child_name, this, null); 271 if (newChild == null) 272 { 273 throw new IllegalStateException (); 274 } 275 synchronized (this) 276 { 277 child = (NodeSPI) children().get(child_name); 280 if (child == null) 281 { 282 cache.getNotifier().notifyNodeCreated(child_fqn, true, true); 283 child = newChild; 284 children.put(child_name, child); 285 if (gtx != null) 286 { 287 MethodCall undo_op = MethodCallFactory.create(MethodDeclarations.removeNodeMethodLocal, gtx, 288 child_fqn, false); 289 cache.addUndoOperation(gtx, undo_op); 290 } 294 } 295 } 296 297 if (newChild == child) 299 { 300 if (log.isTraceEnabled()) 301 { 302 log.trace("created child: fqn=" + child_fqn); 303 } 304 cache.getNotifier().notifyNodeCreated(child_fqn, false, true); 305 } 306 } 307 return child; 308 309 } 310 311 public Object remove(Object key) 312 { 313 return cache.remove(getFqn(), key); 314 } 315 316 public synchronized Object removeDirect(Object key) 317 { 318 if (data == null) return null; 319 return data.remove(key); 320 } 321 322 public void printDetails(StringBuffer sb, int indent) 323 { 324 printDetailsInMap(sb, indent); 325 } 326 327 330 @Override 331 public String toString() 332 { 333 StringBuffer sb = new StringBuffer (); 334 sb.append(getClass().getSimpleName()); 335 if (deleted) 336 { 337 sb.append(" (deleted) [ ").append(fqn); 338 } 339 else 340 { 341 sb.append("[ ").append(fqn); 342 } 343 synchronized (this) 344 { 345 if (data != null) 346 { 347 sb.append(" data=").append(data.keySet()); 348 } 349 } 350 if (children != null && !children.isEmpty()) 351 { 352 sb.append(" child=").append(getChildrenDirect(false)); 353 } 354 if (lock_ != null) 355 { 356 if (isReadLocked()) 357 { 358 sb.append(" RL"); 359 } 360 if (isWriteLocked()) 361 { 362 sb.append(" WL"); 363 } 364 } 365 sb.append("]"); 366 return sb.toString(); 367 } 368 369 public Node addChild(Fqn f) 370 { 371 Fqn nf = new Fqn(getFqn(), f); 372 cache.put(nf, null); 373 return getChild(f); 374 } 375 376 public NodeSPI addChildDirect(Fqn f) 377 { 378 if (f.size() == 1) 379 { 380 GlobalTransaction gtx = cache.getInvocationContext().getGlobalTransaction(); 381 return getOrCreateChild(f.getLastElement(), gtx); 382 } 383 else 384 { 385 throw new UnsupportedOperationException ("Cannot directly create children which aren't directly under the current node."); 386 } 387 388 } 389 390 public void clearData() 391 { 392 cache.removeData(getFqn()); 393 } 394 395 public synchronized void clearDataDirect() 396 { 397 if (data != null) data.clear(); 398 } 399 400 public Node getChild(Fqn fqn) 401 { 402 return cache.get(new Fqn(getFqn(), fqn)); 403 } 404 405 public NodeSPI getChildDirect(Fqn fqn) 406 { 407 if (fqn.size() == 1) 408 { 409 return getChildDirect(fqn.getLastElement()); 410 } 411 else 412 { 413 NodeSPI currentNode = this; 414 for (int i = 0; i < fqn.size(); i++) 415 { 416 Object nextChildName = fqn.get(i); 417 currentNode = currentNode.getChildDirect(nextChildName); 418 if (currentNode == null) return null; 419 } 420 return currentNode; 421 } 422 } 423 424 public Set <Object > getChildrenNames() 425 { 426 return cache.getChildrenNames(getFqn()); 427 } 428 429 public Set <Object > getChildrenNamesDirect() 430 { 431 return Collections.unmodifiableSet(new HashSet (new ChildrenNames())); 432 } 433 434 public Set <Object > getKeys() 435 { 436 Set keys = cache.getKeys(getFqn()); 437 return keys == null ? Collections.emptySet() : Collections.unmodifiableSet(keys); 438 } 439 440 public synchronized Set <Object > getKeysDirect() 441 { 442 if (data == null) 443 { 444 return Collections.emptySet(); 445 } 446 return Collections.unmodifiableSet(new HashSet (data.keySet())); 447 } 448 449 public boolean hasChild(Fqn f) 450 { 451 return cache.exists(new Fqn(getFqn(), f)); 452 } 453 454 public void putIfAbsent(Object k, Object v) 455 { 456 throw new UnsupportedOperationException ("This operation was only added in 2.0.0 to finalise the API. This will not be implemented till 2.1.0."); 457 } 458 459 public void putIfAbsent(Map m) 460 { 461 throw new UnsupportedOperationException ("This operation was only added in 2.0.0 to finalise the API. This will not be implemented till 2.1.0."); 462 } 463 464 public void removeChild(Fqn fqn) 465 { 466 cache.removeNode(new Fqn(getFqn(), fqn)); 467 } 468 469 public void removeChild(Object childName) 470 { 471 removeChild(new Fqn(getFqn(), childName)); 472 } 473 474 public synchronized void removeChildDirect(Object childName) 475 { 476 children().remove(childName); 477 } 478 479 public void removeChildDirect(Fqn f) 480 { 481 if (f.size() == 1) 482 { 483 removeChildDirect(f.getLastElement()); 484 } 485 else 486 { 487 NodeSPI child = getChildDirect(f); 488 if (child != null) child.getParent().removeChildDirect(f.getLastElement()); 489 } 490 } 491 492 public synchronized Map <Object , Node> getChildrenMapDirect() 493 { 494 return new MapCopy(children()); 495 } 496 497 public synchronized void setChildrenMapDirect(Map <Object , Node> children) 498 { 499 this.children().clear(); 500 this.children.putAll(children); 501 } 502 503 public void put(Map data) 504 { 505 cache.put(fqn, data); 506 } 507 508 public synchronized void putDirect(Map data) 509 { 510 if (data == null) return; 511 this.data.putAll(data); 512 } 513 514 public synchronized void removeChildrenDirect() 515 { 516 if (children != null) 517 { 518 children.clear(); 519 } 520 children = null; 521 } 522 523 public void print(StringBuffer sb, int indent) 524 { 525 printIndent(sb, indent); 526 sb.append(Fqn.SEPARATOR).append(getName()).append(" ").append(getDataDirect().size()); 527 if (children != null) 528 { 529 for (Node node : children.values()) 530 { 531 sb.append("\n"); 532 ((NodeSPI) node).print(sb, indent + INDENT); 533 } 534 } 535 } 536 537 539 public void setVersion(DataVersion version) 540 { 541 throw new UnsupportedOperationException ("Versioning not supported"); 542 } 543 544 public DataVersion getVersion() 545 { 546 throw new UnsupportedOperationException ("Versioning not supported"); 547 } 548 549 private void printIndent(StringBuffer sb, int indent) 550 { 551 if (sb != null) 552 { 553 for (int i = 0; i < indent; i++) 554 { 555 sb.append(" "); 556 } 557 } 558 } 559 560 public void addChild(Object child_name, Node n) 561 { 562 if (child_name != null) 563 { 564 children().put(child_name, n); 565 } 566 } 567 568 571 private Object getName() 572 { 573 return fqn.getLastElement(); 574 } 575 576 579 public Fqn getFqn() 580 { 581 return fqn; 582 } 583 584 public void setFqn(Fqn fqn) 585 { 586 if (log.isTraceEnabled()) 587 { 588 log.trace(getFqn() + " set FQN " + fqn); 589 } 590 this.fqn = fqn; 591 592 if (children == null) 593 { 594 return; 595 } 596 597 for (Map.Entry <Object , ? extends Node> me : children.entrySet()) 599 { 600 NodeSPI n = (NodeSPI) me.getValue(); 601 Fqn cfqn = new Fqn(fqn, me.getKey()); 602 n.setFqn(cfqn); 603 } 604 } 605 606 public Node getChild(Object childName) 607 { 608 return cache.get(new Fqn(getFqn(), childName)); 609 } 610 611 public synchronized NodeSPI getChildDirect(Object childName) 612 { 613 if (childName == null) return null; 614 return (NodeSPI) (children == null ? null : children.get(childName)); 615 } 616 617 public Set <Node> getChildren() 618 { 619 if (cache == null) return Collections.emptySet(); 620 Set <Node> children = new HashSet <Node>(); 621 for (Object c : cache.getChildrenNames(getFqn())) 622 { 623 Node n = cache.get(new Fqn(getFqn(), c)); 624 if (n != null) children.add(n); 625 } 626 return Collections.unmodifiableSet(children); 627 } 628 629 public synchronized Set <NodeSPI> getChildrenDirect() 630 { 631 if (children == null || children.size() == 0) return Collections.emptySet(); 633 634 Set <NodeSPI> exclDeleted = new HashSet <NodeSPI>(); 635 for (Node n : children.values()) 636 { 637 NodeSPI spi = (NodeSPI) n; 638 if (!spi.isDeleted()) exclDeleted.add(spi); 639 } 640 return Collections.unmodifiableSet(exclDeleted); 641 } 642 643 public synchronized Set <NodeSPI> getChildrenDirect(boolean includeMarkedForRemoval) 644 { 645 if (includeMarkedForRemoval) 646 { 647 if (children != null && !children.isEmpty()) 648 { 649 return Collections.unmodifiableSet(new HashSet (children.values())); 650 } 651 else 652 { 653 return Collections.emptySet(); 654 } 655 } 656 else 657 { 658 return getChildrenDirect(); 659 } 660 } 661 662 665 private void printDetailsInMap(StringBuffer sb, int indent) 666 { 667 printIndent(sb, indent); 668 indent += 2; if (!(getFqn()).isRoot()) 670 { 671 sb.append(Fqn.SEPARATOR); 672 } 673 sb.append(getName()); 674 sb.append(" "); 675 sb.append(data); 676 if (children != null) 677 { 678 for (Node n : children.values()) 679 { 680 sb.append("\n"); 681 ((NodeSPI) n).printDetails(sb, indent); 682 } 683 } 684 } 685 686 689 public boolean getDataLoaded() 690 { 691 return dataLoaded; 692 } 693 694 697 public void setDataLoaded(boolean dataLoaded) 698 { 699 this.dataLoaded = dataLoaded; 700 } 701 702 private class ChildrenNames extends AbstractSet implements Serializable 703 { 704 705 708 private static final long serialVersionUID = 5468697840097489795L; 709 710 @Override 711 public Iterator iterator() 712 { 713 if (children == null) 714 { 715 return Collections.emptySet().iterator(); 716 } 717 return children.keySet().iterator(); 718 } 719 720 @Override 721 public boolean contains(Object o) 722 { 723 return children != null && children.containsKey(o); 724 } 725 726 @Override 727 public int size() 728 { 729 if (children == null) 730 { 731 return 0; 732 } 733 return children.size(); 734 } 735 736 private Object writeReplace() 737 { 738 if (children == null) 739 { 740 return Collections.emptySet(); 741 } 742 return Collections.unmodifiableSet(new HashSet (children.keySet())); 743 } 744 745 } 746 747 792 793 } 794 | Popular Tags |