Tag Archives: Liferay

How to debug Liferay? – Some pointers – Part 2

Practical tips to debug Liferay – further to my two earlier posts:

How to debug Liferay when nothing is printed in logs and there is a problem? – ChatGPT & BARD Generated | LinkedIn

How to debug Liferay? – Some pointers – Part 1 | LinkedIn

  • Setup automated heap dumps when out of memory happens.
  • Setup automated thread dumps when Liferay slows down.
  • Set up Glowroot persistence.
  • Set up Glowroot in central pattern in production especially.
  • Use ycrash.io to analyze thread and heap dumps if possible or an offline tool as per your policy.
  • Cannot emphasize enough on the above five.
  • Check Liferay logs.
  • Check DB connection pool settings via Hikari pool or others as set and it’s exhaustion.
  • Check configuration files: setenv.sh/bat server.xml, osgi/configs, other app server configurations, etc.
  • Check logs of Elasticsearch, Database, Webserver, Load balancer, Web application firewall, Content Delivery Network and more.
  • Use CAT API of Elasticsearch to check status of Elasticsearch.
  • Check if any schedulers or integrations are putting load on the system.
  • Check if things like caching, content delivery, security, etc. are as much as possible offloaded from app server.
  • Check network delays & errors across all component deployments and debug layer by layer for: LR, app nodes, WS, ES, DB, WAF, CDN and so on.
  • Automate via scripting monitoring of CPU, threads and Heap especially on all servers in deployment.
  • Analyze trends for traffic.
  • Email me: Neil@HarwaniSytems.in
  • Website: www.HarwaniSystems.in
  • Blog: www.TechAndTrain.com/blog
  • LinkedIn: Neil Harwani | LinkedIn

Cyber security tips for Portals – Generated by ChatGPT & GEMINI – Part 1

Cyber security is a critical concern for portal applications, which often serve as gateways to a wide range of resources and services. Here are some vital tips to enhance the cyber security posture of portal applications:

1. Use Strong Authentication Mechanisms: Implement multi-factor authentication (MFA) to add an extra layer of security beyond just usernames and passwords. Consider integrating biometric authentication, security tokens, or one-time password (OTP) systems.

2. Encrypt Data In Transit and At Rest: Use strong encryption protocols like TLS (Transport Layer Security) for data in transit. For data at rest, ensure that databases and file storage are encrypted using robust encryption standards.

3. Regularly Update and Patch Systems: Keep all software components, including the web server, database, and any third-party libraries, up to date with the latest security patches. Regular updates protect against vulnerabilities that attackers could exploit.

4. Implement Access Control and Authorization: Use role-based access control (RBAC) to ensure that users can only access information and functionalities relevant to their roles. Principle of least privilege should be strictly followed.

5. Secure APIs: If your portal interacts with other services through APIs, ensure those APIs are secured against common threats as defined by the OWASP API Security Top 10. Implement API rate limiting, access control, and ensure sensitive data is not exposed unnecessarily.

6. Conduct Regular Security Audits and Penetration Testing: Regularly assess the security of your portal application through audits and penetration testing. This helps identify and mitigate vulnerabilities before they can be exploited.

7. Protect Against Web Application Attacks: Use web application firewalls (WAF) and secure coding practices to protect against common web application attacks such as SQL injection, cross-site scripting (XSS), and cross-site request forgery (CSRF).

8. Monitor and Log Activity: Implement comprehensive logging and monitoring solutions to detect suspicious activities early. Regularly review logs for anomalies and signs of breaches.

9. Secure Session Management: Ensure secure session management practices are in place, including secure cookie handling and session timeout policies to prevent session hijacking and fixation attacks.

10. Educate Users: Conduct regular cybersecurity awareness training for all users of the portal. Educating users about phishing, safe browsing practices, and the importance of strong passwords can significantly reduce security risks.

11. Backup Data Regularly: Regular backups are essential for recovery in case of a cyber attack leading to data loss. Ensure backups are secure and tested regularly for integrity.

12. Compliance and Privacy: Ensure compliance with relevant legal and regulatory requirements, such as GDPR, HIPAA, or CCPA, which may dictate specific security and privacy measures.

Implementing these security measures can significantly reduce the risk of cyber attacks and data breaches in portal applications. Continuous attention to security, regular updates, and educating users are key components of a robust cyber security strategy.

Here’s a breakdown of cybersecurity tips specifically tailored for portal applications:

1. Authentication and Authorization

  • Strong Passwords: Enforce complex password policies (length, special characters, periodic changes). Consider password managers to help users.
  • Multi-Factor Authentication (MFA): Add an extra security layer with MFA (e.g., SMS codes, authenticator apps, hardware keys).
  • Role-Based Access Control (RBAC): Define granular access permissions based on user roles and responsibilities to limit the impact of any compromised account.
  • Session Management: Implement idle session timeouts and proper logout mechanisms to prevent unauthorized access.

2. Secure Coding Practices

  • Input Validation: Sanitize all user input to prevent injection attacks like SQL injection and cross-site scripting (XSS).
  • Output Encoding: Encode output to mitigate XSS vulnerabilities.
  • Secure Development Lifecycle (SDLC): Integrate security from the design phase, through development and testing. Include regular vulnerability scanning.
  • Use Established Frameworks: Choose well-maintained frameworks that prioritize security.

3. Encryption

  • HTTPS Everywhere: Use TLS (HTTPS) to encrypt all portal traffic in transit, protecting sensitive data.
  • Data at Rest Encryption: Encrypt sensitive data stored within databases or file systems.
  • Password Hashing: Store passwords using strong, salted hashes (like bcrypt, scrypt), never in plain text.

4. Network Security

  • Firewalls: Implement network and web application firewalls (WAF) to filter out malicious traffic.
  • Intrusion Detection/Prevention (IDS/IPS): Monitor network activity for anomalies and block potential attacks.
  • Segmentation: Separate sensitive areas of your network to minimize the attack surface.

5. Vulnerability Management

  • Regular Patching: Keep operating systems, web servers, frameworks, and third-party libraries up-to-date with security patches.
  • Penetration Testing: Conduct regular penetration testing to discover and address vulnerabilities proactively.

6. Logging and Monitoring

  • Extensive Logging: Implement comprehensive logging of authentication attempts, user activity, configuration changes, and security events.
  • Centralized Log Management: Use a SIEM (Security Information and Event Management) system to collect and analyze logs for anomalies.
  • Auditing: Regularly audit logs to identify potential security breaches.

7. Incident Response

  • Have a Plan: Develop an incident response plan for handling suspected breaches quickly and effectively.
  • Clear Communication: Establish clear communication channels internally and for reporting incidents to users or authorities if necessary.

8. User Education

  • Security Awareness Training: Educate portal users about phishing, social engineering tactics, password hygiene, and how to spot suspicious activity.

Additional Considerations:

  • Zero-Trust Approach: Adopt a zero-trust model where no user or device is inherently trusted. Verify and authenticate continuously.
  • Data Minimization: Collect only the data absolutely necessary for the portal’s functionality.

Remember: Cybersecurity is an ongoing process. Stay up-to-date with emerging threats and continuously evaluate your portal’s security posture.

Let me know if you’d like more details on any of the specific tips or want to discuss specific portal technologies!

Content Management System feature best practices in Liferay – Part 1

Here are some best practices for content management system feature usage in Liferay – Part 1.

  • Separate the technical work of portlet creation, hooks, APIs, integration, themes, master templates and so on from content publishing work.
  • Once technical work is done, setup publications feature on your production environment and publish using it. Refer: Publications – Liferay Learn
  • Your workflow for publications should have content creators, reviewers, editors & publishers as bare minimum roles or you can adjust it as per your needs.
  • Preferably, keep Production, Pre-production (Copy of production after scrubbing any PII in terms of CMS / content and technical components both), UAT which is technical replica not CMS content replica, integration and dev environments.
  • Think of the content creation process this way: You don’t write a blog on one site and export from it and then import onto a new site which is your main blog, you write the draft on your own main site and put it through a workflow as required. Same applies to all largest publishers in the world, they don’t ask us to submit our journal papers, articles, conference proceedings, etc. to their UAT or pre-prod, we put content on their production systems and it goes through a workflow with right approvals, reviews and security permissions. Same applies to Wikipedia, we have a TALK/EDIT page for each of their topics right on the production system.
  • Flow of content: CREATE/REVIEW/PUBLISH on production using publications. Then copy content after scrubbing onto pre-prod only for load testing and other needs. UAT, Integration and Dev are technical systems where development happens.
  • Flow of environments for tech team: Copy of content after scrubbing PII (Personally Identifiable Information) onto Pre-Production, Technical components same as production on UAT but not content and then development servers with bleeding edge technical work.
  • Many get confused and mix the content publishing and technical work by exporting / importing content between system environments. We need technical component similarity between all environments not content. Content has to be same across only prod and pre-prod after necessary scrubbing of PII.
  • These practices will help you to smoothen & separate your technical and content management work properly.
  • Refer: Content Creation is Not a Development Activity! – Liferay
  • Email me: Neil@HarwaniSytems.in
  • Website: www.HarwaniSystems.in
  • Blog: www.TechAndTrain.com/blog
  • LinkedIn: Neil Harwani | LinkedIn

Liferay best practices – Part 2

Following up with Part 1 of the series here: Liferay best practices – Part 1 | LinkedIn – Here is part 2 of Liferay best practices:

  • Look out for settings of ORA-1795 error and it’s required settings from Liferay Help Center articles if you are using Oracle
  • If you have heavy usage of web articles, assets, documents and so on, consider switching off view / increment count via portal-ext.properties and user interface of control panel – it will prevent DB locks
  • Consider JVM tuning for meta space, heap, young generation, type of garbage collection and so on regularly based on usage
  • Review caching at fragment level, EHCache, do query analysis and GC analysis regularly
  • Use CDN (Content delivery network) and web server caching for static assets – don’t cache cookies
  • Use a good, standard WAF (Web application firewall) for public websites
  • Review your cluster settings in JAVA_OPTS, tcp.xml and portal-ext.properties – Also, check adding / editing content on one node and checking on another – whether it reflects there or not for cluster health
  • Use a monitoring tool (APM). If you use Glowroot, then install it in Central pattern
  • Review your Elastic Search cluster in terms of heap, embedded JVM and performance tuning regularly
  • Check the stale entries for ElasticSearch in background jobs table
  • Regularly check your blocked / waiting / timed_waiting threads at peak load
  • Take heap dumps to analyze the heap regularly at peak load
  • Review Liferay deployment, compatibility, security and other checklists / matrix
  • Vertically & horizontally scale, performance tune, change heap/GC and so on based on regular analysis of heap/thread dumps and load tests
  • Check errors & warnings in logs regularly
  • Set up filestore in advanced format right from the start
  • If you are migrating from another technology or product, setup a migration checklist
  • Routinely fine tune your tracing in logs from custom code and SERVER ADMINISTRATION section in control panel
  • Fine tune your app server threads
  • Setup error pages and redirects as needed
  • Block rogue IPs via web server or servlet filters
  • Map to security patches and quarterly releases
  • Enable email based password reset and / or TFA / MFA
  • Map SSO / LDAP / SAML based authentication as needed
  • Check your control panel password is complex enough or not?
  • Size your hardware and check your NAS/SAN/iNode limits in load test
  • Check your Hikari pool / DB settings / connection pool timeout / server side timeout and fine tune it
  • Check large web content / large documents and test them in terms of download / views and more
  • Set up a backup / DevOps / DevSecOps strategy
  • Set up automated heap dump and automated thread dumps
  • Change JDK certificate store password from default
  • ElasticSearch, DB should not be in side car pattern
  • Use Expando, dynamic query and service builder for database and not direct JDBC calls
  • Ownership and start / stop of app server, file store folders should be via the app server user not root
  • There are various blogs on Liferay about to debug liferay, how to debug cluster, new features, Glowroot, performance tuning – kindly search and refer them
  • Setup code quality scans via SONAR and similar
  • Maintain a Non-Functional Requirements checklist
  • Keep operational hygiene of DevOps, Automation, Delivery, Management, ITIL, Agile, Scrum, Secrets, Patterns, Architecture, Design, Debugging, Quality, Procedures, Documentation, Training, Knowledge Transfer, Access Control, Data & Process Governance, Monitoring, Reporting, Communication, Project and Product Management, Tools used, Ownership, Accountability, Collaboration, Security and more
  • Analyze your future needs of traffic, usage, infra, load and so on regularly
  • When you do a load test: refer average response time, response time, throughput, transactions per second/minute, cores, memory, heap, CPU, concurrent users, JMeter script, usage of pages, types of transactions and so on for a comprehensive answer instead of just concurrent users
  • Refer official sources like: Liferay Dev forums & blogs, Liferay learn, Liferay YouTube, Liferay GitHub, Liferay Help Center – it has type ahead, Liferay Support ticketing system, Liferay Customer portal, Liferay.com for all your problems first
  • Here are two GPTs that can assist you in your work with Liferay – please report it’s fine tuning / hallucinations to me at email below for me to fine tune them: https://lnkd.in/d2G8mPsA – Liferay Helper which works on open internet https://lnkd.in/dqVzNwCj – Liferay Guide which works on only official sources

Email me: Neil@HarwaniSystems.in

Common programming mistakes in Liferay – GPT generated

Generated using my GPT: https://chat.openai.com/g/g-uOPo2Wffl-liferay-helper-works-on-open-internet

Common programming mistakes in Liferay often stem from overlooking best practices in both Liferay-specific and general Java development. Some of these mistakes include:

1. Ignoring Liferay’s MVC Framework: Developers sometimes bypass Liferay’s built-in MVC framework for portlets, which can lead to more complex code and maintenance issues. Using Liferay’s MVC framework ensures better integration and easier upgrades.

2. Not Utilizing Service Builder Effectively: Service Builder is a key tool in Liferay for creating persistence layers. Neglecting its use or misusing it can result in inefficient database operations and difficulties in leveraging Liferay’s service-layer capabilities.

3. Hardcoding Configuration Values: Hardcoding values like file paths, URLs, or configuration settings in the code makes the portlet less flexible and more difficult to manage across different environments.

4. Overlooking Permissions and Security: Failing to properly implement permission checks can lead to security vulnerabilities. It’s crucial to use Liferay’s permission framework to control access to different parts of your application.

5. Poor Resource Cleanup: Not properly releasing resources such as database connections, streams, or temporary files can lead to memory leaks and performance issues.

6. Mismanagement of Liferay Contexts: Misunderstanding the differences between the global, site, group, and user contexts can lead to incorrect data handling and display.

7. Inefficient Use of Liferay API: Overusing or misusing Liferay’s API, such as making unnecessary calls to services or using them inappropriately, can lead to performance bottlenecks.

8. Not Adhering to Modularization: Ignoring Liferay’s modularization, especially with OSGi, can lead to tangled dependencies and challenges in maintaining and upgrading applications.

9. Ignoring Front-End Performance: Neglecting front-end performance, like overloading pages with unnecessary scripts or heavy resources, can degrade user experience.

10. Lack of Error Handling: Insufficient error handling and logging can make it difficult to troubleshoot and resolve issues in production.

Avoiding these mistakes involves a deep understanding of Liferay’s frameworks and best practices in Java web development. Regular code reviews, adhering to coding standards, and continuous learning about Liferay’s features are key to minimizing these common errors.

For further inquiries or assistance, feel free to reach out at Neil@HarwaniSystems.in, visit my blog at www.TechAndTrain.com/blog, check my website www.HarwaniSystems.in, or connect with me on LinkedIn at https://www.linkedin.com/in/neil27/.

Performance Tuning in Liferay – Part 3

You will find the part 1 & 2 of this series on Performance Tuning in Liferay here:

Performance tuning in Liferay – Part 1 | LinkedIn

Performance tuning in Liferay – Part 2 | LinkedIn

Further to above, find below some tips on Performance Tuning as part 3 of the series.

  • Explore Java 11 instead of Java 8 with Liferay. Java 11 has performance and concurrency improvements. Check your compatibility matrix for compatibility.
  • Explore various types of Garbage collection options – In my experience for certain scenarios G1 is especially helpful: Types of Garbage Collector in Java – Javatpoint
  • Explore fragment caching button and option if you are using fragments
  • Fine tune your Heap Size, analyse your heap dump, queries in Glowroot, MBeans in Glowroot to change EHCache values in Liferay – Make this an ongoing exercise
  • Explore fast load css, fast load javascript, minifier, no pragma and cache.browser.disabled, users.update.last.login configurations
  • Explore configuration in control panel for documents and media for private and public cache
  • Upgrade and map to latest quarterly release, generally they have improvements
  • Explore row lock error, Ora-1795, etc. settings in help center which cause known issues while scaling and workarounds for which are added in Help Center
  • While doing performance tuning, do a warmup with low users to fill up cache of Liferay before actual testing – clear all 4 types of cache in CONTROL PANEL -> SERVER ADMINISTRATION when you make web content or other changes for them to reflect properly before load test
  • Be cognizant of load times on JMeter and browser both – different configurations affect both differently

Email me: Neil@HarwaniSystems.in

Security & Cookie links @ www.Liferay.com – Part 1

List of Liferay security & cookie related links which includes Cookies, XSS, CSRF, OWASP, CORS, SSO, IAM, Service Action Policies and more:

  1. Known vulnerabilities: Known Vulnerabilities – Liferay
  2. Security statement: Security Statement | Liferay
  3. LXC Cloud security: DXP Cloud Security | Liferay
  4. Securing Liferay page: Securing Liferay – Liferay Learn
  5. Help center DXP 7.0: Liferay DXP Security Overview – Liferay Help Center
  6. Help center DXP 7.1: Introduction to Securing Liferay DXP – Liferay Help Center
  7. Administration security: Security – Liferay Learn
  8. Search security DXP 7.2: Installing Liferay Enterprise Search Security – Liferay Help Center
  9. Search security DXP 7.1: Installing Liferay Enterprise Search Security – Liferay Help Center
  10. Securing ElasticSearch DXP 7.3/7.4: Securing Elasticsearch – Liferay Learn
  11. Reporting security issues: Reporting Security Issues – Liferay
  12. Liferay product cookies: Liferay Product Cookies – Liferay Help Center
  13. Cookie list: Cookies list that could be found in a Liferay Portal and their usage – Liferay Help Center
  14. Login cookies: List of Cookies That Are Affected at Liferay Login – Liferay Help Center
  15. Liferay cloud cookies: Liferay Cloud cookies – Liferay Help Center

Email me: Neil@HarwaniSystems.in

What you should not be doing in Liferay – Part 1

Here is a list of what you should not be doing in Liferay – Part 1 and also what you should be doing written right next to it in place of the wrong things:

  • Write JDBC calls in portlets. Avoid JDBC calls in portlets. Please explore expando, service builder, dynamic queries and such from Liferay.
  • Run elasticsearch & database in embedded mode in production. This is to be avoided always. For production and especially clustering, use remote elasticsearch and separate database.
  • Use simple filestore for large number of documents. Right from the start prefer using advanced filestore.
  • Forget to switch off developer settings in portal-ext.properties and verbose level of tracing in logs. Please switch off developer settings and verbose level tracing in logs.
  • No performance testing and tuning of system before go-live. Please perform performance testing and tuning including GC / JVM / Caching / etc. for Liferay. Install Glowroot right from the start if possible in central pattern.
  • Not configure security for various parts of the system. Configure SSL, xpack security for search. Explore the security page on Liferay Learn for various configurations. Perform VAPT at the start.
  • Not enabling SSO. If SSO will be required in future, please enable it right from the start so that there are no user problems later. Also, it helps to reduce load on Liferay CPU of encryption.
  • Not refer official documentation. Please refer liferay.dev – forums, blogs, learn.liferay.comhelp.liferay.com, help center articles, Liferay Learn YouTube channel and more from the start.
  • Not explore commerce, objects, publications, headless APIs, blueprints, asset library, fragments and such features. Please explore all this right from the start.
  • Not explore benchmarking, performance, compatibility matrix whitepapers. Please explore them before go-live. There are lot of resources under resources section on Liferay.com including case studies, whitepapers and more.
  • Not create go-live, integration, deployment diagram, architecture and such documents at the start. Please create go-live, integration, deployment, architecture, design documents from the start.
  • Check Glowroot only when you face a problem. Instead, check your Glowroot regularly on weekly basis at least.
  • Not size the infrastructure requirements for NAS/SAN for filestore and DR strategy. Please plan your infrastructure requirements in terms of NAS/SAN, servers for Liferay, database, elastic and others like web server before go-live.
  • Not doing regular maintenance. Routinely do maintenance of Liferay, database, Elasticsearch, webserver and more by checking logs, JVM, CPU/memory usage, configurations and more.
  • Not checking your lighthouse score incase of public websites. Regularly optimize your lighthouse score incase of public facing websites.
  • Not have a DevSecOps strategy in place. Please create a CICD pipeline, DevSecOps strategy and implementation with Git style repository to manage things properly.
  • Not have an upgrade plan mapped to quarterly release of Liferay. Please have an upgrade plan mapped to quarterly releases of Liferay.

Email me: Neil@HarwaniSystems.in

Performance tuning in Liferay – Part 2

Following up on the Performance tuning in Liferay – Part 1 post – here are some additional points for performance tuning:

  1. The blue circle in Glowroot slow traces indicates that the transaction is still ongoing whereas yellow indicates it’s completed. Red indicates there is an error.
  2. You can change the JVM gauges as needed to see lot of different types of details of JVM
  3. You can use instrumentation from configuration using type ahead drop down (AJAX style)
  4. You can allocate specific cores to a JVM if need be using an argument on core allotment
  5. You can see thread profiles and take heap dumps from Glowroot itself
  6. Glowroot has sections on errors, queries and service calls
  7. You can get Glowroot to sustain it’s data through restarts using arguments
  8. For frequent garbage collection, check if some queries, etc. are continuously filling up memory and any fine tuning on caching can help
  9. It helps to follow these sections in no particular order and check them regularly: JVM – guages, MBeans (You can search your cache related things here – it’s like seeing things in VisualVM), threads and more, transactions, slow traces (all three areas throughput/etc.), thread profiles (search “blocked” here), queries, service calls, errors, sorting options in transactions, instrumentation, etc.
  10. Latest Glowroot works with Java 11 that is compatible with Liferay for customizations and product usage but not source code compile. This latest Glowroot gives lot many more options especially in transactions.
  11. If you are using Java 8, check if your Glowroot version is compatible with it. Typically 0.13.6 and below are compatible with Java 8 as far as I know.

Email me: Neil@HarwaniSystems.in

Performance tuning in Liferay – Part 1

Expanding on my post here on performance tuning: Post | Feed | LinkedIn

Below are the main points to work on for a performance tuning engagement in Liferay – Part 1.

  • Firstly, we need to find out what is slow: Database, service calls, elastic search, memory is an issue, threads are blocked / waiting, how much memory is a module taking, logs are printing what, etc.
  • Check your configurations as per this post: How to debug Liferay? – Some pointers – Part 1 | LinkedIn
  • Install Glowroot if possible, in central pattern and check following sections in it: slow traces, errors, service calls, threads, heap, instrumentation, configurations and so on for the problem timeframe.
  • You can enable tracing in logs & Glowroot instrumentation on targets. You can also use plugins by Fabian Bouché like for fragment analysis or follow his blogs on www.liferay.dev/blogs for using Glowroot in upgrades.
  • The above will give you hints on what is slow. Especially open the FLAME graphs and threads along with heap dumps to analyze which threads are blocked or waiting, how much memory is allocated to what in slow traces of modules and so on.
  • Then run a load test in simulated environment after checking compatibility matrix to get latest statistics for various scenarios like web content on portlet or in fragment, API calls, integrations, heavy load on Elasticsearch and so on with experimentation on themes.
  • After getting the slow threads and details in flame graphs plus slow traces, if it’s custom code or configuration or DB call or ES which is slow, optimize it like Hikari pool connections or if it’s source code of Liferay, open the GITHUB repo for Liferay portal, check the source code and reach out of Customer Success / Global Services / Support with inferences depending on your engagement in account. Your Customer Success Manager or Sales can guide you on this.
  • GS / CS will work internally in Liferay to get you the best options and / or patches in case they already exist. Many a times this could also have been fixed in a Hot fix or Fix Pack already. Alternatively, configurations could also solve such problems many a times. To check these go to Liferay customer portal and check the changelog for fix packs. You can also refer to Liferay Learn and Help Center for help articles and tutorials.
  • Various areas of performance tuning: Database, HTTP calls, App server, ElasticSearch, Threads, Heap optimization, Caching and more. We will follow up this post with more pointers on performance tuning in Part – 2. A good list of areas is to check in the deployment guide for your version.
  • Thanks to Fabian Bouché David Nebinger and many more at Liferay Global Services / Support / Customer Success and Customer Support / Engineering due to which I am able to compile the above. Above is a compilation of work from many sources internally in Liferay via work with customers & externally which hopefully should help many of Liferay customers and partners. This also serves as a case study on performance tuning.
  • Email me: Neil@HarwaniSystems.in