Source Code Cross Referenced for LockManager.java in  » GIS » deegree » org » deegree » io » datastore » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » GIS » deegree » org.deegree.io.datastore 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        //$HeadURL: svn+ssh://mschneider@svn.wald.intevation.org/deegree/base/trunk/src/org/deegree/io/datastore/FeatureId.java $
002:        /*----------------    FILE HEADER  ------------------------------------------
003:
004:         This file is part of deegree.
005:         Copyright (C) 2001-2008 by:
006:         EXSE, Department of Geography, University of Bonn
007:         http://www.giub.uni-bonn.de/deegree/
008:         lat/lon GmbH
009:         http://www.lat-lon.de
010:
011:         This library is free software; you can redistribute it and/or
012:         modify it under the terms of the GNU Lesser General Public
013:         License as published by the Free Software Foundation; either
014:         version 2.1 of the License, or (at your option) any later version.
015:
016:         This library is distributed in the hope that it will be useful,
017:         but WITHOUT ANY WARRANTY; without even the implied warranty of
018:         MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
019:         Lesser General Public License for more details.
020:
021:         You should have received a copy of the GNU Lesser General Public
022:         License along with this library; if not, write to the Free Software
023:         Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
024:
025:         Contact:
026:
027:         Andreas Poth
028:         lat/lon GmbH
029:         Aennchenstr. 19
030:         53115 Bonn
031:         Germany
032:         E-Mail: poth@lat-lon.de
033:
034:         Prof. Dr. Klaus Greve
035:         Department of Geography
036:         University of Bonn
037:         Meckenheimer Allee 166
038:         53115 Bonn
039:         Germany
040:         E-Mail: greve@giub.uni-bonn.de
041:
042:        
043:         ---------------------------------------------------------------------------*/
044:        package org.deegree.io.datastore;
045:
046:        import java.io.File;
047:        import java.io.FileInputStream;
048:        import java.io.FileOutputStream;
049:        import java.io.FilenameFilter;
050:        import java.io.ObjectInputStream;
051:        import java.io.ObjectOutputStream;
052:        import java.util.ArrayList;
053:        import java.util.Date;
054:        import java.util.HashMap;
055:        import java.util.List;
056:        import java.util.Map;
057:        import java.util.Set;
058:        import java.util.TreeMap;
059:        import java.util.TreeSet;
060:        import java.util.UUID;
061:
062:        import org.deegree.framework.log.ILogger;
063:        import org.deegree.framework.log.LoggerFactory;
064:        import org.deegree.i18n.Messages;
065:        import org.deegree.ogcwebservices.wfs.operation.LockFeature;
066:
067:        /**
068:         * Keeps track of all persistent features that are in a locked state, i.e. a {@link LockFeature}
069:         * request has been issued to lock them.
070:         * <p>
071:         * Locked features cannot be updated or deleted except by transactions that specify the appropriate
072:         * lock identifier.
073:         * <p>
074:         * The <code>LockManager</code> also ensures that active locks survive a restart of the VM -
075:         * therefore it keeps serialized and up-to-date versions of all active {@link Lock} instances in a
076:         * temporary directory. The directory is specified by the <code>java.io.tmpdir</code> system
077:         * property. On first initialization, i.e. the first call to {@link #getInstance()}, the directory
078:         * is scanned for all files matching the pattern <code>deegree-lock*.tmp</code>, and these are
079:         * deserialized to rebuild the <code>LockManager</code>'s status.
080:         * 
081:         * @author <a href="mailto:schneider@lat-lon.de">Markus Schneider</a>
082:         * @author last edited by: $Author:$
083:         * 
084:         * @version $Revision:$, $Date:$
085:         */
086:        public class LockManager {
087:
088:            private static final ILogger LOG = LoggerFactory
089:                    .getLogger(LockManager.class);
090:
091:            static String FILE_PREFIX = "deegree-lock";
092:
093:            static String FILE_SUFFIX = ".tmp";
094:
095:            private static LockManager instance;
096:
097:            private static File workingDir;
098:
099:            // maps expiry time to Lock, first key is the one that will timeout first
100:            private TreeMap<Long, Lock> expiryTimeToLock = new TreeMap<Long, Lock>();
101:
102:            private Map<String, Lock> lockIdToLock = new HashMap<String, Lock>();
103:
104:            private Map<String, Lock> fidToLock = new HashMap<String, Lock>();
105:
106:            private Map<Lock, File> lockToFile = new HashMap<Lock, File>();
107:
108:            private LockManager(File workingDir) throws DatastoreException {
109:                if (workingDir == null) {
110:                    String msg = "No working directory for the lock manager specified. Using default temp directory: '"
111:                            + System.getProperty("java.io.tmpdir") + "'";
112:                    LOG.logInfo(msg);
113:                    workingDir = new File(System.getProperty("java.io.tmpdir"));
114:                }
115:
116:                LockManager.workingDir = workingDir;
117:                if (!workingDir.isDirectory()) {
118:                    String msg = "Specified working directory for the lock manager '"
119:                            + workingDir + "' does not denote a directory.";
120:                    throw new DatastoreException(msg);
121:                }
122:                if (!workingDir.canWrite()) {
123:                    String msg = "Cannot write to the lock manager's working directory ('"
124:                            + workingDir + "' ).";
125:                    throw new DatastoreException(msg);
126:                }
127:
128:                String msg = "Lock manager will use directory '" + workingDir
129:                        + "' to persist it's locks.";
130:                LOG.logInfo(msg);
131:
132:                restoreLocks();
133:                checkForExpiredLocks();
134:            }
135:
136:            private void restoreLocks() {
137:
138:                // get all persistent locks from temporary directory
139:                String[] fileNames = workingDir.list(new FilenameFilter() {
140:                    public boolean accept(File dir, String name) {
141:                        return name.startsWith(FILE_PREFIX)
142:                                && name.endsWith(FILE_SUFFIX);
143:                    }
144:                });
145:
146:                if (fileNames != null) {
147:                    String msg = Messages.getMessage(
148:                            "DATASTORE_LOCK_RESTORING", fileNames.length,
149:                            workingDir);
150:                    LOG.logInfo(msg);
151:                    for (String fileName : fileNames) {
152:                        File file = new File(workingDir + File.separator
153:                                + fileName);
154:                        try {
155:                            FileInputStream fis = null;
156:                            ObjectInputStream ois = null;
157:                            try {
158:                                fis = new FileInputStream(file);
159:                                ois = new ObjectInputStream(fis);
160:                                Lock lock = (Lock) ois.readObject();
161:                                registerLock(lock, file);
162:                            } finally {
163:                                if (ois != null) {
164:                                    ois.close();
165:                                }
166:                            }
167:                        } catch (Exception e) {
168:                            msg = Messages.getMessage(
169:                                    "DATASTORE_LOCK_RESTORE_FAILED", fileName);
170:                            LOG.logError(msg, e);
171:                        }
172:                    }
173:                }
174:            }
175:
176:            /**
177:             * Initializes the <code>LockManager</code>.
178:             * 
179:             * @param workingDir
180:             *            directory where the <code>LockManager</code> will persists its locks
181:             * @throws DatastoreException
182:             */
183:            public static synchronized void initialize(File workingDir)
184:                    throws DatastoreException {
185:                if (instance != null) {
186:                    String msg = "LockManager has already been initialized.";
187:                    throw new DatastoreException(msg);
188:                }
189:                instance = new LockManager(workingDir);
190:            }
191:
192:            /**
193:             * Returns the only instance of <code>LockManager</code>.
194:             * 
195:             * @return the only instance of <code>LockManager</code>
196:             */
197:            public static synchronized LockManager getInstance() {
198:                if (instance == null) {
199:                    String msg = "LockManager has not been initialized yet.";
200:                    throw new RuntimeException(msg);
201:                }
202:                return instance;
203:            }
204:
205:            /**
206:             * Returns whether the specified feature is locked.
207:             * 
208:             * @param fid
209:             *            id of the feature
210:             * @return true, if the specified feature is locked, false otherwise
211:             */
212:            public boolean isLocked(FeatureId fid) {
213:                return getLockId(fid) != null;
214:            }
215:
216:            /**
217:             * Returns the id of the lock that locks the specified feature (if it is locked).
218:             * 
219:             * @param fid
220:             *            id of the feature
221:             * @return the lock id, or null if it is not locked
222:             */
223:            public String getLockId(FeatureId fid) {
224:
225:                checkForExpiredLocks();
226:
227:                String lockId = null;
228:                synchronized (this ) {
229:                    Lock lock = this .fidToLock.get(fid.getAsString());
230:                    if (lock != null) {
231:                        lockId = lock.getId();
232:                    }
233:                }
234:                return lockId;
235:            }
236:
237:            /**
238:             * Acquires a lock for the given {@link LockFeature} request. The affected feature instances and
239:             * their descendant features + super features have to be specified as well.
240:             * <p>
241:             * If the lockAction in the request is set to ALL and not all requested features could be
242:             * locked, a {@link DatastoreException} will be thrown.
243:             * <p>
244:             * If no features have been locked at all, a lock will be issued, but the lock is not registered
245:             * (as requested by the WFS spec.).
246:             * 
247:             * @param request
248:             *            <code>LockFeature</code> request
249:             * @param fidsToLock
250:             *            all feature instances that are affected by the request
251:             * @return the acquired lock, never null
252:             * @throws DatastoreException
253:             */
254:            public Lock acquireLock(LockFeature request,
255:                    List<FeatureId> fidsToLock) throws DatastoreException {
256:
257:                checkForExpiredLocks();
258:
259:                Lock lock = null;
260:
261:                synchronized (this ) {
262:                    String lockId = UUID.randomUUID().toString();
263:
264:                    Set<String> lockableFids = new TreeSet<String>();
265:                    List<String> notLockableFids = new ArrayList<String>(
266:                            fidsToLock.size());
267:
268:                    for (FeatureId fid : fidsToLock) {
269:                        String fidAsString = fid.getAsString();
270:                        if (this .fidToLock.get(fidAsString) != null) {
271:                            notLockableFids.add(fidAsString);
272:                        } else {
273:                            lockableFids.add(fidAsString);
274:                        }
275:                    }
276:
277:                    if (request.lockAllFeatures() && !notLockableFids.isEmpty()) {
278:                        StringBuffer sb = new StringBuffer();
279:                        for (int i = 0; i < notLockableFids.size(); i++) {
280:                            sb.append(notLockableFids.get(i));
281:                            if (i != notLockableFids.size() - 1) {
282:                                sb.append(", ");
283:                            }
284:                        }
285:                        String msg = Messages.getMessage(
286:                                "DATASTORE_LOCK_SOME_HELD", sb);
287:                        throw new DatastoreException(msg);
288:                    }
289:
290:                    if (!lockableFids.isEmpty()) {
291:                        long duration = request.getExpiry();
292:                        long expiryTime = System.currentTimeMillis() + duration;
293:                        lock = new Lock(lockId, lockableFids, expiryTime);
294:                        File file = persistLock(lock);
295:                        registerLock(lock, file);
296:                    } else {
297:                        lock = new Lock(lockId, lockableFids, System
298:                                .currentTimeMillis());
299:                        String msg = Messages.getMessage(
300:                                "DATASTORE_EMPTY_LOCK", lockId);
301:                        LOG.logInfo(msg);
302:                    }
303:                }
304:                return lock;
305:            }
306:
307:            /**
308:             * Releases the specified lock completely (all associated features are unlocked) and removes it
309:             * (also from the temporary directory).
310:             * 
311:             * @param lockId
312:             *            lock identifier
313:             * @throws DatastoreException
314:             */
315:            public void releaseLock(String lockId) throws DatastoreException {
316:                synchronized (this ) {
317:                    Lock lock = this .lockIdToLock.get(lockId);
318:                    if (lock == null) {
319:                        String msg = Messages.getMessage(
320:                                "DATASTORE_UNKNOWN_LOCK", lockId);
321:                        throw new DatastoreException(msg);
322:                    }
323:                    releaseLock(lock);
324:                }
325:            }
326:
327:            /**
328:             * Releases the given lock completely (all associated features are unlocked) and removes it
329:             * (also from the temporary directory).
330:             * 
331:             * @param lock
332:             *            lock to be released
333:             */
334:            public void releaseLock(Lock lock) {
335:                synchronized (this ) {
336:                    this .lockIdToLock.remove(lock.getId());
337:                    this .expiryTimeToLock.remove(lock.getExpiryTime());
338:                    Set<String> lockedFids = lock.getLockedFids();
339:                    for (String fid : lockedFids) {
340:                        this .fidToLock.remove(fid);
341:                    }
342:                    File file = this .lockToFile.get(lock);
343:                    file.delete();
344:                    this .lockToFile.remove(lock);
345:                }
346:            }
347:
348:            /**
349:             * Releases the specified lock partly (all specified features are unlocked).
350:             * <p>
351:             * If there are no more features associated with the lock, the lock is removed.
352:             * 
353:             * @param lockId
354:             *            lock identifier
355:             * @param unlockFids
356:             *            features to be unlocked
357:             * @throws DatastoreException
358:             */
359:            public void releaseLockPartly(String lockId,
360:                    Set<FeatureId> unlockFids) throws DatastoreException {
361:
362:                synchronized (this ) {
363:                    Lock lock = this .lockIdToLock.get(lockId);
364:                    if (lock == null) {
365:                        String msg = Messages.getMessage(
366:                                "DATASTORE_UNKNOWN_LOCK", lockId);
367:                        throw new DatastoreException(msg);
368:                    }
369:
370:                    Set<String> lockedFeatures = lock.getLockedFids();
371:
372:                    for (FeatureId fid : unlockFids) {
373:                        String fidAsString = fid.getAsString();
374:                        this .fidToLock.remove(fidAsString);
375:                        lockedFeatures.remove(fidAsString);
376:                    }
377:
378:                    if (lockedFeatures.isEmpty()) {
379:                        String msg = Messages.getMessage(
380:                                "DATASTORE_LOCK_CLEARED", lock.getId());
381:                        LOG.logInfo(msg);
382:                        this .lockIdToLock.remove(lockId);
383:                        this .expiryTimeToLock.remove(lock.getExpiryTime());
384:                    }
385:                    persistLock(lock);
386:                }
387:            }
388:
389:            /**
390:             * Checks for expired locks and releases them.
391:             */
392:            private void checkForExpiredLocks() {
393:                synchronized (this ) {
394:                    while (!this .expiryTimeToLock.isEmpty()) {
395:                        long expiry = this .expiryTimeToLock.firstKey();
396:                        if (expiry > System.currentTimeMillis()) {
397:                            break;
398:                        }
399:                        Lock lock = this .expiryTimeToLock.get(expiry);
400:                        String msg = Messages.getMessage(
401:                                "DATASTORE_LOCK_EXPIRED", lock.getId(),
402:                                new Date(lock.getExpiryTime()));
403:                        LOG.logInfo(msg);
404:                        releaseLock(lock);
405:                    }
406:                }
407:            }
408:
409:            /**
410:             * Registers the given lock in the lookup maps of the <code>LockManager</code>.
411:             * <p>
412:             * This includes:
413:             * <ul>
414:             * <li><code>fidToLock-Map</code></li>
415:             * <li><code>lockIdToLock-Map</code></li>
416:             * <li><code>expiryTimeToLock-Map</code></li>
417:             * <li><code>lockToFile-Map</code></li>
418:             * </ul>
419:             * 
420:             * @param lock
421:             *            the lock to be registered
422:             * @param file
423:             *            file that stores the persistent representation of the lock
424:             */
425:            private void registerLock(Lock lock, File file) {
426:                for (String fid : lock.getLockedFids()) {
427:                    this .fidToLock.put(fid, lock);
428:                }
429:                this .expiryTimeToLock.put(lock.getExpiryTime(), lock);
430:                this .lockIdToLock.put(lock.getId(), lock);
431:                this .lockToFile.put(lock, file);
432:                String msg = Messages.getMessage("DATASTORE_LOCK_TIMEOUT_INFO",
433:                        lock.getId(), new Date(lock.getExpiryTime()));
434:                LOG.logInfo(msg);
435:            }
436:
437:            /**
438:             * Persists the given {@link Lock} to a temporary directory.
439:             * <p>
440:             * <ul>
441:             * <li>If the lock is empty (it holds no features), a potentially existing file is deleted.</li>
442:             * <li>If the lock is not empty and it has not been stored yet, it is written to a temporary
443:             * file.</li>
444:             * <li>If the lock is not empty and it has already been stored, the existing file is
445:             * overwritten with the current lock status.</li>
446:             * </ul>
447:             * 
448:             * @param lock
449:             *            the <code>Lock</code> to be persisted
450:             * @return <code>File</code> that stores the <code>Lock</code>, may be null
451:             * @throws DatastoreException
452:             */
453:            private File persistLock(Lock lock) throws DatastoreException {
454:
455:                File file = this .lockToFile.get(lock);
456:                if (!lock.getLockedFids().isEmpty()) {
457:                    // only store it if any features are hold by the lock
458:
459:                    // delete file if it already exists
460:                    if (file != null) {
461:                        file.delete();
462:                    }
463:
464:                    // write lock to file
465:                    FileOutputStream fos = null;
466:                    ObjectOutputStream oos = null;
467:                    try {
468:                        try {
469:                            if (file == null) {
470:                                file = File.createTempFile(FILE_PREFIX,
471:                                        FILE_SUFFIX, workingDir);
472:                            }
473:                            String msg = Messages.getMessage(
474:                                    "DATASTORE_LOCK_STORE", lock.getId(), file
475:                                            .getAbsolutePath());
476:                            LOG.logDebug(msg);
477:                            fos = new FileOutputStream(file);
478:                            oos = new ObjectOutputStream(fos);
479:                            oos.writeObject(lock);
480:                        } finally {
481:                            if (oos != null) {
482:                                oos.flush();
483:                                oos.close();
484:                            } else if (fos != null) {
485:                                fos.close();
486:                            }
487:                        }
488:                    } catch (Exception e) {
489:                        String msg = Messages.getMessage(
490:                                "DATASTORE_LOCK_STORING_FAILED", lock.getId(),
491:                                file.getAbsolutePath(), e.getMessage());
492:                        LOG.logError(msg, e);
493:                        throw new DatastoreException(msg);
494:                    }
495:                } else if (file != null) {
496:                    // else (and file exists) delete file
497:                    LOG.logDebug("Deleting lock '" + lock.getId()
498:                            + "' in file: " + file.getAbsolutePath());
499:                    file.delete();
500:                }
501:                return file;
502:            }
503:
504:            @Override
505:            public String toString() {
506:                StringBuffer sb = new StringBuffer("LockManager status:\n");
507:                sb.append("- number of locked features: "
508:                        + this .fidToLock.size() + "\n");
509:                sb.append("- active locks: " + this .lockIdToLock.size() + "\n");
510:                for (Lock lock : this .lockIdToLock.values()) {
511:                    sb.append("- ");
512:                    sb.append(lock);
513:                    sb.append("\n");
514:                }
515:                return sb.toString();
516:            }
517:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.