001: /*
002: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
003: *
004: * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
005: *
006: * The contents of this file are subject to the terms of either the GNU
007: * General Public License Version 2 only ("GPL") or the Common
008: * Development and Distribution License("CDDL") (collectively, the
009: * "License"). You may not use this file except in compliance with the
010: * License. You can obtain a copy of the License at
011: * http://www.netbeans.org/cddl-gplv2.html
012: * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
013: * specific language governing permissions and limitations under the
014: * License. When distributing the software, include this License Header
015: * Notice in each file and include the License file at
016: * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
017: * particular file as subject to the "Classpath" exception as provided
018: * by Sun in the GPL Version 2 section of the License file that
019: * accompanied this code. If applicable, add the following below the
020: * License Header, with the fields enclosed by brackets [] replaced by
021: * your own identifying information:
022: * "Portions Copyrighted [year] [name of copyright owner]"
023: *
024: * Contributor(s):
025: *
026: * The Original Software is NetBeans. The Initial Developer of the Original
027: * Software is Sun Microsystems, Inc. Portions Copyright 1997-2007 Sun
028: * Microsystems, Inc. All Rights Reserved.
029: *
030: * If you wish your version of this file to be governed by only the CDDL
031: * or only the GPL Version 2, indicate your decision by adding
032: * "[Contributor] elects to include this software in this distribution
033: * under the [CDDL or GPL Version 2] license." If you do not indicate a
034: * single choice of license, a recipient has the option to distribute
035: * your version of this file under either the CDDL, the GPL Version 2 or
036: * to extend the choice of license to its licensees as provided above.
037: * However, if you add GPL Version 2 code and therefore, elected the GPL
038: * Version 2 license, then the option applies only if the new code is
039: * made subject to such option by the copyright holder.
040: */
041:
042: package org.netbeans.modules.cnd.modelimpl.cache.impl;
043:
044: import java.io.File;
045: import java.util.HashMap;
046: import java.util.Map;
047: import org.netbeans.modules.cnd.modelimpl.csm.core.FileImpl;
048: import org.netbeans.modules.cnd.modelimpl.debug.TraceFlags;
049:
050: /**
051: * cache manager entry for one project
052: *
053: * @author Vladimir Voskresensky
054: */
055: final class ProjectCache {
056: // index for cache files of the project
057: private ProjectIndex index;
058: // accessor to cached info
059: private Map cachedFiles/*<String(abs-path), FileCacheSyncBridge>*/;
060:
061: public ProjectCache(String projectDir) {
062: new File(projectDir).mkdirs();
063: load(projectDir);
064: }
065:
066: public FileCacheSyncBridge getSyncCacheBridge(FileImpl file) {
067: synchronized (cachedFiles) {
068: String absPath = file.getAbsolutePath();
069: FileCacheSyncBridge cache = (FileCacheSyncBridge) cachedFiles
070: .get(absPath);
071: if (cache == null) {
072: if (TraceFlags.TRACE_CACHE) {
073: System.err
074: .println("CACHE: creating FileCacheSyncBridge cache for "
075: + absPath); // NOI18N
076: }
077: cache = new FileCacheSyncBridge(file);
078: cachedFiles.put(absPath, cache);
079: }
080: return cache;
081: }
082: }
083:
084: public void invalidateFile(String absPath) {
085: synchronized (cachedFiles) {
086: if (TraceFlags.TRACE_CACHE) {
087: System.err
088: .println("CACHE: remove FileCacheSyncBridge cache for "
089: + absPath); // NOI18N
090: }
091: // remove cache of invalid file
092: FileCacheSyncBridge cache = (FileCacheSyncBridge) cachedFiles
093: .remove(absPath);
094: if (cache != null) {
095: cache.invalidate();
096: } else {
097: if (TraceFlags.TRACE_CACHE) {
098: System.err
099: .println("CACHE: (invalidateFile) not exists FileCacheSyncBridge cache for "
100: + absPath); // NOI18N
101: }
102: }
103: }
104: ProjectIndex index = getIndex();
105: if (index != null) {
106: synchronized (index) {
107: index.invalidateFile(absPath);
108: }
109: }
110: }
111:
112: private ProjectIndex getIndex() {
113: ProjectIndex index = null;
114: synchronized (loadLock) {
115: if (loaded) {
116: index = this .index;
117: }
118: }
119: return index;
120: }
121:
122: ////////////////////////////////////////////////////////////////////////////
123: // load/store/close support
124:
125: public void store(String baseDir) {
126: if (TraceFlags.TRACE_CACHE) {
127: System.err.println("CACHE: saving project cache data in "
128: + baseDir); // NOI18N
129: }
130: synchronized (loadLock) {
131: storeIndex(baseDir);
132: }
133: }
134:
135: void close(String baseDir) {
136: store(baseDir);
137: index = null;
138: cachedFiles = null;
139: loaded = false;
140: }
141:
142: private boolean loaded = false;
143:
144: // we need exclusive copy of string => use "new String(String)" constructor
145: private final String loadLock = new String("ProjectCache load lock"); // NOI18N
146:
147: private void load(String baseDir) {
148: if (!loaded) {
149: synchronized (loadLock) {
150: if (!loaded) {
151: index = new ProjectIndex();
152: loadIndex(baseDir);
153: cachedFiles = new HashMap();
154: loaded = true;
155: }
156: }
157: }
158: }
159:
160: ////////////////////////////////////////////////////////////////////////////
161: // project index file support
162: // this file contains references from files keys to file-cache names
163: // in the project's cache directory
164:
165: private void loadIndex(String baseDir) {
166: assert (index != null);
167: File file = getProjectIndexFile(baseDir);
168: boolean loaded = false;
169: synchronized (index) {
170: loaded = index.load(file);
171: }
172: if (TraceFlags.TRACE_CACHE) {
173: if (loaded) {
174: System.err.println("CACHE: loaded project index:"
175: + file.getAbsolutePath()); // NOI18N
176: synchronized (index) {
177: System.err.println("CACHE: " + index); // NOI18N
178: }
179: } else {
180: System.err.println("CACHE: project index not found:"
181: + file.getAbsolutePath()); // NOI18N
182: }
183: }
184: }
185:
186: private void storeIndex(String baseDir) {
187: if (index == null)
188: return;
189: File file = getProjectIndexFile(baseDir);
190: boolean saved = false;
191: synchronized (index) {
192: saved = index.save(file);
193: }
194: if (TraceFlags.TRACE_CACHE) {
195: if (saved) {
196: System.err.println("CACHE: saved project index:"
197: + file.getAbsolutePath()); // NOI18N
198: synchronized (index) {
199: System.err.println("project index:"
200: + index.toString()); // NOI18N
201: }
202: } else {
203: System.err
204: .println("CACHE: errors on saving project index:"
205: + file.getAbsolutePath()); // NOI18N
206: }
207: }
208: }
209:
210: private File getProjectIndexFile(String baseDir) {
211: String cache = baseDir + File.separatorChar + "project.dat"; // NOI18N
212: File file = new File(cache);
213: return file;
214: }
215:
216: public CharSequence getValidCacheFileName(FileImpl file,
217: boolean updateEntry) {
218: ProjectIndex index = getIndex();
219: if (index == null) {
220: return null;
221: }
222: CharSequence out = null;
223: // return cache only for file based buffers
224: // and with correct modified date
225: if (file.getBuffer().isFileBased()) {
226: long lastModified = file.getBuffer().getFile()
227: .lastModified();
228: ProjectIndex.Entry entry = null;
229: synchronized (index) {
230: entry = index.getFileEntry(file);
231: if (entry == null) {
232: entry = index.putFile(file);
233: }
234: if (updateEntry) {
235: entry.setLastModified(lastModified);
236: }
237: }
238: assert (entry != null);
239: if (updateEntry) {
240: out = entry.getCacheFileName();
241: } else {
242: if (entry.getLastModified() == lastModified) {
243: out = entry.getCacheFileName();
244: } else {
245: if (TraceFlags.TRACE_CACHE) {
246: System.err.println("CACHE: file "
247: + file.getAbsolutePath()
248: + " was modified " + lastModified
249: + " vs. entry="
250: + entry.getLastModified()); // NOI18N
251: }
252: }
253: }
254: }
255: return TraceFlags.CACHE_SKIP_SAVE ? null : out;
256: }
257: }
|